Class: NMatrix

Inherits:
Object
  • Object
show all
Defined in:
lib/nmatrix/lapack_ext_common.rb,
lib/nmatrix/lapacke.rb

Overview

NMatrix

A linear algebra library for scientific computation in Ruby. NMatrix is part of SciRuby.

NMatrix was originally inspired by and derived from NArray, by Masahiro Tanaka: narray.rubyforge.org

Copyright Information

SciRuby is Copyright © 2010 - 2014, Ruby Science Foundation NMatrix is Copyright © 2012 - 2014, John Woods and the Ruby Science Foundation

Please see LICENSE.txt for additional copyright notices.

Contributing

By contributing source code to SciRuby, you agree to be bound by our Contributor Agreement:

lapack_ext_common.rb

Contains functions shared by nmatrix-atlas and nmatrix-lapacke gems. ++

Defined Under Namespace

Modules: BLAS, LAPACK

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.register_lapack_extension(name) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/nmatrix/lapack_ext_common.rb', line 30

def NMatrix.register_lapack_extension(name)
  if (defined? @@lapack_extension)
    raise "Attempting to load #{name} when #{@@lapack_extension} is already loaded. You can only load one LAPACK extension."
  end

  @@lapack_extension = name
end

Instance Method Details

#dot(right_v) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/nmatrix/lapack_ext_common.rb', line 40

def dot(right_v)
  if (right_v.is_a?(NMatrix) && self.stype == :dense && right_v.stype == :dense &&
      self.dim == 2 && right_v.dim == 2 && self.shape[1] == right_v.shape[0])

    result_dtype = NMatrix.upcast(self.dtype,right_v.dtype)
    left = self.dtype == result_dtype ? self : self.cast(dtype: result_dtype)
    right = right_v.dtype == result_dtype ? right_v : right_v.cast(dtype: result_dtype)

    left = left.clone if left.is_ref?
    right = right.clone if right.is_ref?

    result_m = left.shape[0]
    result_n = right.shape[1]
    left_n = left.shape[1]
    vector = result_n == 1
    result = NMatrix.new([result_m,result_n], dtype: result_dtype)

    if vector
      NMatrix::BLAS.cblas_gemv(false, result_m, left_n, 1, left, left_n, right, 1, 0, result, 1)
    else
      NMatrix::BLAS.cblas_gemm(:row, false, false, result_m, result_n, left_n, 1, left, left_n, right, result_n, 0, result, result_n)
    end
    return result
  else
    #internal_dot will handle non-dense matrices (and also dot-products for NMatrix's with dim=1),
    #and also all error-handling if the input is not valid
    self.internal_dot(right_v)
  end
end

#getrf!Object

Raises:

  • (StorageTypeError)


169
170
171
172
173
174
175
# File 'lib/nmatrix/lapacke.rb', line 169

def getrf!
  raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless self.dense?

  ipiv = NMatrix::LAPACK::lapacke_getrf(:row, self.shape[0], self.shape[1], self, self.shape[1])

  return ipiv
end

#internal_dotObject



38
# File 'lib/nmatrix/lapack_ext_common.rb', line 38

alias_method :internal_dot, :dot

#invert!Object

Raises:

  • (StorageTypeError)


177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/nmatrix/lapacke.rb', line 177

def invert!
  raise(StorageTypeError, "invert only works on dense matrices currently") unless self.dense?
  raise(ShapeError, "Cannot invert non-square matrix") unless shape[0] == shape[1]
  raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype?

  # Get the pivot array; factor the matrix
  n = self.shape[0]
  pivot = NMatrix::LAPACK::lapacke_getrf(:row, n, n, self, n)
  # Now calculate the inverse using the pivot array
  NMatrix::LAPACK::lapacke_getri(:row, n, self, n, pivot)

  self
end

#potrf!(which) ⇒ Object

Raises:

  • (StorageTypeError)


191
192
193
194
195
196
# File 'lib/nmatrix/lapacke.rb', line 191

def potrf!(which)
  raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless self.dense?
  raise(ShapeError, "Cholesky decomposition only valid for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1]

  NMatrix::LAPACK::lapacke_potrf(:row, which, self.shape[0], self, self.shape[1])
end

#solve(b) ⇒ Object

Raises:

  • (ShapeError)


198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/nmatrix/lapacke.rb', line 198

def solve b
  raise(ShapeError, "Must be called on square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1]
  raise(ShapeError, "number of rows of b must equal number of cols of self") if 
    self.shape[1] != b.shape[0]
  raise ArgumentError, "only works with dense matrices" if self.stype != :dense
  raise ArgumentError, "only works for non-integer, non-object dtypes" if 
    integer_dtype? or object_dtype? or b.integer_dtype? or b.object_dtype?

  x     = b.clone
  clone = self.clone
  n = self.shape[0]
  ipiv = NMatrix::LAPACK.lapacke_getrf(:row, n, n, clone, n)
  NMatrix::LAPACK.lapacke_getrs(:row, :no_transpose, n, b.shape[1], clone, n, ipiv, x, b.shape[1])
  x
end