Class: NMatrix
- Includes:
- Enumerable
- Defined in:
- lib/nmatrix/math.rb,
lib/nmatrix/lapack.rb,
lib/nmatrix/nmatrix.rb,
lib/nmatrix/version.rb,
lib/nmatrix/enumerate.rb,
lib/nmatrix/shortcuts.rb,
lib/nmatrix/homogeneous.rb,
lib/nmatrix/io/fortran_format.rb,
lib/nmatrix/io/harwell_boeing.rb,
ext/nmatrix/ruby_nmatrix.c
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:
io/matlab/fortran_format.rb
A parser for making sense of FORTRAN formats.
> Only handles R (real), F (float) and E (exponential) format codes.
++
Defined Under Namespace
Modules: BLAS, IO, LAPACK, NMMath, VERSION, YaleFunctions
Class Method Summary collapse
-
.[](*params) ⇒ Object
call-seq: NMatrix[Numeric, …, Numeric, dtype: Symbol] -> NMatrix NMatrix[Array, dtype: Symbol] -> NMatrix.
-
.diagonal(entries, opts = {}) ⇒ Object
(also: diag, diagonals)
call-seq: diagonals(array) -> NMatrix diagonals(array, dtype: dtype, stype: stype) -> NMatrix.
-
.eye(shape, opts = {}) ⇒ Object
(also: identity)
call-seq: eye(shape) -> NMatrix eye(shape, dtype: dtype) -> NMatrix eye(shape, stype: stype, dtype: dtype) -> NMatrix.
- .guess_dtype ⇒ Object
-
.load_matlab_file(file_path) ⇒ Object
call-seq: load_matlab_file(path) -> Mat5Reader.
-
.load_pcd_file(file_path) ⇒ Object
call-seq: load_pcd_file(path) -> PointCloudReader::MetaReader.
- .min_dtype ⇒ Object
-
.ones(shape, opts = {}) ⇒ Object
call-seq: ones(shape) -> NMatrix ones(shape, dtype: dtype, stype: stype) -> NMatrix.
-
.ones_like(nm) ⇒ NMatrix
call-seq: ones_like(nm) -> NMatrix.
-
.random(shape, opts = {}) ⇒ Object
(also: rand)
call-seq: random(shape) -> NMatrix.
- .read ⇒ Object
-
.seq(shape, options = {}) ⇒ Object
call-seq: seq(shape) -> NMatrix seq(shape, options) -> NMatrix bindgen(shape) -> NMatrix of :byte indgen(shape) -> NMatrix of :int64 findgen(shape) -> NMatrix of :float32 dindgen(shape) -> NMatrix of :float64 cindgen(shape) -> NMatrix of :complex64 zindgen(shape) -> NMatrix of :complex128 rindgen(shape) -> NMatrix of :rational128 rbindgen(shape) -> NMatrix of :object.
-
.size(shape) ⇒ Object
Calculate the size of an NMatrix of a given shape.
-
.translation(*args) ⇒ Object
call-seq: translation(x, y, z) -> NMatrix translation() -> NMatrix translation(translation_matrix) -> NMatrix translation(translation_matrix) -> NMatrix translation(translation, dtype: dtype) -> NMatrix translation(x, y, z, dtype: dtype) -> NMatrix.
-
.upcast ⇒ Object
Singleton methods.
-
.x_rotation(angle_in_radians, opts = {}) ⇒ Object
call-seq: x_rotation(angle_in_radians) -> NMatrix x_rotation(angle_in_radians, dtype: dtype) -> NMatrix y_rotation(angle_in_radians) -> NMatrix y_rotation(angle_in_radians, dtype: dtype) -> NMatrix z_rotation(angle_in_radians) -> NMatrix z_rotation(angle_in_radians, dtype: dtype) -> NMatrix.
- .y_rotation(angle_in_radians, opts = {}) ⇒ Object
- .z_rotation(angle_in_radians, opts = {}) ⇒ Object
-
.zeros(shape, opts = {}) ⇒ Object
(also: zeroes)
call-seq: zeros(shape) -> NMatrix zeros(shape, dtype: dtype) -> NMatrix zeros(shape, dtype: dtype, stype: stype) -> NMatrix.
-
.zeros_like(nm) ⇒ NMatrix
call-seq: zeros_like(nm) -> NMatrix.
Instance Method Summary collapse
- #!~ ⇒ Object
- #% ⇒ Object
- #* ⇒ Object
- #** ⇒ Object
- #+ ⇒ Object
- #- ⇒ Object
- #-@ ⇒ Object
- #/ ⇒ Object
- #< ⇒ Object
- #<= ⇒ Object
- #== ⇒ Object
- #=~ ⇒ Object
- #> ⇒ Object
- #>= ⇒ Object
- #[] ⇒ Object
- #[]= ⇒ Object
-
#__yale_ary__to_s(sym) ⇒ Object
:nodoc:.
-
#abs ⇒ Object
call-seq: abs -> NMatrix.
-
#abs_dtype ⇒ Object
call-seq: abs_dtype -> Symbol.
- #acos ⇒ Object
- #acosh ⇒ Object
-
#angle_vector ⇒ Object
call-seq: angle_vector -> [angle, about_vector].
- #asin ⇒ Object
- #asinh ⇒ Object
-
#asum(incx = 1, n = nil) ⇒ Object
(also: #absolute_sum)
call-seq: absolute_sum -> Numeric.
- #atan ⇒ Object
- #atan2 ⇒ Object
- #atanh ⇒ Object
-
#binned_sorted_indices ⇒ Object
call-seq: binned_sorted_indices -> Array.
- #capacity ⇒ Object
-
#cast(*params) ⇒ Object
call-seq: cast(stype, dtype, default) -> NMatrix cast(stype, dtype) -> NMatrix cast(stype) -> NMatrix cast(options) -> NMatrix.
- #cast_full ⇒ Object
- #cbrt ⇒ Object
- #ceil ⇒ Object
-
#clone_structure(capacity = nil) ⇒ Object
call-seq: clone_structure -> NMatrix.
-
#cols ⇒ Object
call-seq: cols -> Integer.
-
#column(column_number, get_by = :copy) ⇒ Object
(also: #col)
call-seq: column(column_number) -> NMatrix column(column_number, get_by) -> NMatrix.
-
#complex_conjugate(new_stype = self.stype) ⇒ Object
call-seq: complex_conjugate -> NMatrix complex_conjugate(new_stype) -> NMatrix.
- #complex_conjugate! ⇒ Object
-
#complex_dtype? ⇒ Boolean
call-seq: complex_dtype?() -> Boolean.
-
#concat(*matrices) ⇒ Object
call-seq: matrix1.concat(*m2) -> NMatrix matrix1.concat(*m2, rank) -> NMatrix matrix1.hconcat(*m2) -> NMatrix matrix1.vconcat(*m2) -> NMatrix matrix1.dconcat(*m3) -> NMatrix.
-
#conjugate_transpose ⇒ Object
call-seq: conjugate_transpose -> NMatrix.
- #cos ⇒ Object
- #cosh ⇒ Object
-
#data_pointer ⇒ Object
///////////////.
-
#dconcat(*matrices) ⇒ Object
Depth concatenation with
matrices
. - #default_value ⇒ Object
-
#dense? ⇒ Boolean
call-seq: m.dense? -> true or false.
-
#det ⇒ Object
call-seq: det -> determinant.
- #det_exact ⇒ Object
- #dimensions ⇒ Object (also: #dim)
-
#dot ⇒ Object
///////////////////////.
- #dtype ⇒ Object
-
#each(&bl) ⇒ Object
call-seq: each -> Enumerator.
-
#each_column(get_by = :reference) ⇒ Object
call-seq: each_column { |column| block } -> NMatrix.
-
#each_layer(get_by = :reference) ⇒ Object
call-seq: each_layer -> { |column| block } -> …
- #each_ordered_stored_with_indices ⇒ Object
-
#each_rank(dimen = 0, get_by = :reference) ⇒ Object
(also: #each_along_dim)
call-seq: each_rank() -> NMatrix each_rank() { |rank| block } -> NMatrix each_rank(dimen) -> Enumerator each_rank(dimen) { |rank| block } -> NMatrix.
-
#each_row(get_by = :reference) ⇒ Object
call-seq: each_row { |row| block } -> NMatrix.
-
#each_stored_with_index(&block) ⇒ Object
call-seq: each_stored_with_index -> Enumerator.
- #each_stored_with_indices ⇒ Object
- #each_with_indices ⇒ Object
- #effective_dimensions ⇒ Object (also: #effective_dim)
- #erf ⇒ Object
- #erfc ⇒ Object
- #exp ⇒ Object
-
#factorize_cholesky ⇒ Object
call-seq: factorize_cholesky -> …
-
#factorize_lu ⇒ Object
call-seq: factorize_lu -> …
-
#flat_map ⇒ Object
call-seq: flat_map -> Enumerator flat_map { |elem| block } -> Array.
- #floor ⇒ Object
- #gamma ⇒ Object
-
#gesdd(workspace_size = nil) ⇒ Object
call-seq: gesdd -> [u, sigma, v_transpose] gesdd -> [u, sigma, v_conjugate_transpose] # complex.
-
#gesdd!(workspace_size = nil) ⇒ Object
call-seq: gesdd! -> [u, sigma, v_transpose] gesdd! -> [u, sigma, v_conjugate_transpose] # complex.
-
#gesvd(workspace_size = 1) ⇒ Object
call-seq: gesvd -> [u, sigma, v_transpose] gesvd -> [u, sigma, v_conjugate_transpose] # complex.
-
#gesvd!(workspace_size = 1) ⇒ Object
call-seq: gesvd! -> [u, sigma, v_transpose] gesvd! -> [u, sigma, v_conjugate_transpose] # complex.
-
#getrf ⇒ Object
call-seq: getrf -> NMatrix.
-
#getrf! ⇒ Object
call-seq: getrf! -> NMatrix.
-
#hconcat(*matrices) ⇒ Object
Horizontal concatenation with
matrices
. -
#hermitian? ⇒ Boolean
call-seq: hermitian? -> Boolean.
- #hypot ⇒ Object
-
#initialize ⇒ Object
constructor
Forward Declarations.
- #initialize_copy ⇒ Object
-
#inject(sym) ⇒ Object
call-seq: inject -> symbol.
-
#inject_rank(dimen = 0, initial = nil, dtype = nil) ⇒ NMatrix
(also: #reduce_along_dim, #inject_along_dim)
call-seq: inject_rank() -> Enumerator inject_rank(dimen) -> Enumerator inject_rank(dimen, initial) -> Enumerator inject_rank(dimen, initial, dtype) -> Enumerator inject_rank() { |elem| block } -> NMatrix inject_rank(dimen) { |elem| block } -> NMatrix inject_rank(dimen, initial) { |elem| block } -> NMatrix inject_rank(dimen, initial, dtype) { |elem| block } -> NMatrix.
-
#inspect ⇒ Object
:nodoc:.
-
#integer_dtype? ⇒ Boolean
call-seq: integer_dtype?() -> Boolean.
-
#invert(lda = nil, ldb = nil) ⇒ Object
(also: #inverse)
call-seq: invert -> NMatrix.
-
#invert! ⇒ Object
call-seq: invert! -> NMatrix.
- #is_ref? ⇒ Boolean
-
#laswp(ary) ⇒ Object
(also: #permute_columns)
call-seq: laswp(ary) -> NMatrix.
-
#laswp!(ary) ⇒ Object
(also: #permute_columns!)
call-seq: laswp!(ary) -> NMatrix.
-
#layer(layer_number, get_by = :copy) ⇒ Object
call-seq: layer(layer_number) -> NMatrix row(layer_number, get_by) -> NMatrix.
- #ldexp ⇒ Object
-
#list? ⇒ Boolean
call-seq: m.list? -> true or false.
- #log ⇒ Object
- #log10 ⇒ Object
- #log2 ⇒ Object
-
#lower_triangle(k = 0) ⇒ Object
(also: #tril)
call-seq: lower_triangle -> NMatrix lower_triangle(k) -> NMatrix tril -> NMatrix tril(k) -> NMatrix.
-
#lower_triangle!(k = 0) ⇒ Object
(also: #tril!)
call-seq: lower_triangle! -> NMatrix lower_triangle!(k) -> NMatrix tril! -> NMatrix tril!(k) -> NMatrix.
-
#map(&bl) ⇒ Object
call-seq: map -> Enumerator map { |elem| block } -> NMatrix.
-
#map! ⇒ Object
call-seq: map! -> Enumerator map! { |elem| block } -> NMatrix.
- #map_stored ⇒ Object
-
#max(dimen = 0) ⇒ Object
call-seq: max() -> NMatrix max(dimen) -> NMatrix.
-
#mean(dimen = 0) ⇒ Object
call-seq: mean() -> NMatrix mean(dimen) -> NMatrix.
-
#method_missing(name, *args, &block) ⇒ Object
:nodoc:.
-
#min(dimen = 0) ⇒ Object
call-seq: min() -> NMatrix min(dimen) -> NMatrix.
-
#nrm2(incx = 1, n = nil) ⇒ Object
(also: #norm2)
call-seq: norm2 -> Numeric.
-
#nvector? ⇒ Boolean
call-seq: nvector? -> true or false.
- #offset ⇒ Object
-
#potrf!(which) ⇒ Object
call-seq: potrf!(upper_or_lower) -> NMatrix.
- #potrf_lower! ⇒ Object
- #potrf_upper! ⇒ Object
-
#pretty_print(q) ⇒ Object
TODO: Make this actually pretty.
-
#quaternion ⇒ Object
call-seq: quaternion -> NMatrix.
-
#rank(shape_idx, rank_idx, meth = :copy) ⇒ Object
call-seq: rank(dimension, row_or_column_number) -> NMatrix rank(dimension, row_or_column_number, :reference) -> NMatrix reference slice.
-
#rational_dtype? ⇒ Boolean
call-seq: complex_dtype?() -> Boolean.
-
#reshape(new_shape, *shapes) ⇒ Object
call-seq: reshape(new_shape) -> NMatrix.
-
#reshape!(new_shape, *shapes) ⇒ Object
call-seq: reshape!(new_shape) -> NMatrix reshape! new_shape -> NMatrix.
-
#respond_to?(method) ⇒ Boolean
:nodoc:.
- #round ⇒ Object
-
#row(row_number, get_by = :copy) ⇒ Object
call-seq: row(row_number) -> NMatrix row(row_number, get_by) -> NMatrix.
-
#rows ⇒ Object
call-seq: rows -> Integer.
-
#shape ⇒ Object
handles list and dense, which are n-dimensional.
-
#shuffle(*args) ⇒ Object
call-seq: shuffle -> …
-
#shuffle!(*args) ⇒ Object
call-seq: shuffle! -> …
- #sin ⇒ Object
- #sinh ⇒ Object
-
#size ⇒ Object
call-seq: size -> Fixnum.
- #slice ⇒ Object
-
#sorted_indices ⇒ Object
call-seq: sorted_indices -> Array.
- #sqrt ⇒ Object
-
#std(dimen = 0) ⇒ Object
call-seq: std() -> NMatrix std(dimen) -> NMatrix.
- #stype ⇒ Object
-
#sum(dimen = 0) ⇒ Object
call-seq: sum() -> NMatrix sum(dimen) -> NMatrix.
- #supershape ⇒ Object
- #symmetric? ⇒ Boolean
- #tan ⇒ Object
- #tanh ⇒ Object
-
#to_a(dimen = nil) ⇒ Object
call-seq: to_a -> Array.
-
#to_f ⇒ Object
call-seq: to_f -> Float.
-
#to_flat_array ⇒ Object
(also: #to_flat_a)
call-seq: to_flat_array -> Array to_flat_a -> Array.
-
#to_hash ⇒ Object
(also: #to_h)
call-seq: to_hash -> Hash.
-
#to_s ⇒ Object
:nodoc:.
-
#trace ⇒ Object
call-seq: trace -> Numeric.
-
#transpose(permute = nil) ⇒ Object
call-seq: transpose -> NMatrix transpose(permutation) -> NMatrix.
-
#upper_triangle(k = 0) ⇒ Object
(also: #triu)
call-seq: upper_triangle -> NMatrix upper_triangle(k) -> NMatrix triu -> NMatrix triu(k) -> NMatrix.
-
#upper_triangle!(k = 0) ⇒ Object
(also: #triu!)
call-seq: upper_triangle! -> NMatrix upper_triangle!(k) -> NMatrix triu! -> NMatrix triu!(k) -> NMatrix.
-
#variance(dimen = 0) ⇒ Object
call-seq: variance() -> NMatrix variance(dimen) -> NMatrix.
-
#vconcat(*matrices) ⇒ Object
Vertical concatenation with
matrices
. -
#vector? ⇒ Boolean
call-seq: vector? -> true or false.
- #write ⇒ Object
-
#yale? ⇒ Boolean
call-seq: m.yale? -> true or false.
Constructor Details
#initialize ⇒ Object
Forward Declarations
34 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 34
static VALUE nm_init(int argc, VALUE* argv, VALUE nm);
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
:nodoc:
824 825 826 827 828 829 830 831 832 |
# File 'lib/nmatrix/nmatrix.rb', line 824 def method_missing name, *args, &block #:nodoc: if name.to_s =~ /^__list_elementwise_.*__$/ raise NotImplementedError, "requested undefined list matrix element-wise operation" elsif name.to_s =~ /^__yale_scalar_.*__$/ raise NotImplementedError, "requested undefined yale scalar element-wise operation" else super(name, *args, &block) end end |
Class Method Details
.[](*params) ⇒ Object
call-seq:
NMatrix[Numeric, ..., Numeric, dtype: Symbol] -> NMatrix
NMatrix[Array, dtype: Symbol] -> NMatrix
The default value for dtype
is guessed from the first parameter. For example:
NMatrix[1.0, 2.0].dtype # => :float64
NMatrix[1r, 2r].dtype # => :rational64
But this is just a guess. If the other values can’t be converted to this dtype, a TypeError
will be raised.
You can use the N
constant in this way:
N = NMatrix
N[1, 2, 3]
NMatrix needs to have a succinct way to create a matrix by specifying the components directly. This is very useful for using it as an advanced calculator, it is useful for learning how to use, for testing language features and for developing algorithms.
The NMatrix::[] method provides a way to create a matrix in a way that is compact and natural. The components are specified using Ruby array syntax. Optionally, one can specify a dtype as the last parameter (default is :float64).
Examples:
a = N[ 1,2,3,4 ] => 1 2 3 4
a = N[ 1,2,3,4, :int32 ] => 1 2 3 4
a = N[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
3.0 4.0 5.0
a = N[ 3,6,9 ].transpose => 3
6
9
SYNTAX COMPARISON:
MATLAB: a = [ [1 2 3] ; [4 5 6] ] or [ 1 2 3 ; 4 5 6 ]
IDL: a = [ [1,2,3] , [4,5,6] ]
NumPy: a = array( [1,2,3], [4,5,6] )
SciRuby: a = NMatrix[ [1,2,3], [4,5,6] ]
Ruby array: a = [ [1,2,3], [4,5,6] ]
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/nmatrix/shortcuts.rb', line 101 def [](*params) = params.last.is_a?(Hash) ? params.pop : {} # First find the dimensions of the array. i = 0 shape = [] row = params while row.is_a?(Array) shape[i] = row.length row = row[0] i += 1 end # A row vector should be stored as 1xN, not N #shape.unshift(1) if shape.size == 1 # Then flatten the array. NMatrix.new(shape, params.flatten, ) end |
.diagonal(entries, opts = {}) ⇒ Object Also known as: diag, diagonals
call-seq:
diagonals(array) -> NMatrix
diagonals(array, dtype: dtype, stype: stype) -> NMatrix
Creates a matrix filled with specified diagonals.
-
Arguments :
-
entries
-> Array containing input values for diagonal matrix -
options
-> (optional) Hash with options for NMatrix#initialize
-
-
Returns :
-
NMatrix filled with specified diagonal values.
-
Examples:
NMatrix.diagonal([1.0,2,3,4]) # => 1.0 0.0 0.0 0.0
0.0 2.0 0.0 0.0
0.0 0.0 3.0 0.0
0.0 0.0 0.0 4.0
NMatrix.diagonal([1,2,3,4], dtype: :int32) # => 1 0 0 0
0 2 0 0
0 0 3 0
0 0 0 4
266 267 268 269 270 271 272 273 274 |
# File 'lib/nmatrix/shortcuts.rb', line 266 def diagonal(entries, opts={}) m = NMatrix.zeros(entries.size, {:dtype => guess_dtype(entries[0]), :capacity => entries.size + 1}.merge(opts) ) entries.each_with_index do |n, i| m[i,i] = n end m end |
.eye(shape, opts = {}) ⇒ Object Also known as: identity
call-seq:
eye(shape) -> NMatrix
eye(shape, dtype: dtype) -> NMatrix
eye(shape, stype: stype, dtype: dtype) -> NMatrix
Creates an identity matrix (square matrix rank 2).
-
Arguments :
-
size
-> Array (or integer for square matrix) specifying the dimensions. -
dtype
-> (optional) Default is:float64
-
stype
-> (optional) Default is:dense
.
-
-
Returns :
-
An identity matrix.
-
Examples:
NMatrix.eye(3) # => 1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
NMatrix.eye(3, dtype: :int32) # => 1 0 0
0 1 0
0 0 1
NMatrix.eye(2, dtype: :int32, stype: :yale) # => 1 0
0 1
230 231 232 233 234 235 236 237 238 |
# File 'lib/nmatrix/shortcuts.rb', line 230 def eye(shape, opts={}) # Fill the diagonal with 1's. m = NMatrix.zeros(shape, {:dtype => :float64}.merge(opts)) (0...m.shape[0]).each do |i| m[i, i] = 1 end m end |
.guess_dtype ⇒ Object
65 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 65
static VALUE nm_guess_dtype(VALUE self, VALUE v);
|
.load_matlab_file(file_path) ⇒ Object
call-seq:
load_matlab_file(path) -> Mat5Reader
-
Arguments :
-
file_path
-> The path to a version 5 .mat file.
-
-
Returns :
-
A Mat5Reader object.
-
73 74 75 |
# File 'lib/nmatrix/nmatrix.rb', line 73 def load_matlab_file(file_path) NMatrix::IO::Mat5Reader.new(File.open(file_path, 'rb')).to_ruby end |
.load_pcd_file(file_path) ⇒ Object
call-seq:
load_pcd_file(path) -> PointCloudReader::MetaReader
-
Arguments :
-
file_path
-> The path to a PCL PCD file.
-
-
Returns :
-
A PointCloudReader::MetaReader object with the matrix stored in its
matrix
property
-
84 85 86 |
# File 'lib/nmatrix/nmatrix.rb', line 84 def load_pcd_file(file_path) NMatrix::IO::PointCloudReader::MetaReader.new(file_path) end |
.min_dtype ⇒ Object
66 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 66
static VALUE nm_min_dtype(VALUE self, VALUE v);
|
.ones(shape, opts = {}) ⇒ Object
call-seq:
ones(shape) -> NMatrix
ones(shape, dtype: dtype, stype: stype) -> NMatrix
Creates a matrix filled with ones.
-
Arguments :
-
shape
-> Array (or integer for square matrix) specifying the shape. -
opts
-> (optional) Hash of options from NMatrix#initialize
-
-
Returns :
-
NMatrix filled with ones.
-
Examples:
NMatrix.ones([1, 3]) # => 1.0 1.0 1.0
NMatrix.ones([2, 3], dtype: :int32) # => 1 1 1
1 1 1
172 173 174 |
# File 'lib/nmatrix/shortcuts.rb', line 172 def ones(shape, opts={}) NMatrix.new(shape, 1, {:dtype => :float64, :default => 1}.merge(opts)) end |
.ones_like(nm) ⇒ NMatrix
call-seq:
ones_like(nm) -> NMatrix
Creates a new matrix of ones with the same dtype and shape as the provided matrix.
185 186 187 |
# File 'lib/nmatrix/shortcuts.rb', line 185 def ones_like(nm) NMatrix.ones(nm.shape, dtype: nm.dtype, stype: nm.stype, capacity: nm.capacity, default: 1) end |
.random(shape, opts = {}) ⇒ Object Also known as: rand
call-seq:
random(shape) -> NMatrix
Creates a :dense
NMatrix with random numbers between 0 and 1 generated by Random::rand
. The parameter is the dimension of the matrix.
If you use an integer dtype, make sure to specify :scale as a parameter, or you’ll only get a matrix of 0s. You may not currently generate random numbers for a rational matrix.
-
Arguments :
-
shape
-> Array (or integer for square matrix) specifying the dimensions.
-
-
Returns :
-
NMatrix filled with random values.
-
Examples:
NMatrix.random([2, 2]) # => 0.4859439730644226 0.1783195585012436
0.23193766176700592 0.4503345191478729
NMatrix.random([2, 2], :dtype => :byte, :scale => 255) # => [ [252, 108] [44, 12] ]
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/nmatrix/shortcuts.rb', line 302 def random(shape, opts={}) scale = opts.delete(:scale) || 1.0 raise(NotImplementedError, "does not support rational random number generation") if opts[:dtype].to_s =~ /^rational/ rng = Random.new random_values = [] # Construct the values of the final matrix based on the dimension. if opts[:dtype] == :complex64 || opts[:dtype] == :complex128 NMatrix.size(shape).times { |i| random_values << Complex(rng.rand(scale), rng.rand(scale)) } else NMatrix.size(shape).times { |i| random_values << rng.rand(scale) } end NMatrix.new(shape, random_values, {:dtype => :float64, :stype => :dense}.merge(opts)) end |
.read ⇒ Object
37 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 37
static VALUE nm_read(int argc, VALUE* argv, VALUE self);
|
.seq(shape, options = {}) ⇒ Object
call-seq:
seq(shape) -> NMatrix
seq(shape, options) -> NMatrix
bindgen(shape) -> NMatrix of :byte
indgen(shape) -> NMatrix of :int64
findgen(shape) -> NMatrix of :float32
dindgen(shape) -> NMatrix of :float64
cindgen(shape) -> NMatrix of :complex64
zindgen(shape) -> NMatrix of :complex128
rindgen(shape) -> NMatrix of :rational128
rbindgen(shape) -> NMatrix of :object
Creates a matrix filled with a sequence of integers starting at zero.
-
Arguments :
-
shape
-> Array (or integer for square matrix) specifying the dimensions. -
options
-> (optional) Options permissible for NMatrix#initialize
-
-
Returns :
-
NMatrix filled with values 0 through
size
.
-
Examples:
NMatrix.seq(2) # => 0 1
2 3
NMatrix.seq([3, 3], dtype: :float32) # => 0.0 1.0 2.0
3.0 4.0 5.0
6.0 7.0 8.0
353 354 355 356 357 358 359 360 |
# File 'lib/nmatrix/shortcuts.rb', line 353 def seq(shape, ={}) # Construct the values of the final matrix based on the dimension. values = (0 ... NMatrix.size(shape)).to_a # It'll produce :int32, except if a dtype is provided. NMatrix.new(shape, values, {:stype => :dense}.merge()) end |
.size(shape) ⇒ Object
Calculate the size of an NMatrix of a given shape.
89 90 91 92 |
# File 'lib/nmatrix/nmatrix.rb', line 89 def size(shape) shape = [shape,shape] unless shape.is_a?(Array) (0...shape.size).inject(1) { |x,i| x * shape[i] } end |
.translation(*args) ⇒ Object
call-seq:
translation(x, y, z) -> NMatrix
translation([x,y,z]) -> NMatrix
translation(translation_matrix) -> NMatrix
translation(translation_matrix) -> NMatrix
translation(translation, dtype: dtype) -> NMatrix
translation(x, y, z, dtype: dtype) -> NMatrix
Generate a 4x4 homogeneous transformation matrix representing a translation.
-
Returns :
-
A homogeneous transformation matrix consisting of a translation.
-
Examples:
NMatrix.translation(4.0,5.0,6.0) # =>
1.0 0.0 0.0 4.0
0.0 1.0 0.0 5.0
0.0 0.0 1.0 6.0
0.0 0.0 0.0 1.0
NMatrix.translation(4.0,5.0,6.0, dtype: :int64) # =>
1 0 0 4
0 1 0 5
0 0 1 6
0 0 0 1
NMatrix.translation(4,5,6) # =>
1 0 0 4
0 1 0 5
0 0 1 6
0 0 0 1
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/nmatrix/homogeneous.rb', line 127 def translation *args xyz = args.shift if args.first.is_a?(NMatrix) || args.first.is_a?(Array) default_dtype = xyz.respond_to?(:dtype) ? xyz.dtype : NMatrix.guess_dtype(xyz) opts = {dtype: default_dtype} opts = opts.merge(args.pop) if args.size > 0 && args.last.is_a?(Hash) xyz ||= args n = if args.size > 0 NMatrix.eye(4, opts) else NMatrix.eye(4, opts) end n[0..2,3] = xyz n end |
.upcast ⇒ Object
Singleton methods
170 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 170
static VALUE nm_upcast(VALUE self, VALUE t1, VALUE t2);
|
.x_rotation(angle_in_radians, opts = {}) ⇒ Object
call-seq:
x_rotation(angle_in_radians) -> NMatrix
x_rotation(angle_in_radians, dtype: dtype) -> NMatrix
y_rotation(angle_in_radians) -> NMatrix
y_rotation(angle_in_radians, dtype: dtype) -> NMatrix
z_rotation(angle_in_radians) -> NMatrix
z_rotation(angle_in_radians, dtype: dtype) -> NMatrix
Generate a 4x4 homogeneous transformation matrix representing a rotation about the x, y, or z axis respectively.
-
Arguments :
-
angle_in_radians
-> The angle of rotation in radians. -
dtype
-> (optional) Default is:float64
-
-
Returns :
-
A homogeneous transformation matrix consisting of a single rotation.
-
Examples:
NMatrix.x_rotation(Math::PI.quo(6)) # =>
1.0 0.0 0.0 0.0
0.0 0.866025 -0.499999 0.0
0.0 0.499999 0.866025 0.0
0.0 0.0 0.0 1.0
NMatrix.x_rotation(Math::PI.quo(6), dtype: :float32) # =>
1.0 0.0 0.0 0.0
0.0 0.866025 -0.5 0.0
0.0 0.5 0.866025 0.0
0.0 0.0 0.0 1.0
66 67 68 69 70 71 72 73 |
# File 'lib/nmatrix/homogeneous.rb', line 66 def x_rotation angle_in_radians, opts={} c = Math.cos(angle_in_radians) s = Math.sin(angle_in_radians) NMatrix.new(4, [1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c, 0.0, 0.0, 0.0, 0.0, 1.0], {dtype: :float64}.merge(opts)) end |
.y_rotation(angle_in_radians, opts = {}) ⇒ Object
75 76 77 78 79 80 81 82 |
# File 'lib/nmatrix/homogeneous.rb', line 75 def y_rotation angle_in_radians, opts={} c = Math.cos(angle_in_radians) s = Math.sin(angle_in_radians) NMatrix.new(4, [ c, 0.0, s, 0.0, 0.0, 1.0, 0.0, 0.0, -s, 0.0, c, 0.0, 0.0, 0.0, 0.0, 1.0], {dtype: :float64}.merge(opts)) end |
.z_rotation(angle_in_radians, opts = {}) ⇒ Object
84 85 86 87 88 89 90 91 |
# File 'lib/nmatrix/homogeneous.rb', line 84 def z_rotation angle_in_radians, opts={} c = Math.cos(angle_in_radians) s = Math.sin(angle_in_radians) NMatrix.new(4, [ c, -s, 0.0, 0.0, s, c, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0], {dtype: :float64}.merge(opts)) end |
.zeros(shape, opts = {}) ⇒ Object Also known as: zeroes
call-seq:
zeros(shape) -> NMatrix
zeros(shape, dtype: dtype) -> NMatrix
zeros(shape, dtype: dtype, stype: stype) -> NMatrix
Creates a new matrix of zeros with the dimensions supplied as parameters.
-
Arguments :
-
shape
-> Array (or integer for square matrix) specifying the dimensions. -
dtype
-> (optional) Default is:float64
-
stype
-> (optional) Default is:dense
.
-
-
Returns :
-
NMatrix filled with zeros.
-
Examples:
NMatrix.zeros(2) # => 0.0 0.0
0.0 0.0
NMatrix.zeros([2, 3], dtype: :int32) # => 0 0 0
0 0 0
NMatrix.zeros([1, 5], dtype: :int32) # => 0 0 0 0 0
147 148 149 |
# File 'lib/nmatrix/shortcuts.rb', line 147 def zeros(shape, opts = {}) NMatrix.new(shape, 0, {:dtype => :float64}.merge(opts)) end |
.zeros_like(nm) ⇒ NMatrix
call-seq:
zeros_like(nm) -> NMatrix
Creates a new matrix of zeros with the same stype, dtype, and shape as the provided matrix.
198 199 200 |
# File 'lib/nmatrix/shortcuts.rb', line 198 def zeros_like(nm) NMatrix.zeros(nm.shape, dtype: nm.dtype, stype: nm.stype, capacity: nm.capacity, default: 0) end |
Instance Method Details
#!~ ⇒ Object
#% ⇒ Object
#* ⇒ Object
#** ⇒ Object
#+ ⇒ Object
#- ⇒ Object
#-@ ⇒ Object
#/ ⇒ Object
#< ⇒ Object
#<= ⇒ Object
#== ⇒ Object
152 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 152
static VALUE nm_eqeq(VALUE left, VALUE right);
|
#=~ ⇒ Object
#> ⇒ Object
#>= ⇒ Object
#[] ⇒ Object
60 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 60
static VALUE nm_mref(int argc, VALUE* argv, VALUE self);
|
#[]= ⇒ Object
58 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 58
static VALUE nm_mset(int argc, VALUE* argv, VALUE self);
|
#__yale_ary__to_s(sym) ⇒ Object
:nodoc:
236 237 238 239 240 |
# File 'lib/nmatrix/nmatrix.rb', line 236 def __yale_ary__to_s(sym) #:nodoc: ary = self.send("__yale_#{sym.to_s}__".to_sym) '[' + ary.collect { |a| a ? a : 'nil'}.join(',') + ']' end |
#abs ⇒ Object
call-seq:
abs -> NMatrix
Maps all values in a matrix to their absolute values.
536 537 538 539 540 541 542 543 544 545 |
# File 'lib/nmatrix/math.rb', line 536 def abs if stype == :dense self.__dense_map__ { |v| v.abs } elsif stype == :list # FIXME: Need __list_map_stored__, but this will do for now. self.__list_map_merged_stored__(nil, nil) { |v,dummy| v.abs } else self.__yale_map_stored__ { |v| v.abs } end.cast(self.stype, abs_dtype) end |
#abs_dtype ⇒ Object
call-seq:
abs_dtype -> Symbol
Returns the dtype of the result of a call to #abs. In most cases, this is the same as dtype; it should only differ for :complex64 (where it’s :float32) and :complex128 (:float64).
520 521 522 523 524 525 526 527 528 |
# File 'lib/nmatrix/math.rb', line 520 def abs_dtype if self.dtype == :complex64 :float32 elsif self.dtype == :complex128 :float64 else self.dtype end end |
#acos ⇒ Object
#acosh ⇒ Object
#angle_vector ⇒ Object
call-seq:
angle_vector -> [angle, about_vector]
Find the angle vector for a quaternion. Assumes the quaternion has unit length.
Source: www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/
-
Returns :
-
An angle (in radians) describing the rotation about the
about_vector
. -
A length-3 NMatrix representing the corresponding quaternion.
-
Examples:
q.angle_vector # => [1, 0, 0, 0]
228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/nmatrix/homogeneous.rb', line 228 def angle_vector raise(ShapeError, "Expected length-4 vector or matrix (quaternion)") if self.shape[0] != 4 raise("Expected unit quaternion") if self[0] > 1 xyz = NMatrix.new([3], dtype: self.dtype) angle = 2 * Math.acos(self[0]) s = Math.sqrt(1.0 - self[0]*self[0]) xyz[0..2] = self[1..3] xyz /= s if s >= 0.001 # avoid divide by zero return [angle, xyz] end |
#asin ⇒ Object
#asinh ⇒ Object
#asum(incx = 1, n = nil) ⇒ Object Also known as: absolute_sum
call-seq:
absolute_sum -> Numeric
Arguments
- +incx+ -> the skip size (defaults to 1, no skip)
- +n+ -> the number of elements to include
Return the sum of the contents of the vector. This is the BLAS asum routine.
557 558 559 560 561 |
# File 'lib/nmatrix/math.rb', line 557 def asum incx=1, n=nil return self[0].abs if self.shape == [1] return method_missing(:asum, incx, n) unless vector? NMatrix::BLAS::asum(self, incx, self.size / incx) end |
#atan ⇒ Object
#atan2 ⇒ Object
#atanh ⇒ Object
#binned_sorted_indices ⇒ Object
call-seq:
binned_sorted_indices -> Array
Returns an array of arrays of indices ordered by value sorted. Functions basically like sorted_indices
, but groups indices together for those values that are the same.
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 |
# File 'lib/nmatrix/nmatrix.rb', line 807 def binned_sorted_indices return method_missing(:sorted_indices) unless vector? ary = self.to_flat_array ary2 = [] last_bin = ary.each_index.sort_by { |i| [ary[i]] }.inject([]) do |result, element| if result.empty? || ary[result[-1]] == ary[element] result << element else ary2 << result [element] end end ary2 << last_bin unless last_bin.empty? ary2 end |
#capacity ⇒ Object
50 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 50 static VALUE nm_capacity(VALUE self); |
#cast(*params) ⇒ Object
call-seq:
cast(stype, dtype, default) -> NMatrix
cast(stype, dtype) -> NMatrix
cast(stype) -> NMatrix
cast(options) -> NMatrix
This is a user-friendly helper for calling #cast_full. The easiest way to call this function is using an options hash, e.g.,
n.cast(:stype => :yale, :dtype => :int64, :default => false)
For list and yale, :default sets the “default value” or “init” of the matrix. List allows a bit more freedom since non-zeros are permitted. For yale, unpredictable behavior may result if the value is not false, nil, or some version of 0. Dense discards :default.
dtype and stype are inferred from the matrix upon which #cast is called – so you only really need to provide one. You can actually call this function with no arguments, in which case it functions like #clone.
If your dtype is :object and you are converting from :dense to a sparse type, it is recommended that you provide a :default, as 0 may behave differently from its Float, Rational, or Complex equivalent. If no option is given, Fixnum 0 will be used.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/nmatrix/nmatrix.rb', line 158 def cast(*params) if (params.size > 0 && params[0].is_a?(Hash)) opts = { :stype => self.stype, :dtype => self.dtype, :default => self.stype == :dense ? 0 : self.default_value }.merge(params[0]) self.cast_full(opts[:stype], opts[:dtype], opts[:default]) else params << self.stype if params.size == 0 params << self.dtype if params.size == 1 #HACK: the default value can cause an exception if dtype is not complex #and default_value is. (The ruby C code apparently won't convert these.) #Perhaps this should be fixed in the C code (in rubyval_to_cval). default_value = maybe_get_noncomplex_default_value(params[1]) params << (self.stype == :dense ? 0 : default_value) if params.size == 2 self.cast_full(*params) end end |
#cast_full ⇒ Object
#cbrt ⇒ Object
#ceil ⇒ Object
#clone_structure(capacity = nil) ⇒ Object
call-seq:
clone_structure -> NMatrix
This function is like clone, but it only copies the structure and the default value. None of the other values are copied. It takes an optional capacity argument. This is mostly only useful for dense, where you may not want to initialize; for other types, you should probably use zeros_like
.
867 868 869 870 871 |
# File 'lib/nmatrix/nmatrix.rb', line 867 def clone_structure(capacity = nil) opts = {stype: self.stype, default: self.default_value, dtype: self.dtype} opts = {capacity: capacity}.merge(opts) if self.yale? NMatrix.new(self.shape, opts) end |
#cols ⇒ Object
call-seq:
cols -> Integer
This shortcut use #shape to return the number of columns (the second dimension) of the matrix.
199 200 201 |
# File 'lib/nmatrix/nmatrix.rb', line 199 def cols shape[1] end |
#column(column_number, get_by = :copy) ⇒ Object Also known as: col
call-seq:
column(column_number) -> NMatrix
column(column_number, get_by) -> NMatrix
Returns the column specified. Uses slicing by copy as default.
-
Arguments :
-
column_number
-> Integer. -
get_by
-> Type of slicing to use,:copy
or:reference
.
-
-
Returns :
-
A NMatrix representing the requested column as a column vector.
-
Examples:
m = NMatrix.new(2, [1, 4, 9, 14], :int32) # => 1 4
9 14
m.column(1) # => 4
14
410 411 412 |
# File 'lib/nmatrix/nmatrix.rb', line 410 def column(column_number, get_by = :copy) rank(1, column_number, get_by) end |
#complex_conjugate(new_stype = self.stype) ⇒ Object
call-seq:
complex_conjugate -> NMatrix
complex_conjugate(new_stype) -> NMatrix
Get the complex conjugate of this matrix. See also complex_conjugate! for an in-place operation (provided the dtype is already :complex64
or :complex128
).
Doesn’t work on list matrices, but you can optionally pass in the stype you want to cast to if you’re dealing with a list matrix.
-
Arguments :
-
new_stype
-> stype for the new matrix.
-
-
Returns :
-
If the original NMatrix isn’t complex, the result is a
:complex128
NMatrix. Otherwise, it’s the original dtype.
-
341 342 343 |
# File 'lib/nmatrix/math.rb', line 341 def complex_conjugate(new_stype = self.stype) self.cast(new_stype, NMatrix::upcast(dtype, :complex64)).complex_conjugate! end |
#complex_conjugate! ⇒ Object
160 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 160 static VALUE nm_complex_conjugate_bang(VALUE self); |
#complex_dtype? ⇒ Boolean
call-seq:
complex_dtype?() -> Boolean
Checks if dtype is a complex type
258 259 260 |
# File 'lib/nmatrix/nmatrix.rb', line 258 def complex_dtype? [:complex64, :complex128].include?(self.dtype) end |
#concat(*matrices) ⇒ Object
call-seq:
matrix1.concat(*m2) -> NMatrix
matrix1.concat(*m2, rank) -> NMatrix
matrix1.hconcat(*m2) -> NMatrix
matrix1.vconcat(*m2) -> NMatrix
matrix1.dconcat(*m3) -> NMatrix
Joins two matrices together into a new larger matrix. Attempts to determine which direction to concatenate on by looking for the first common element of the matrix shape
in reverse. In other words, concatenating two columns together without supplying rank
will glue them into an n x 2 matrix.
You can also use hconcat, vconcat, and dconcat for the first three ranks. concat performs an hconcat when no rank argument is provided.
The two matrices must have the same dim
.
-
Arguments :
-
matrices
-> one or more matrices -
rank
-> Fixnum (for rank); alternatively, may use :row, :column, or
:layer for 0, 1, 2, respectively
-
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 |
# File 'lib/nmatrix/nmatrix.rb', line 556 def concat(*matrices) rank = nil rank = matrices.pop unless matrices.last.is_a?(NMatrix) # Find the first matching dimension and concatenate along that (unless rank is specified) if rank.nil? rank = self.dim-1 self.shape.reverse_each.with_index do |s,i| matrices.each do |m| if m.shape[i] != s rank -= 1 break end end end elsif rank.is_a?(Symbol) # Convert to numeric rank = {:row => 0, :column => 1, :col => 1, :lay => 2, :layer => 2}[rank] end # Need to figure out the new shape. new_shape = self.shape.dup new_shape[rank] = matrices.inject(self.shape[rank]) { |total,m| total + m.shape[rank] } # Now figure out the options for constructing the concatenated matrix. opts = {stype: self.stype, default: self.default_value, dtype: self.dtype} if self.yale? # We can generally predict the new capacity for Yale. Subtract out the number of rows # for each matrix being concatenated, and then add in the number of rows for the new # shape. That takes care of the diagonal. The rest of the capacity is represented by # the non-diagonal non-default values. new_cap = matrices.inject(self.capacity - self.shape[0]) do |total,m| total + m.capacity - m.shape[0] end - self.shape[0] + new_shape[0] opts = {capacity: new_cap}.merge(opts) end # Do the actual construction. n = NMatrix.new(new_shape, opts) # Figure out where to start and stop the concatenation. We'll use NMatrices instead of # Arrays because then we can do elementwise addition. ranges = self.shape.map.with_index { |s,i| 0...self.shape[i] } matrices.unshift(self) matrices.each do |m| n[*ranges] = m # move over by the requisite amount ranges[rank] = (ranges[rank].first + m.shape[rank])...(ranges[rank].last + m.shape[rank]) end n end |
#conjugate_transpose ⇒ Object
call-seq:
conjugate_transpose -> NMatrix
Calculate the conjugate transpose of a matrix. If your dtype is already complex, this should only require one copy (for the transpose).
-
Returns :
-
The conjugate transpose of the matrix as a copy.
-
355 356 357 |
# File 'lib/nmatrix/math.rb', line 355 def conjugate_transpose self.transpose.complex_conjugate! end |
#cos ⇒ Object
#cosh ⇒ Object
#data_pointer ⇒ Object
///////////////
68 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 68 static VALUE nm_data_pointer(VALUE self); |
#dconcat(*matrices) ⇒ Object
Depth concatenation with matrices
.
621 622 623 |
# File 'lib/nmatrix/nmatrix.rb', line 621 def dconcat(*matrices) concat(*matrices, :layer) end |
#default_value ⇒ Object
43 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 43 static VALUE nm_default_value(VALUE self); |
#dense? ⇒ Boolean
call-seq:
m.dense? -> true or false
Determine if m
is a dense matrix.
41 |
# File 'lib/nmatrix/shortcuts.rb', line 41 def dense?; return stype == :dense; end |
#det ⇒ Object
call-seq:
det -> determinant
Calculate the determinant by way of LU decomposition. This is accomplished using clapack_getrf, and then by summing the diagonal elements. There is a risk of underflow/overflow.
There are probably also more efficient ways to calculate the determinant. This method requires making a copy of the matrix, since clapack_getrf modifies its input.
For smaller matrices, you may be able to use #det_exact
.
This function is guaranteed to return the same type of data in the matrix upon which it is called. In other words, if you call it on a rational matrix, you’ll get a rational number back.
Integer matrices are converted to rational matrices for the purposes of performing the calculation, as xGETRF can’t work on integer matrices.
-
Returns :
-
The determinant of the matrix. It’s the same type as the matrix’s dtype.
-
-
Raises :
-
NotImplementedError
-> Must be used in 2D matrices.
-
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/nmatrix/math.rb', line 304 def det raise(NotImplementedError, "determinant can be calculated only for 2D matrices") unless self.dim == 2 # Cast to a dtype for which getrf is implemented new_dtype = [:byte,:int8,:int16,:int32,:int64].include?(self.dtype) ? :rational128 : self.dtype copy = self.cast(:dense, new_dtype) # Need to know the number of permutations. We'll add up the diagonals of # the factorized matrix. pivot = copy.getrf! prod = pivot.size % 2 == 1 ? -1 : 1 # odd permutations => negative [shape[0],shape[1]].min.times do |i| prod *= copy[i,i] end # Convert back to an integer if necessary new_dtype != self.dtype ? prod.to_i : prod end |
#det_exact ⇒ Object
157 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 157 static VALUE nm_det_exact(VALUE self); |
#dimensions ⇒ Object Also known as: dim
46 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 46 static VALUE nm_dim(VALUE self); |
#dot ⇒ Object
///////////////////////
156 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 156
static VALUE nm_multiply(VALUE left_v, VALUE right_v);
|
#dtype ⇒ Object
41 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 41 static VALUE nm_dtype(VALUE self); |
#each(&bl) ⇒ Object
call-seq:
each -> Enumerator
Enumerate through the matrix. @see Enumerable#each
For dense, this actually calls a specialized each iterator (in C). For yale and list, it relies upon #each_with_indices (which is about as fast as reasonably possible for C code).
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/nmatrix/enumerate.rb', line 40 def each &bl if self.stype == :dense self.__dense_each__(&bl) elsif block_given? self.each_with_indices(&bl) else # Handle case where no block is given Enumerator.new do |yielder| self.each_with_indices do |params| yielder.yield params end end end end |
#each_column(get_by = :reference) ⇒ Object
call-seq:
each_column { |column| block } -> NMatrix
Iterate through each column, referencing it as an NMatrix slice.
144 145 146 147 148 149 150 |
# File 'lib/nmatrix/enumerate.rb', line 144 def each_column(get_by=:reference) return enum_for(:each_column, get_by) unless block_given? (0...self.shape[1]).each do |j| yield self.column(j, get_by) end self end |
#each_layer(get_by = :reference) ⇒ Object
call-seq:
each_layer -> { |column| block } -> ...
Iterate through each layer, referencing it as an NMatrix slice.
Note: If you have a 3-dimensional matrix, the first dimension contains rows, the second contains columns, and the third contains layers.
160 161 162 163 164 165 166 |
# File 'lib/nmatrix/enumerate.rb', line 160 def each_layer(get_by=:reference) return enum_for(:each_layer, get_by) unless block_given? (0...self.shape[2]).each do |k| yield self.layer(k, get_by) end self end |
#each_ordered_stored_with_indices ⇒ Object
53 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 53 static VALUE nm_each_ordered_stored_with_indices(VALUE nmatrix); |
#each_rank(dimen = 0, get_by = :reference) ⇒ Object Also known as: each_along_dim
call-seq:
each_rank() -> NMatrix
each_rank() { |rank| block } -> NMatrix
each_rank(dimen) -> Enumerator
each_rank(dimen) { |rank| block } -> NMatrix
Generic for @each_row, @each_col
Iterate through each rank by reference.
117 118 119 120 121 122 123 |
# File 'lib/nmatrix/enumerate.rb', line 117 def each_rank(dimen=0, get_by=:reference) return enum_for(:each_rank, dimen, get_by) unless block_given? (0...self.shape[dimen]).each do |idx| yield self.rank(dimen, idx, get_by) end self end |
#each_row(get_by = :reference) ⇒ Object
call-seq:
each_row { |row| block } -> NMatrix
Iterate through each row, referencing it as an NMatrix slice.
131 132 133 134 135 136 137 |
# File 'lib/nmatrix/enumerate.rb', line 131 def each_row(get_by=:reference) return enum_for(:each_row, get_by) unless block_given? (0...self.shape[0]).each do |i| yield self.row(i, get_by) end self end |
#each_stored_with_index(&block) ⇒ Object
call-seq:
each_stored_with_index -> Enumerator
Allow iteration across a vector NMatrix’s stored values. See also @each_stored_with_indices
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/nmatrix/enumerate.rb', line 175 def each_stored_with_index(&block) raise(NotImplementedError, "only works for dim 2 vectors") unless self.dim <= 2 return enum_for(:each_stored_with_index) unless block_given? self.each_stored_with_indices do |v, i, j| if shape[0] == 1 yield(v,j) elsif shape[1] == 1 yield(v,i) else method_missing(:each_stored_with_index, &block) end end self end |
#each_stored_with_indices ⇒ Object
52 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 52 static VALUE nm_each_stored_with_indices(VALUE nmatrix); |
#each_with_indices ⇒ Object
51 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 51 static VALUE nm_each_with_indices(VALUE nmatrix); |
#effective_dimensions ⇒ Object Also known as: effective_dim
45 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 45 static VALUE nm_effective_dim(VALUE self); |
#erf ⇒ Object
#erfc ⇒ Object
#exp ⇒ Object
#factorize_cholesky ⇒ Object
call-seq:
factorize_cholesky -> ...
Cholesky factorization of a matrix.
174 175 176 177 |
# File 'lib/nmatrix/math.rb', line 174 def factorize_cholesky [self.clone.potrf_upper!.triu!, self.clone.potrf_lower!.tril!] end |
#factorize_lu ⇒ Object
call-seq:
factorize_lu -> ...
LU factorization of a matrix.
FIXME: For some reason, getrf seems to require that the matrix be transposed first – and then you have to transpose the FIXME: result again. Ideally, this would be an in-place factorize instead, and would be called nm_factorize_lu_bang.
188 189 190 191 192 193 194 195 |
# File 'lib/nmatrix/math.rb', line 188 def factorize_lu raise(NotImplementedError, "only implemented for dense storage") unless self.stype == :dense raise(NotImplementedError, "matrix is not 2-dimensional") unless self.dimensions == 2 t = self.transpose NMatrix::LAPACK::clapack_getrf(:row, t.shape[0], t.shape[1], t, t.shape[1]) t.transpose end |
#flat_map ⇒ Object
call-seq:
flat_map -> Enumerator
flat_map { |elem| block } -> Array
Maps using Enumerator (returns an Array or an Enumerator)
60 |
# File 'lib/nmatrix/enumerate.rb', line 60 alias_method :flat_map, :map |
#floor ⇒ Object
#gamma ⇒ Object
#gesdd(workspace_size = nil) ⇒ Object
call-seq:
gesdd -> [u, sigma, v_transpose]
gesdd -> [u, sigma, v_conjugate_transpose] # complex
Compute the singular value decomposition of a matrix using LAPACK’s GESDD function. This uses a divide-and-conquer strategy. See also #gesvd.
Optionally accepts a workspace_size
parameter, which will be honored only if it is larger than what LAPACK requires.
254 255 256 |
# File 'lib/nmatrix/math.rb', line 254 def gesdd(workspace_size=nil) self.clone.gesdd!(workspace_size) end |
#gesdd!(workspace_size = nil) ⇒ Object
call-seq:
gesdd! -> [u, sigma, v_transpose]
gesdd! -> [u, sigma, v_conjugate_transpose] # complex
Compute the singular value decomposition of a matrix using LAPACK’s GESDD function. This uses a divide-and-conquer strategy. This is destructive, modifying the source NMatrix. See also #gesvd.
Optionally accepts a workspace_size
parameter, which will be honored only if it is larger than what LAPACK requires.
239 240 241 |
# File 'lib/nmatrix/math.rb', line 239 def gesdd!(workspace_size=nil) NMatrix::LAPACK::gesdd(self, workspace_size) end |
#gesvd(workspace_size = 1) ⇒ Object
call-seq:
gesvd -> [u, sigma, v_transpose]
gesvd -> [u, sigma, v_conjugate_transpose] # complex
Compute the singular value decomposition of a matrix using LAPACK’s GESVD function.
Optionally accepts a workspace_size
parameter, which will be honored only if it is larger than what LAPACK requires.
222 223 224 |
# File 'lib/nmatrix/math.rb', line 222 def gesvd(workspace_size=1) self.clone.gesvd!(workspace_size) end |
#gesvd!(workspace_size = 1) ⇒ Object
call-seq:
gesvd! -> [u, sigma, v_transpose]
gesvd! -> [u, sigma, v_conjugate_transpose] # complex
Compute the singular value decomposition of a matrix using LAPACK’s GESVD function. This is destructive, modifying the source NMatrix. See also #gesdd.
Optionally accepts a workspace_size
parameter, which will be honored only if it is larger than what LAPACK requires.
208 209 210 |
# File 'lib/nmatrix/math.rb', line 208 def gesvd!(workspace_size=1) NMatrix::LAPACK::gesvd(self, workspace_size) end |
#getrf ⇒ Object
call-seq:
getrf -> NMatrix
In-place version of #getrf!. Returns the new matrix, which contains L and U matrices.
-
Raises :
-
StorageTypeError
-> ATLAS functions only work on dense matrices.
-
133 134 135 136 137 |
# File 'lib/nmatrix/math.rb', line 133 def getrf a = self.clone a.getrf! return a end |
#getrf! ⇒ Object
call-seq:
getrf! -> NMatrix
LU factorization of a general M-by-N matrix A
using partial pivoting with row interchanges. Only works in dense matrices.
-
Returns :
-
The IPIV vector. The L and U matrices are stored in A.
-
-
Raises :
-
StorageTypeError
-> ATLAS functions only work on dense matrices.
-
118 119 120 121 |
# File 'lib/nmatrix/math.rb', line 118 def getrf! raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense? NMatrix::LAPACK::clapack_getrf(:row, self.shape[0], self.shape[1], self, self.shape[1]) end |
#hconcat(*matrices) ⇒ Object
Horizontal concatenation with matrices
.
611 612 613 |
# File 'lib/nmatrix/nmatrix.rb', line 611 def hconcat(*matrices) concat(*matrices, :column) end |
#hermitian? ⇒ Boolean
call-seq:
hermitian? -> Boolean
A hermitian matrix is a complex square matrix that is equal to its conjugate transpose. (en.wikipedia.org/wiki/Hermitian_matrix)
-
Returns :
-
True if
self
is a hermitian matrix, nil otherwise.
-
369 370 371 372 373 374 375 376 377 378 |
# File 'lib/nmatrix/math.rb', line 369 def hermitian? return false if self.dim != 2 or self.shape[0] != self.shape[1] if [:complex64, :complex128].include?(self.dtype) # TODO: Write much faster Hermitian test in C self.eql?(self.conjugate_transpose) else symmetric? end end |
#hypot ⇒ Object
#initialize_copy ⇒ Object
35 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 35
static VALUE nm_init_copy(VALUE copy, VALUE original);
|
#inject(sym) ⇒ Object
call-seq:
inject -> symbol
This overrides the inject function to use map_stored for yale matrices
852 853 854 855 |
# File 'lib/nmatrix/nmatrix.rb', line 852 def inject(sym) return super(sym) unless self.yale? return self.map_stored.inject(sym) end |
#inject_rank(dimen = 0, initial = nil, dtype = nil) ⇒ NMatrix Also known as: reduce_along_dim, inject_along_dim
call-seq:
inject_rank() -> Enumerator
inject_rank(dimen) -> Enumerator
inject_rank(dimen, initial) -> Enumerator
inject_rank(dimen, initial, dtype) -> Enumerator
inject_rank() { |elem| block } -> NMatrix
inject_rank(dimen) { |elem| block } -> NMatrix
inject_rank(dimen, initial) { |elem| block } -> NMatrix
inject_rank(dimen, initial, dtype) { |elem| block } -> NMatrix
Reduces an NMatrix using a supplied block over a specified dimension. The block should behave the same way as for Enumerable#reduce.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/nmatrix/enumerate.rb', line 217 def inject_rank(dimen=0, initial=nil, dtype=nil) raise(RangeError, "requested dimension (#{dimen}) does not exist (shape: #{shape})") if dimen > self.dim return enum_for(:inject_rank, dimen, initial, dtype) unless block_given? new_shape = shape new_shape[dimen] = 1 first_as_acc = false if initial then acc = NMatrix.new(new_shape, initial, :dtype => dtype || self.dtype, stype: self.stype) else each_rank(dimen) do |sub_mat| acc = (sub_mat.is_a?(NMatrix) and !dtype.nil? and dtype != self.dtype) ? sub_mat.cast(self.stype, dtype) : sub_mat break end first_as_acc = true end each_rank(dimen) do |sub_mat| if first_as_acc first_as_acc = false next end acc = yield(acc, sub_mat) end acc end |
#inspect ⇒ Object
:nodoc:
230 231 232 233 234 |
# File 'lib/nmatrix/nmatrix.rb', line 230 def inspect #:nodoc: original_inspect = super() original_inspect = original_inspect[0...original_inspect.size-1] original_inspect + " " + inspect_helper.join(" ") + ">" end |
#integer_dtype? ⇒ Boolean
call-seq:
integer_dtype?() -> Boolean
Checks if dtype is an integer type
248 249 250 |
# File 'lib/nmatrix/nmatrix.rb', line 248 def integer_dtype? [:byte, :int8, :int16, :int32, :int64].include?(self.dtype) end |
#invert(lda = nil, ldb = nil) ⇒ Object Also known as: inverse
call-seq:
invert -> NMatrix
Make a copy of the matrix, then invert using Gauss-Jordan elimination. Works without LAPACK.
-
Returns :
-
A dense NMatrix.
-
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/nmatrix/math.rb', line 77 def invert lda=nil, ldb=nil if lda.nil? and ldb.nil? if NMatrix.has_clapack? begin self.cast(:dense, self.dtype).invert! # call CLAPACK version rescue NotImplementedError # probably a rational matrix inverse = self.clone __inverse__(inverse, false) end elsif self.integer_dtype? # FIXME: This check is probably too slow. rational_self = self.cast(dtype: :rational128) inverse = rational_self.clone rational_self.__inverse__(inverse, false) else inverse = self.clone __inverse__(inverse, false) end else inverse = self.clone_structure if self.integer_dtype? __inverse_exact__(inverse.cast(dtype: :rational128), lda, ldb) else dtype = self.dtype __inverse_exact__(inverse, lda, ldb) end end end |
#invert! ⇒ Object
call-seq:
invert! -> NMatrix
Use LAPACK to calculate the inverse of the matrix (in-place) if available. Only works on dense matrices. Alternatively uses in-place Gauss-Jordan elimination.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/nmatrix/math.rb', line 47 def invert! if NMatrix.has_clapack? # Get the pivot array; factor the matrix pivot = self.getrf! # Now calculate the inverse using the pivot array NMatrix::LAPACK::clapack_getri(:row, self.shape[1], self, self.shape[1], pivot) self else if self.integer_dtype? __inverse__(self.cast(dtype: :rational128), true) else dtype = self.dtype __inverse__(self, true) end end end |
#is_ref? ⇒ Boolean
61 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 61 static VALUE nm_is_ref(VALUE self); |
#laswp(ary) ⇒ Object Also known as: permute_columns
call-seq:
laswp(ary) -> NMatrix
Permute the columns of a dense matrix using LASWP according to the order given in an Array ary
. Not yet implemented for yale or list.
273 274 275 |
# File 'lib/nmatrix/math.rb', line 273 def laswp(ary) self.clone.laswp!(ary) end |
#laswp!(ary) ⇒ Object Also known as: permute_columns!
call-seq:
laswp!(ary) -> NMatrix
In-place permute the columns of a dense matrix using LASWP according to the order given in an Array ary
. Not yet implemented for yale or list.
263 264 265 |
# File 'lib/nmatrix/math.rb', line 263 def laswp!(ary) NMatrix::LAPACK::laswp(self, ary) end |
#layer(layer_number, get_by = :copy) ⇒ Object
call-seq:
layer(layer_number) -> NMatrix
row(layer_number, get_by) -> NMatrix
-
Arguments :
-
layer_number
-> Integer. -
get_by
-> Type of slicing to use,:copy
or:reference
.
-
-
Returns :
-
A NMatrix representing the requested layer as a layer vector.
-
747 748 749 |
# File 'lib/nmatrix/nmatrix.rb', line 747 def layer(layer_number, get_by = :copy) rank(2, layer_number, get_by) end |
#ldexp ⇒ Object
#list? ⇒ Boolean
call-seq:
m.list? -> true or false
Determine if m
is a list-of-lists matrix.
53 |
# File 'lib/nmatrix/shortcuts.rb', line 53 def list?; return stype == :list; end |
#log ⇒ Object
#log10 ⇒ Object
#log2 ⇒ Object
#lower_triangle(k = 0) ⇒ Object Also known as: tril
call-seq:
lower_triangle -> NMatrix
lower_triangle(k) -> NMatrix
tril -> NMatrix
tril(k) -> NMatrix
Returns the lower triangular portion of a matrix. This is analogous to the tril
method in MATLAB.
-
Arguments :
-
k
-> Integer. How many extra diagonals to include in the lower triangular portion.
-
694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
# File 'lib/nmatrix/nmatrix.rb', line 694 def lower_triangle(k = 0) raise(NotImplementedError, "only implemented for 2D matrices") if self.shape.size > 2 t = self.clone_structure (0...self.shape[0]).each do |i| if i + k >= shape[0] t[i, :*] = self[i, :*] else t[i, (i+k+1)...self.shape[1]] = 0 t[i, 0..(i+k)] = self[i, 0..(i+k)] end end t end |
#lower_triangle!(k = 0) ⇒ Object Also known as: tril!
call-seq:
lower_triangle! -> NMatrix
lower_triangle!(k) -> NMatrix
tril! -> NMatrix
tril!(k) -> NMatrix
Deletes the upper triangular portion of the matrix (in-place) so only the lower portion remains.
-
Arguments :
-
k
-> Integer. How many extra diagonals to include in the deletion.
-
723 724 725 726 727 728 729 730 731 732 |
# File 'lib/nmatrix/nmatrix.rb', line 723 def lower_triangle!(k = 0) raise(NotImplementedError, "only implemented for 2D matrices") if self.shape.size > 2 (0...self.shape[0]).each do |i| if i + k < shape[0] self[i, (i+k+1)...self.shape[1]] = 0 end end self end |
#map(&bl) ⇒ Object
call-seq:
map -> Enumerator
map { |elem| block } -> NMatrix
Returns an NMatrix if a block is given. For an Array, use #flat_map
Note that #map will always return an :object matrix, because it has no way of knowing how to handle operations on the different dtypes.
72 73 74 75 76 77 |
# File 'lib/nmatrix/enumerate.rb', line 72 def map(&bl) return enum_for(:map) unless block_given? cp = self.cast(dtype: :object) cp.map!(&bl) cp end |
#map! ⇒ Object
call-seq:
map! -> Enumerator
map! { |elem| block } -> NMatrix
Maps in place.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/nmatrix/enumerate.rb', line 87 def map! return enum_for(:map!) unless block_given? iterated = false self.each_stored_with_indices do |e, *i| iterated = true self[*i] = (yield e) end #HACK: if there's a single element in a non-dense matrix, it won't iterate and #won't change the default value; this ensures that it does get changed. unless iterated then self.each_with_indices do |e, *i| self[*i] = (yield e) end end end |
#map_stored ⇒ Object
54 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 54 static VALUE nm_map_stored(VALUE nmatrix); |
#max(dimen = 0) ⇒ Object
call-seq:
max() -> NMatrix
max(dimen) -> NMatrix
Calculates the maximum along the specified dimension.
464 465 466 467 468 469 470 471 472 |
# File 'lib/nmatrix/math.rb', line 464 def max(dimen=0) inject_rank(dimen) do |max, sub_mat| if max.is_a? NMatrix then max * (max >= sub_mat).cast(self.stype, self.dtype) + ((max)*0.0 + (max < sub_mat).cast(self.stype, self.dtype)) * sub_mat else max >= sub_mat ? max : sub_mat end end end |
#mean(dimen = 0) ⇒ Object
call-seq:
mean() -> NMatrix
mean(dimen) -> NMatrix
Calculates the mean along the specified dimension.
This will force integer types to float64 dtype.
411 412 413 414 415 416 417 418 419 |
# File 'lib/nmatrix/math.rb', line 411 def mean(dimen=0) reduce_dtype = nil if integer_dtype? then reduce_dtype = :float64 end inject_rank(dimen, 0.0, reduce_dtype) do |mean, sub_mat| mean + sub_mat end / shape[dimen] end |
#min(dimen = 0) ⇒ Object
call-seq:
min() -> NMatrix
min(dimen) -> NMatrix
Calculates the minimum along the specified dimension.
445 446 447 448 449 450 451 452 453 |
# File 'lib/nmatrix/math.rb', line 445 def min(dimen=0) inject_rank(dimen) do |min, sub_mat| if min.is_a? NMatrix then min * (min <= sub_mat).cast(self.stype, self.dtype) + ((min)*0.0 + (min > sub_mat).cast(self.stype, self.dtype)) * sub_mat else min <= sub_mat ? min : sub_mat end end end |
#nrm2(incx = 1, n = nil) ⇒ Object Also known as: norm2
call-seq:
norm2 -> Numeric
Arguments
- +incx+ -> the skip size (defaults to 1, no skip)
- +n+ -> the number of elements to include
Return the 2-norm of the vector. This is the BLAS nrm2 routine.
573 574 575 576 |
# File 'lib/nmatrix/math.rb', line 573 def nrm2 incx=1, n=nil return method_missing(:nrm2, incx, n) unless vector? NMatrix::BLAS::nrm2(self, incx, self.size / incx) end |
#nvector? ⇒ Boolean
call-seq:
nvector? -> true or false
Shortcut function for determining whether the effective dimension is less than the dimension. Useful when we take slices of n-dimensional matrices where n > 2.
323 324 325 |
# File 'lib/nmatrix/nmatrix.rb', line 323 def nvector? self.effective_dim < self.dim end |
#offset ⇒ Object
47 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 47 static VALUE nm_offset(VALUE self); |
#potrf!(which) ⇒ Object
call-seq:
potrf!(upper_or_lower) -> NMatrix
Cholesky factorization of a symmetric positive-definite matrix – or, if complex, a Hermitian positive-definite matrix A
. This uses the ATLAS function clapack_potrf, so the result will be written in either the upper or lower triangular portion of the matrix upon which it is called.
-
Returns : the triangular portion specified by the parameter
-
Raises :
-
StorageTypeError
-> ATLAS functions only work on dense matrices.
-
154 155 156 157 158 |
# File 'lib/nmatrix/math.rb', line 154 def potrf!(which) raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense? # FIXME: Surely there's an easy way to calculate one of these from the other. Do we really need to run twice? NMatrix::LAPACK::clapack_potrf(:row, which, self.shape[0], self, self.shape[1]) end |
#potrf_lower! ⇒ Object
164 165 166 |
# File 'lib/nmatrix/math.rb', line 164 def potrf_lower! potrf! :lower end |
#potrf_upper! ⇒ Object
160 161 162 |
# File 'lib/nmatrix/math.rb', line 160 def potrf_upper! potrf! :upper end |
#pretty_print(q) ⇒ Object
TODO: Make this actually pretty.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/nmatrix/nmatrix.rb', line 96 def pretty_print(q) #:nodoc: if self.shape.size > 1 and self.shape[1] > 100 self.inspect.pretty_print(q) elsif self.dim > 3 || self.dim == 1 self.to_a.pretty_print(q) else # iterate through the whole matrix and find the longest number longest = Array.new(self.shape[1], 0) self.each_column.with_index do |col, j| col.each do |elem| elem_len = elem.inspect.size longest[j] = elem_len if longest[j] < elem_len end end if self.dim == 3 q.group(0, "\n{ layers:", "}") do self.each_layer.with_index do |layer,k| q.group(0, "\n [\n", " ]\n") do layer.each_row.with_index do |row,i| q.group(0, " [", "]\n") do q.seplist(self[i,0...self.shape[1],k].to_flat_array, lambda { q.text ", "}, :each_with_index) { |v,j| q.text v.inspect.rjust(longest[j]) } end end end end end else # dim 2 q.group(0, "\n[\n", "]") do self.each_row.with_index do |row,i| q.group(1, " [", "]") do q.seplist(self.dim > 2 ? row.to_a[0] : row.to_a, lambda { q.text ", " }, :each_with_index) { |v,j| q.text v.inspect.rjust(longest[j]) } end q.breakable end end end end end |
#quaternion ⇒ Object
call-seq:
quaternion -> NMatrix
Find the quaternion for a 3D rotation matrix.
Code borrowed from: courses.cms.caltech.edu/cs171/quatut.pdf
-
Returns :
-
A length-4 NMatrix representing the corresponding quaternion.
-
Examples:
n.quaternion # => [1, 0, 0, 0]
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/nmatrix/homogeneous.rb', line 159 def quaternion raise(ShapeError, "Expected square matrix") if self.shape[0] != self.shape[1] raise(ShapeError, "Expected 3x3 rotation (or 4x4 homogeneous) matrix") if self.shape[0] > 4 || self.shape[0] < 3 q = NMatrix.new([4], dtype: self.dtype == :float32 ? :float32: :float64) rotation_trace = self[0,0] + self[1,1] + self[2,2] if rotation_trace >= 0 self_w = self.shape[0] == 4 ? self[3,3] : 1.0 root_of_homogeneous_trace = Math.sqrt(rotation_trace + self_w) q[0] = root_of_homogeneous_trace * 0.5 s = 0.5 / root_of_homogeneous_trace q[1] = (self[2,1] - self[1,2]) * s q[2] = (self[0,2] - self[2,0]) * s q[3] = (self[1,0] - self[0,1]) * s else h = 0 h = 1 if self[1,1] > self[0,0] h = 2 if self[2,2] > self[h,h] case_macro = Proc.new do |i,j,k,ii,jj,kk| qq = NMatrix.new([4], dtype: :float64) self_w = self.shape[0] == 4 ? self[3,3] : 1.0 s = Math.sqrt( (self[ii,ii] - (self[jj,jj] + self[kk,kk])) + self_w) qq[i] = s*0.5 s = 0.5 / s qq[j] = (self[ii,jj] + self[jj,ii]) * s qq[k] = (self[kk,ii] + self[ii,kk]) * s qq[0] = (self[kk,jj] - self[jj,kk]) * s qq end case h when 0 q = case_macro.call(1,2,3, 0,1,2) when 1 q = case_macro.call(2,3,1, 1,2,0) when 2 q = case_macro.call(3,1,2, 2,0,1) end self_w = self.shape[0] == 4 ? self[3,3] : 1.0 if self_w != 1 s = 1.0 / Math.sqrt(self_w) q[0] *= s q[1] *= s q[2] *= s q[3] *= s end end q end |
#rank(shape_idx, rank_idx, meth = :copy) ⇒ Object
call-seq:
rank(dimension, row_or_column_number) -> NMatrix
rank(dimension, row_or_column_number, :reference) -> NMatrix reference slice
Returns the rank (e.g., row, column, or layer) specified, using slicing by copy as default.
See @row (dimension = 0), @column (dimension = 1)
375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/nmatrix/nmatrix.rb', line 375 def rank(shape_idx, rank_idx, meth = :copy) if shape_idx > (self.dim-1) raise(RangeError, "#rank call was out of bounds") end params = Array.new(self.dim) params.each.with_index do |v,d| params[d] = d == shape_idx ? rank_idx : 0...self.shape[d] end meth == :reference ? self[*params] : self.slice(*params) end |
#rational_dtype? ⇒ Boolean
call-seq:
complex_dtype?() -> Boolean
Checks if dtype is a rational type
268 269 270 |
# File 'lib/nmatrix/nmatrix.rb', line 268 def rational_dtype? [:rational32, :rational64, :rational128].include?(self.dtype) end |
#reshape(new_shape, *shapes) ⇒ Object
call-seq:
reshape(new_shape) -> NMatrix
Clone a matrix, changing the shape in the process. Note that this function does not do a resize; the product of the new and old shapes’ components must be equal.
-
Arguments :
-
new_shape
-> Array of positive Fixnums.
-
-
Returns :
-
A copy with a different shape.
-
444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/nmatrix/nmatrix.rb', line 444 def reshape new_shape,*shapes if new_shape.is_a?Fixnum newer_shape = [new_shape]+shapes else # new_shape is an Array newer_shape = new_shape end t = reshape_clone_structure(newer_shape) left_params = [:*]*newer_shape.size right_params = [:*]*self.shape.size t[*left_params] = self[*right_params] t end |
#reshape!(new_shape, *shapes) ⇒ Object
call-seq:
reshape!(new_shape) -> NMatrix
reshape! new_shape -> NMatrix
Reshapes the matrix (in-place) to the desired shape. Note that this function does not do a resize; the product of the new and old shapes’ components must be equal.
-
Arguments :
-
new_shape
-> Array of positive Fixnums.
-
469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/nmatrix/nmatrix.rb', line 469 def reshape! new_shape,*shapes if self.is_ref? raise(ArgumentError, "This operation cannot be performed on reference slices") else if new_shape.is_a?Fixnum shape = [new_shape]+shapes else # new_shape is an Array shape = new_shape end self.reshape_bang(shape) end end |
#respond_to?(method) ⇒ Boolean
:nodoc:
835 836 837 838 839 840 841 842 843 |
# File 'lib/nmatrix/nmatrix.rb', line 835 def respond_to?(method) #:nodoc: if [:shuffle, :shuffle!, :each_with_index, :sorted_indices, :binned_sorted_indices, :nrm2, :asum].include?(method.intern) # vector-only methods return vector? elsif [:each_layer, :layer].include?(method.intern) # 3-or-more dimensions only return dim > 2 else super(method) end end |
#round ⇒ Object
#row(row_number, get_by = :copy) ⇒ Object
call-seq:
row(row_number) -> NMatrix
row(row_number, get_by) -> NMatrix
-
Arguments :
-
row_number
-> Integer. -
get_by
-> Type of slicing to use,:copy
or:reference
.
-
-
Returns :
-
An NMatrix representing the requested row as a row vector.
-
427 428 429 |
# File 'lib/nmatrix/nmatrix.rb', line 427 def row(row_number, get_by = :copy) rank(0, row_number, get_by) end |
#rows ⇒ Object
call-seq:
rows -> Integer
This shortcut use #shape to return the number of rows (the first dimension) of the matrix.
188 189 190 |
# File 'lib/nmatrix/nmatrix.rb', line 188 def rows shape[0] end |
#shape ⇒ Object
handles list and dense, which are n-dimensional
48 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 48 static VALUE nm_shape(VALUE self); |
#shuffle(*args) ⇒ Object
call-seq:
shuffle -> ...
shuffle(rng) -> ...
Re-arranges the contents of an NVector.
TODO: Write more efficient version for Yale, list. TODO: Generalize for more dimensions.
780 781 782 783 784 |
# File 'lib/nmatrix/nmatrix.rb', line 780 def shuffle(*args) method_missing(:shuffle!, *args) if self.effective_dim > 1 t = self.clone t.shuffle!(*args) end |
#shuffle!(*args) ⇒ Object
call-seq:
shuffle! -> ...
shuffle!(random: rng) -> ...
Re-arranges the contents of an NVector.
TODO: Write more efficient version for Yale, list. TODO: Generalize for more dimensions.
762 763 764 765 766 767 768 |
# File 'lib/nmatrix/nmatrix.rb', line 762 def shuffle!(*args) method_missing(:shuffle!, *args) if self.effective_dim > 1 ary = self.to_flat_a ary.shuffle!(*args) ary.each.with_index { |v,idx| self[idx] = v } self end |
#sin ⇒ Object
#sinh ⇒ Object
#size ⇒ Object
call-seq:
size -> Fixnum
Returns the total size of the NMatrix based on its shape.
307 308 309 |
# File 'lib/nmatrix/nmatrix.rb', line 307 def size NMatrix.size(self.shape) end |
#slice ⇒ Object
59 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 59
static VALUE nm_mget(int argc, VALUE* argv, VALUE self);
|
#sorted_indices ⇒ Object
call-seq:
sorted_indices -> Array
Returns an array of the indices ordered by value sorted.
793 794 795 796 797 |
# File 'lib/nmatrix/nmatrix.rb', line 793 def sorted_indices return method_missing(:sorted_indices) unless vector? ary = self.to_flat_array ary.each_index.sort_by { |i| ary[i] } # from: http://stackoverflow.com/a/17841159/170300 end |
#sqrt ⇒ Object
#std(dimen = 0) ⇒ Object
call-seq:
std() -> NMatrix
std(dimen) -> NMatrix
Calculates the sample standard deviation along the specified dimension.
This will force integer types to float64 dtype.
509 510 511 |
# File 'lib/nmatrix/math.rb', line 509 def std(dimen=0) variance(dimen).sqrt end |
#stype ⇒ Object
42 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 42 static VALUE nm_stype(VALUE self); |
#sum(dimen = 0) ⇒ Object
call-seq:
sum() -> NMatrix
sum(dimen) -> NMatrix
Calculates the sum along the specified dimension.
429 430 431 432 433 |
# File 'lib/nmatrix/math.rb', line 429 def sum(dimen=0) inject_rank(dimen, 0.0) do |sum, sub_mat| sum + sub_mat end end |
#supershape ⇒ Object
49 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 49 static VALUE nm_supershape(VALUE self); |
#symmetric? ⇒ Boolean
149 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 149 static VALUE nm_symmetric(VALUE self); |
#tan ⇒ Object
#tanh ⇒ Object
#to_a(dimen = nil) ⇒ Object
call-seq:
to_a -> Array
Converts an NMatrix to an array of arrays, or an NMatrix of effective dimension 1 to an array.
Does not yet work for dimensions > 2
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/nmatrix/nmatrix.rb', line 345 def to_a(dimen=nil) if self.dim == 2 return self.to_flat_a if self.shape[0] == 1 ary = [] begin self.each_row do |row| ary << row.to_flat_a end #rescue NotImplementedError # Oops. Try copying instead # self.each_row(:copy) do |row| # ary << row.to_a.flatten # end end ary else to_a_rec(0) end end |
#to_f ⇒ Object
call-seq:
to_f -> Float
Converts an nmatrix with a single element (but any number of dimensions)
to a float.
Raises an IndexError if the matrix does not have just a single element.
282 283 284 285 |
# File 'lib/nmatrix/nmatrix.rb', line 282 def to_f raise IndexError, 'to_f only valid for matrices with a single element' unless shape.all? { |e| e == 1 } self[*Array.new(shape.size, 0)] end |
#to_flat_array ⇒ Object Also known as: to_flat_a
call-seq:
to_flat_array -> Array
to_flat_a -> Array
Converts an NMatrix to a one-dimensional Ruby Array.
294 295 296 297 298 |
# File 'lib/nmatrix/nmatrix.rb', line 294 def to_flat_array ary = Array.new(self.size) self.each.with_index { |v,i| ary[i] = v } ary end |
#to_hash ⇒ Object Also known as: to_h
call-seq:
to_hash -> Hash
Create a Ruby Hash from an NMatrix.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/nmatrix/nmatrix.rb', line 209 def to_hash if stype == :yale h = {} each_stored_with_indices do |val,i,j| next if val == 0 # Don't bother storing the diagonal zero values -- only non-zeros. if h.has_key?(i) h[i][j] = val else h[i] = {j => val} end end h else # dense and list should use a C internal function. # FIXME: Write a C internal to_h function. m = stype == :dense ? self.cast(:list, self.dtype) : self m.__list_to_hash__ end end |
#to_s ⇒ Object
:nodoc:
312 313 314 |
# File 'lib/nmatrix/nmatrix.rb', line 312 def to_s #:nodoc: self.to_flat_array.to_s end |
#trace ⇒ Object
call-seq:
trace -> Numeric
Calculates the trace of an nxn matrix.
-
Raises :
-
ShapeError
-> Expected square matrix
-
-
Returns :
-
The trace of the matrix (a numeric value)
-
392 393 394 395 396 397 398 |
# File 'lib/nmatrix/math.rb', line 392 def trace raise(ShapeError, "Expected square matrix") unless self.shape[0] == self.shape[1] && self.dim == 2 (0...self.shape[0]).inject(0) do |total,i| total + self[i,i] end end |
#transpose(permute = nil) ⇒ Object
call-seq:
transpose -> NMatrix
transpose(permutation) -> NMatrix
Clone a matrix, transposing it in the process. If the matrix is two-dimensional, the permutation is taken to be [1,0] automatically (switch dimension 0 with dimension 1). If the matrix is n-dimensional, you must provide a permutation of 0...n
.
-
Arguments :
-
permutation
-> Optional Array giving a permutation.
-
-
Returns :
-
A copy of the matrix, but transposed.
-
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'lib/nmatrix/nmatrix.rb', line 496 def transpose(permute = nil) if self.dim == 1 return self.clone elsif self.dim == 2 new_shape = [self.shape[1], self.shape[0]] elsif permute.nil? raise(ArgumentError, "need permutation array of size #{self.dim}") elsif permute.sort.uniq != (0...self.dim).to_a raise(ArgumentError, "invalid permutation array") else # Figure out the new shape based on the permutation given as an argument. new_shape = permute.map { |p| self.shape[p] } end if self.dim > 2 # FIXME: For dense, several of these are basically equivalent to reshape. # Make the new data structure. t = self.reshape_clone_structure(new_shape) self.each_stored_with_indices do |v,*indices| p_indices = permute.map { |p| indices[p] } t[*p_indices] = v end t elsif self.list? # TODO: Need a C list transposition algorithm. # Make the new data structure. t = self.reshape_clone_structure(new_shape) self.each_column.with_index do |col,j| t[j,:*] = col.to_flat_array end t else # Call C versions of Yale and List transpose, which do their own copies self.clone_transpose end end |
#upper_triangle(k = 0) ⇒ Object Also known as: triu
call-seq:
upper_triangle -> NMatrix
upper_triangle(k) -> NMatrix
triu -> NMatrix
triu(k) -> NMatrix
Returns the upper triangular portion of a matrix. This is analogous to the triu
method in MATLAB.
-
Arguments :
-
k
-> Positive integer. How many extra diagonals to include in the upper triangular portion.
-
639 640 641 642 643 644 645 646 647 648 649 650 651 652 |
# File 'lib/nmatrix/nmatrix.rb', line 639 def upper_triangle(k = 0) raise(NotImplementedError, "only implemented for 2D matrices") if self.shape.size > 2 t = self.clone_structure (0...self.shape[0]).each do |i| if i - k < 0 t[i, :*] = self[i, :*] else t[i, 0...(i-k)] = 0 t[i, (i-k)...self.shape[1]] = self[i, (i-k)...self.shape[1]] end end t end |
#upper_triangle!(k = 0) ⇒ Object Also known as: triu!
call-seq:
upper_triangle! -> NMatrix
upper_triangle!(k) -> NMatrix
triu! -> NMatrix
triu!(k) -> NMatrix
Deletes the lower triangular portion of the matrix (in-place) so only the upper portion remains.
-
Arguments :
-
k
-> Integer. How many extra diagonals to include in the deletion.
-
668 669 670 671 672 673 674 675 676 677 |
# File 'lib/nmatrix/nmatrix.rb', line 668 def upper_triangle!(k = 0) raise(NotImplementedError, "only implemented for 2D matrices") if self.shape.size > 2 (0...self.shape[0]).each do |i| if i - k >= 0 self[i, 0...(i-k)] = 0 end end self end |
#variance(dimen = 0) ⇒ Object
call-seq:
variance() -> NMatrix
variance(dimen) -> NMatrix
Calculates the sample variance along the specified dimension.
This will force integer types to float64 dtype.
486 487 488 489 490 491 492 493 494 495 |
# File 'lib/nmatrix/math.rb', line 486 def variance(dimen=0) reduce_dtype = nil if integer_dtype? then reduce_dtype = :float64 end m = mean(dimen) inject_rank(dimen, 0.0, reduce_dtype) do |var, sub_mat| var + (m - sub_mat)*(m - sub_mat)/(shape[dimen]-1) end end |
#vconcat(*matrices) ⇒ Object
Vertical concatenation with matrices
.
616 617 618 |
# File 'lib/nmatrix/nmatrix.rb', line 616 def vconcat(*matrices) concat(*matrices, :row) end |
#vector? ⇒ Boolean
call-seq:
vector? -> true or false
Shortcut function for determining whether the effective dimension is 1. See also #nvector?
333 334 335 |
# File 'lib/nmatrix/nmatrix.rb', line 333 def vector? self.effective_dim == 1 end |
#write ⇒ Object
38 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 38
static VALUE nm_write(int argc, VALUE* argv, VALUE self);
|
#yale? ⇒ Boolean
call-seq:
m.yale? -> true or false
Determine if m
is a Yale matrix.
47 |
# File 'lib/nmatrix/shortcuts.rb', line 47 def yale?; return stype == :yale; end |