Class: NMatrix
- Includes:
- Enumerable
- Defined in:
- lib/nmatrix/math.rb,
lib/nmatrix/nmatrix.rb,
lib/nmatrix/version.rb,
lib/nmatrix/enumerate.rb,
lib/nmatrix/shortcuts.rb,
lib/nmatrix/cruby/math.rb,
lib/nmatrix/jruby/math.rb,
lib/nmatrix/homogeneous.rb,
lib/nmatrix/jruby/slice.rb,
lib/nmatrix/lapack_core.rb,
lib/nmatrix/jruby/operators.rb,
lib/nmatrix/io/fortran_format.rb,
lib/nmatrix/io/harwell_boeing.rb,
lib/nmatrix/jruby/nmatrix_java.rb,
lib/nmatrix/jruby/decomposition.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 - 2016, Ruby Science Foundation NMatrix is Copyright © 2012 - 2016, 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, FactorizeLUMethods, IO, LAPACK, MagicHelpers, NMMath, VERSION, YaleFunctions
Instance Attribute Summary collapse
-
#dim ⇒ Object
Sets the attribute dim.
-
#dtype ⇒ Object
Returns the value of attribute dtype.
-
#s ⇒ Object
Returns the value of attribute s.
-
#shape ⇒ Object
handles list and dense, which are n-dimensional.
-
#stype ⇒ Object
Returns the value of attribute stype.
Class Method Summary collapse
-
.[](*params) ⇒ Object
call-seq: NMatrix[Numeric, …, Numeric, dtype: Symbol] -> NMatrix NMatrix[Array, dtype: Symbol] -> NMatrix.
-
.block_diagonal(*params) ⇒ Object
(also: block_diag)
Generate a block-diagonal NMatrix from the supplied 2D square matrices.
-
.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(arg) ⇒ Object
FIXME.
-
.hilbert(shape, opts = {}) ⇒ Object
call-seq: hilbert(shape) -> NMatrix hilbert(shape, dtype: dtype) -> NMatrix hilbert(shape, stype: stype, dtype: dtype) -> NMatrix.
-
.inv_hilbert(shape, opts = {}) ⇒ Object
call-seq: inv_hilbert(shape) -> NMatrix inv_hilbert(shape, dtype: dtype) -> NMatrix inv_hilbert(shape, stype: stype, dtype: dtype) -> NMatrix.
-
.linspace(base, limit, shape = [100]) ⇒ Object
call-seq: linspace(base, limit) -> 1x100 NMatrix linspace(base, limit, *shape) -> NMatrix.
-
.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.
-
.logspace(base, limit, shape = [50], exponent_base: 10) ⇒ Object
call-seq: logspace(base, limit) -> 1x50 NMatrix with exponent_base = 10 logspace(base, limit, shape , exponent_base:) -> NMatrix logspace(base, :pi, n) -> 1xn NMatrix with interval [10 ^ base, Math::PI].
-
.magic(shape, opts = {}) ⇒ Object
call-seq: magic(shape) -> NMatrix magic(shape, dtype: dtype) -> NMatrix.
-
.meshgrid(vectors, options = {}) ⇒ Object
Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given N coordinate arrays arrs.
-
.min_dtype(alpha) ⇒ Object
Needs to be properly implemented.
-
.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 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(alpha, beta) ⇒ 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
- #!~(other) ⇒ Object
- #%(other) ⇒ Object
- #*(other) ⇒ Object
- #**(val) ⇒ Object
-
#+(other) ⇒ Object
A dummy matrix is a matrix without the elements atrribute.
- #-(other) ⇒ Object
- #-@ ⇒ Object
- #/(other) ⇒ Object
- #<(other) ⇒ Object
- #<=(other) ⇒ Object
- #==(otherNmatrix) ⇒ Object
- #=~(other) ⇒ Object
- #>(other) ⇒ Object
- #>=(other) ⇒ Object
- #[](*args) ⇒ Object
- #[]=(*args) ⇒ Object
- #__list_default_value__ ⇒ Object
-
#__yale_ary__to_s(sym) ⇒ Object
:nodoc:.
- #__yale_default_value__ ⇒ Object
-
#abs ⇒ Object
call-seq: abs -> NMatrix.
-
#abs_dtype ⇒ Object
call-seq: abs_dtype -> Symbol.
- #acos ⇒ Object
- #acosh ⇒ Object
-
#adjugate ⇒ Object
(also: #adjoint)
call-seq: adjugate -> NMatrix.
-
#adjugate! ⇒ Object
(also: #adjoint!)
call-seq: adjugate! -> NMatrix.
-
#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(other, scalar = false) ⇒ 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(*args) ⇒ Object
- #cbrt ⇒ Object
- #ceil ⇒ Object
- #clone ⇒ 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.
-
#corr ⇒ Object
Calculate the correlation matrix.
- #cos ⇒ Object
- #cosh ⇒ Object
-
#cov(opts = {}) ⇒ Object
Calculate the variance co-variance matrix.
-
#data_pointer ⇒ Object
///////////////.
-
#dconcat(*matrices) ⇒ Object
Depth concatenation with
matrices
. - #default_value ⇒ Object
-
#dense? ⇒ Boolean
call-seq: m.dense? -> true or false.
-
#dense_storage_coords(s, slice_pos, coords_out, stride, offset) ⇒ Object
array, int, array.
- #dense_storage_get(slice, stride) ⇒ Object
- #dense_storage_pos(coords, stride) ⇒ Object
- #dense_storage_set(slice, right) ⇒ Object
-
#det ⇒ Object
call-seq: det -> determinant.
- #det_exact ⇒ Object
- #det_exact2 ⇒ Object
-
#diagonal(main_diagonal = true) ⇒ Object
Return the main diagonal or antidiagonal a matrix.
-
#dot(other) ⇒ 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
Iterators public methods.
- #entries ⇒ Object
- #erf ⇒ Object
- #erfc ⇒ Object
-
#exact_inverse ⇒ Object
(also: #invert_exactly)
call-seq: exact_inverse -> NMatrix.
-
#exact_inverse! ⇒ Object
call-seq: exact_inverse! -> NMatrix.
- #exp ⇒ Object
-
#factorize_cholesky ⇒ Object
call-seq: factorize_cholesky -> [upper NMatrix, lower NMatrix].
-
#factorize_lu(with_permutation_matrix = nil) ⇒ Object
call-seq: factorize_lu -> …
-
#factorize_qr ⇒ Object
call-seq: factorize_qr -> [Q,R].
-
#flat_map ⇒ Object
call-seq: flat_map -> Enumerator flat_map { |elem| block } -> Array.
-
#float_dtype? ⇒ Boolean
call-seq: float_dtype?() -> Boolean.
- #floor ⇒ Object
-
#fro_matrix_norm ⇒ Object
Norm calculation methods Frobenius norm: the Euclidean norm of the matrix, treated as if it were a vector.
- #gamma ⇒ Object
-
#geqrf! ⇒ Object
call-seq: geqrf! -> shape.min x 1 NMatrix.
-
#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.
- #get_slice(dim, args, shape_array) ⇒ Object
- #get_stride(nmatrix) ⇒ Object
-
#getrf! ⇒ Object
call-seq: getrf! -> Array.
-
#hconcat(*matrices) ⇒ Object
Horizontal concatenation with
matrices
. - #hermitian? ⇒ Boolean
-
#hessenberg ⇒ Object
Reduce self to upper hessenberg form using householder transforms.
-
#hessenberg! ⇒ Object
Destructive version of #hessenberg.
- #hypot(other, scalar = false) ⇒ Object
-
#index(value) ⇒ Object
Returns the index of the first occurence of the specified value.
-
#inf_matrix_norm(minus = false) ⇒ Object
Infinity norm: the maximum/minimum absolute row sum of the matrix.
-
#initialize(*args) ⇒ 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 ⇒ Object
(also: #inverse)
call-seq: invert -> NMatrix.
-
#invert! ⇒ Object
call-seq: invert! -> NMatrix.
- #is_ref? ⇒ Boolean
- #is_symmetric(hermitian) ⇒ Object
-
#kron_prod(mat) ⇒ Object
Compute the Kronecker product of
self
and other NMatrix. -
#last ⇒ Object
call-seq: last -> Element of self.dtype.
-
#laswp(ary, opts = {}) ⇒ Object
(also: #permute_columns)
call-seq: laswp(ary) -> NMatrix.
-
#laswp!(ary, opts = {}) ⇒ 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(other, scalar = false) ⇒ Object
-
#least_squares(b, tolerance: 10e-6) ⇒ Object
call-seq: least_squares(b) -> NMatrix least_squares(b, tolerance: 10e-10) -> NMatrix.
-
#list? ⇒ Boolean
call-seq: m.list? -> true or false.
- #log(val = :natural) ⇒ 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
-
#matrix_norm(type = 2) ⇒ Object
call-seq: matrix_norm -> Numeric.
-
#matrix_solve(rhs) ⇒ Object
discussion in github.com/SciRuby/nmatrix/issues/374.
-
#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.
-
#object_dtype? ⇒ Boolean
call-seq:.
- #offset ⇒ Object
-
#one_matrix_norm(minus = false) ⇒ Object
1-norm: the maximum/minimum absolute column sum of the matrix.
-
#ormqr(tau, side = :left, transpose = false, c = nil) ⇒ Object
call-seq: ormqr(tau) -> NMatrix ormqr(tau, side, transpose, c) -> NMatrix.
-
#pinv(tolerance = 1e-15) ⇒ Object
(also: #pseudo_inverse, #pseudoinverse)
call-seq: pinv -> NMatrix.
-
#positive_definite? ⇒ Boolean
call-seq: positive_definite? -> boolean.
-
#potrf!(which) ⇒ Object
call-seq: potrf!(upper_or_lower) -> NMatrix.
- #potrf_lower! ⇒ Object
- #potrf_upper! ⇒ Object
-
#pow(n) ⇒ Object
Raise a square matrix to a power.
-
#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.
-
#repeat(count, axis) ⇒ Object
call-seq: repeat(count, axis) -> NMatrix.
-
#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, include_all = false) ⇒ 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.
-
#scale(alpha, incx = 1, n = nil) ⇒ Object
call-seq: scale -> NMatrix.
-
#scale!(alpha, incx = 1, n = nil) ⇒ Object
call-seq: scale! -> NMatrix.
-
#shuffle(*args) ⇒ Object
call-seq: shuffle -> …
-
#shuffle!(*args) ⇒ Object
call-seq: shuffle! -> …
- #sin ⇒ Object
- #sinh ⇒ Object
-
#size ⇒ Object
call-seq: size -> Fixnum.
- #slice(*args) ⇒ Object
- #slice_copy(src, dest, lengths, pdest, psrc, n) ⇒ Object
- #slice_set(dest, lengths, pdest, rank, v, v_size, v_offset) ⇒ Object
-
#solve(b, opts = {}) ⇒ Object
Solve the matrix equation AX = B, where A is
self
, B is the first argument, and X is returned. -
#sorted_indices ⇒ Object
call-seq: sorted_indices -> Array.
- #sqrt ⇒ Object
-
#std(dimen = 0) ⇒ Object
call-seq: std() -> NMatrix std(dimen) -> NMatrix.
-
#sum(dimen = 0) ⇒ Object
(also: #cumsum)
call-seq: sum() -> NMatrix cumsum() -> NMatrix sum(dimen) -> NMatrix cumsum(dimen) -> NMatrix.
- #supershape(s) ⇒ 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.
-
#two_matrix_norm(minus = false) ⇒ Object
2-norm: the largest/smallest singular value of the matrix.
- #twoDMat ⇒ Object
-
#unmqr(tau, side = :left, transpose = false, c = nil) ⇒ Object
call-seq: unmqr(tau) -> NMatrix unmqr(tau, side, transpose, c) -> 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
- #xslice(args) ⇒ Object
-
#xslice_ref(args) ⇒ Object
its by ref.
-
#yale? ⇒ Boolean
call-seq: m.yale? -> true or false.
Constructor Details
#initialize(*args) ⇒ Object
Forward Declarations
34 35 36 37 38 39 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 69 70 71 72 73 74 75 76 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 34 def initialize(*args) if args[-1] == :copy @shape = [2,2] @s = [0,0,0,0] @dim = shape.is_a?(Array) ? shape.length : 2 else if (args.length <= 3) @shape = args[0] if args[1].is_a?(Array) elements = args[1] if args.length > 2 hash = args[2] # puts hash @dtype = hash[:dtype] @stype = hash[:stype] else @dtype = :float64 @stype = :dense end else # elements = Java::double[shape[0]*shape[1]].new{ Java::Double.NaN } if args.length > 1 if args[1].is_a?(Symbol) hash = args[1] @dtype = hash[:dtype] @stype = hash[:stype] elements = Array.new(shape*shape) unless shape.is_a? Array else elements = Array.new(shape*shape) unless shape.is_a? Array end end end else offset = 0 if (!args[0].is_a?(Symbol) && !args[0].is_a?(String)) @stype = :dense else offset = 1 @stype = :dense @dtype = args[-1] end @shape = args[offset] elements = args[offset+1] end @shape = [shape,shape] unless shape.is_a?(Array) # @dtype = interpret_dtype(argc-1-offset, argv+offset+1, stype); # @dtype = args[:dtype] if args[:dtype] @dtype_sym = nil @stype_sym = nil @default_val_num = nil @capacity_num = nil @size = (0...@shape.size).inject(1) { |x,i| x * @shape[i] } j=0 if (elements.is_a?(ArrayRealVector)) @s = elements # elsif elements.java_class.to_s == "[D" # @s = ArrayRealVector.new(elements) else storage = Array.new(size) elements = [elements,elements] unless elements.is_a?(Array) if size > elements.length (0...size).each do |i| j=0 unless j!=elements.length storage[i] = elements[j] j+=1 end else storage = elements end if @dtype == :object @s = storage else @s = ArrayRealVector.new(storage.to_java Java::double) end end @dim = @shape.is_a?(Array) ? @shape.length : 2 end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
:nodoc:
977 978 979 980 981 982 983 984 985 |
# File 'lib/nmatrix/nmatrix.rb', line 977 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 |
Instance Attribute Details
#dim=(value) ⇒ Object
Sets the attribute dim
19 20 21 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 19 def dim=(value) @dim = value end |
#dtype ⇒ Object
Returns the value of attribute dtype.
41 42 43 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 41 def dtype @dtype end |
#s ⇒ Object
Returns the value of attribute s.
19 20 21 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 19 def s @s end |
#shape ⇒ Object
handles list and dense, which are n-dimensional
48 49 50 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 48 def shape @shape end |
#stype ⇒ Object
Returns the value of attribute stype.
42 43 44 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 42 def stype @stype 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
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] ]
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/nmatrix/shortcuts.rb', line 186 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 |
.block_diagonal(*params) ⇒ Object Also known as: block_diag
Generate a block-diagonal NMatrix from the supplied 2D square matrices.
-
Arguments
-
*params -> An array that collects all arguments passed to the method. The method
can receive any number of arguments. Optionally, the last entry of +params+ is a hash of options from NMatrix#initialize. All other entries of +params+ are the blocks of the desired block-diagonal matrix. Each such matrix block can be supplied as a square 2D NMatrix object, or alternatively as an array of arrays (with dimensions corresponding to a square matrix), or alternatively as a number.
-
-
Returns
-
NMatrix of block-diagonal form filled with specified matrices as the blocks along the diagonal.
-
-
Example
a = NMatrix.new([2,2], [1,2,3,4])
b = NMatrix.new([1,1], [123], dtype: :float64)
c = Array.new(2) { [[10,10], [10,10]] }
d = Array[[1,2,3], [4,5,6], [7,8,9]]
m = NMatrix.block_diagonal(a, b, *c, d, 10.0, 11, dtype: :int64, stype: :yale)
=>
[
[1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11]
]
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
# File 'lib/nmatrix/shortcuts.rb', line 479 def block_diagonal(*params) = params.last.is_a?(Hash) ? params.pop : {} params.each_index do |i| params[i] = params[i].to_nm if params[i].is_a?(Array) # Convert Array to NMatrix params[i] = NMatrix.new([1,1], [params[i]]) if params[i].is_a?(Numeric) # Convert number to NMatrix end block_sizes = [] #holds the size of each matrix block params.each do |b| unless b.is_a?(NMatrix) raise(ArgumentError, "Only NMatrix or appropriate Array objects or single numbers allowed") end raise(ArgumentError, "Only 2D matrices or 2D arrays allowed") unless b.shape.size == 2 raise(ArgumentError, "Only square-shaped blocks allowed") unless b.shape[0] == b.shape[1] block_sizes << b.shape[0] end block_diag_mat = NMatrix.zeros(block_sizes.inject(0,:+), ) (0...params.length).each do |n| # First determine the size and position of the n'th block in the block-diagonal matrix block_size = block_sizes[n] block_pos = block_sizes[0...n].inject(0,:+) # populate the n'th block in the block-diagonal matrix (0...block_size).each do |i| (0...block_size).each do |j| block_diag_mat[block_pos+i,block_pos+j] = params[n][i,j] end end end return block_diag_mat 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
431 432 433 434 435 436 437 438 439 |
# File 'lib/nmatrix/shortcuts.rb', line 431 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
315 316 317 318 319 320 321 322 323 |
# File 'lib/nmatrix/shortcuts.rb', line 315 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(arg) ⇒ Object
FIXME
139 140 141 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 139 def self.guess_dtype arg :float32 end |
.hilbert(shape, opts = {}) ⇒ Object
call-seq:
hilbert(shape) -> NMatrix
hilbert(shape, dtype: dtype) -> NMatrix
hilbert(shape, stype: stype, dtype: dtype) -> NMatrix
Creates an hilbert matrix (square matrix).
-
Arguments :
-
size
-> integer ( for square matrix) specifying the dimensions. -
dtype
-> (optional) Default is:float64
-
stype
-> (optional) Default is:dense
.
-
-
Returns :
-
A hilbert matrix.
-
Examples:
NMatrix.hilbert(3) # => 1.0 0.5 0.3333333333333333
0.5 0.3333333333333333 0.25
0.3333333333333333 0.25 0.2
347 348 349 350 351 352 353 354 355 356 |
# File 'lib/nmatrix/shortcuts.rb', line 347 def hilbert(shape, opts={}) m = NMatrix.new([shape,shape], {:dtype => :float64}.merge(opts)) 0.upto(shape - 1) do |i| 0.upto(i) do |j| m[i,j] = 1.0 / (j + i + 1) m[j,i] = m[i,j] if i != j end end m end |
.inv_hilbert(shape, opts = {}) ⇒ Object
call-seq:
inv_hilbert(shape) -> NMatrix
inv_hilbert(shape, dtype: dtype) -> NMatrix
inv_hilbert(shape, stype: stype, dtype: dtype) -> NMatrix
Creates an inverse hilbert 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 :
-
A hilbert matrix.
-
Examples:
NMatrix.inv_hilbert(3) # => 9.0, -36.0, 30.0
-36.0, 192.0, -180.0
30.0, -180.0, 180.0
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
# File 'lib/nmatrix/shortcuts.rb', line 379 def inv_hilbert(shape, opts={}) opts = {:dtype => :float64}.merge(opts) m = NMatrix.new([shape,shape],opts) combination = NMatrix.new([2*shape,2*shape],opts) #combinations refers to the combination of n things taken k at a time 0.upto(2*shape-1) do |i| 0.upto(i) do |j| if j != 0 and j != i combination[i,j] = combination[i-1,j] + combination[i-1,j-1] else combination[i,j] = 1 end end end 0.upto(shape-1) do |i| 0.upto(i) do |j| m[i,j] = combination[shape + j,shape - i - 1] * ((i+j)+1) * \ combination[shape + i,shape - j - 1] * (-1) ** ((i+j)) * \ combination[(i+j),i] * combination[(i+j),i] m[j,i] = m[i,j] if i != j end end m end |
.linspace(base, limit, shape = [100]) ⇒ Object
call-seq:
linspace(base, limit) -> 1x100 NMatrix
linspace(base, limit, *shape) -> NMatrix
Returns an NMatrix with [shape x shape x .. x shape] values of dtype :float64
equally spaced from base
to limit
, inclusive.
See: www.mathworks.com/help/matlab/ref/linspace.html
-
Arguments :
-
base
-> The first value in the sequence. -
limit
-> The last value in the sequence. -
shape
-> Desired output shape. Default returns a 1x100 row vector.
-
-
Returns :
-
NMatrix with
:float64
values.
-
Examples :-
NMatrix.linspace(1,Math::PI, 6)
=>[1.0,
1.4283185005187988,
1.8566370010375977,
2.2849555015563965,
2.7132740020751953,
3.1415927410125732
]
NMatrix.linspace(1,10, [3,2])
=>[
[ 1.0, 2.799999952316284]
[4.599999904632568, 6.400000095367432]
[8.199999809265137, 10.0]
]
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/nmatrix/shortcuts.rb', line 644 def linspace(base, limit, shape = [100]) # Convert shape to array format shape = [shape] if shape.is_a? Integer #Calculate number of elements count = shape.inject(:*) # Linear spacing between elements calculated in step # step = limit - base / (count - 1) # [Result Sequence] = [0->N sequence] * step + [Base] step = (limit - base) * (1.0 / (count - 1)) result = NMatrix.seq(shape, {:dtype => :float64}) * step result += NMatrix.new(shape, base) result end |
.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.
-
99 100 101 |
# File 'lib/nmatrix/nmatrix.rb', line 99 def load_matlab_file(file_path) NMatrix::IO::Matlab::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
-
110 111 112 |
# File 'lib/nmatrix/nmatrix.rb', line 110 def load_pcd_file(file_path) NMatrix::IO::PointCloudReader::MetaReader.new(file_path) end |
.logspace(base, limit, shape = [50], exponent_base: 10) ⇒ Object
call-seq:
logspace(base, limit) -> 1x50 NMatrix with exponent_base = 10
logspace(base, limit, shape , exponent_base:) -> NMatrix
logspace(base, :pi, n) -> 1xn NMatrix with interval [10 ^ base, Math::PI]
Returns an NMatrix with [shape x shape x .. x shape] values of dtype :float64
logarithmically spaced from exponent_base ^ base to exponent_base ^ limit, inclusive.
See: www.mathworks.com/help/matlab/ref/logspace.html
-
Arguments :
-
base
-> exponent_base ** base is the first value in the sequence -
limit
-> exponent_base ** limit is the last value in the sequence. -
shape
-> Desired output shape. Default returns a 1x50 row vector.
-
-
Returns :
-
NMatrix with
:float64
values.
-
Examples :-
NMatrix.logspace(1,:pi,7)
=>[
10.0000,
8.2450,
6.7980,
5.6050,
4.6213,
3.8103,
3.1416
]
NMatrix.logspace(1,2,[3,2])
=>[
[10.0, 15.8489]
[25.1189, 39.8107]
[63.0957, 100.0]
]
698 699 700 701 702 703 704 705 706 707 |
# File 'lib/nmatrix/shortcuts.rb', line 698 def logspace(base, limit, shape = [50], exponent_base: 10) #Calculate limit for [10 ^ base ... Math::PI] if limit = :pi limit = Math.log(Math::PI, exponent_base = 10) if limit == :pi shape = [shape] if shape.is_a? Integer #[base...limit] -> [exponent_base ** base ... exponent_base ** limit] result = NMatrix.linspace(base, limit, shape) result.map {|element| exponent_base ** element} end |
.magic(shape, opts = {}) ⇒ Object
call-seq:
magic(shape) -> NMatrix
magic(shape, dtype: dtype) -> NMatrix
The parameter is the dimension of the matrix.
Creates a +:dense+ NMatrix with the following properties:
- An arrangement of the numbers from 1 to n^2 (n-squared) in the matrix, with each number occurring exactly once.
- The sum of the entries of any row, any column, or any main diagonal is the same.
- This sum must be n(n^2+1)/2.
See: http://www.mathworks.com/help/matlab/ref/magic.html
* *Arguments* :
- +shape+ -> Array (or integer for square matrix) specifying the dimensions.
- +dtype+ -> (optional) Default is +:float64+
* *Returns* :
- NMatrix with the above given properties.
Examples:
NMatrix.magic(3) # => [ [4.0, 9.0, 2.0] [3.0, 5.0, 7.0] [8.0, 1.0, 6.0] ]
NMatrix.magic(4, dtype :int32) # => [ [ 1, 15, 14, 4]
[12, 6, 7, 9]
[ 8, 10, 11, 5]
[13, 3, 2, 16] ]
NMatrix.magic(6,dtype: :int64) # => [ [31, 9, 2, 22, 27, 20]
[ 3, 32, 7, 21, 23, 25]
[35, 1, 6, 26, 19, 24]
[ 4, 36, 29, 13, 18, 11]
[30, 5, 34, 12, 14, 16]
[ 8, 28, 33, 17, 10, 15] ]
596 597 598 599 600 601 602 603 604 605 606 607 |
# File 'lib/nmatrix/shortcuts.rb', line 596 def magic(shape, opts={}) raise(ArgumentError, "shape of two is not allowed") if shape == 2 nm = NMatrix.new([shape,shape], 0, {:dtype => :float64}.merge(opts)) if shape % 2 != 0 MagicHelpers.odd_magic nm, shape elsif shape % 4 == 0 MagicHelpers.doubly_even_magic nm, shape else MagicHelpers.singly_even_magic nm, shape end nm end |
.meshgrid(vectors, options = {}) ⇒ Object
Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given N coordinate arrays arrs. N > 1.
call-seq:
meshgrid(arrs) -> Array of NMatrix
meshgrid(arrs, options) -> Array of NMatrix
-
Arguments :
-
vectors
-> Array of N coordinate arrays (Array or NMatrix), if any have more than one dimension they will be flatten -
options
-> Hash with options (:sparse Boolean, false by default; :indexing Symbol, may be :ij or :xy, :xy by default)
-
-
Returns :
-
Array of N N-D NMatrixes
-
-
Examples :
x, y = NMatrix::meshgrid([[1, [2, 3]], [4, 5]]) x.to_a #<= [[1, 2, 3], [1, 2, 3]] y.to_a #<= [[4, 4, 4], [5, 5, 5]]
-
Using options :
x, y = NMatrix::meshgrid([[[1, 2], 3], [4, 5]], sparse: true) x.to_a #<= [[1, 2, 3]] y.to_a #<= [[4], [5]] x, y = NMatrix::meshgrid([[1, 2, 3], [[4], 5]], indexing: :ij) x.to_a #<= [[1, 1], [2, 2], [3, 3]] y.to_a #<= [[4, 5], [4, 5], [4, 5]]
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/nmatrix/nmatrix.rb', line 147 def meshgrid(vectors, = {}) raise(ArgumentError, 'Expected at least 2 arrays.') if vectors.size < 2 [:indexing] ||= :xy raise(ArgumentError, 'Indexing must be :xy of :ij') unless [:ij, :xy].include? [:indexing] mats = vectors.map { |arr| arr.respond_to?(:flatten) ? arr.flatten : arr.to_flat_array } mats[0], mats[1] = mats[1], mats[0] if [:indexing] == :xy new_dim = mats.size lengths = mats.map(&:size) result = mats.map.with_index do |matrix, axis| if [:sparse] new_shape = Array.new(new_dim, 1) new_shape[axis] = lengths[axis] new_elements = matrix else before_axis = lengths[0...axis].reduce(:*) after_axis = lengths[(axis+1)..-1].reduce(:*) new_shape = lengths new_elements = after_axis ? matrix.map{ |el| [el] * after_axis }.flatten : matrix new_elements *= before_axis if before_axis end NMatrix.new(new_shape, new_elements) end result[0], result[1] = result[1], result[0] if [:indexing] == :xy result end |
.min_dtype(alpha) ⇒ Object
Needs to be properly implemented
110 111 112 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 110 def self.min_dtype(alpha) :int8 end |
.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
257 258 259 |
# File 'lib/nmatrix/shortcuts.rb', line 257 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.
270 271 272 |
# File 'lib/nmatrix/shortcuts.rb', line 270 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.
-
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] ]
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
# File 'lib/nmatrix/shortcuts.rb', line 536 def random(shape, opts={}) scale = opts.delete(:scale) || 1.0 if opts[:seed].nil? rng = Random.new else rng = Random.new(opts[:seed]) end 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
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
838 839 840 841 842 843 844 845 |
# File 'lib/nmatrix/shortcuts.rb', line 838 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.
115 116 117 118 |
# File 'lib/nmatrix/nmatrix.rb', line 115 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(alpha, beta) ⇒ Object
Singleton methods
170 171 172 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 170 def self.upcast(alpha, beta) false end |
.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
232 233 234 |
# File 'lib/nmatrix/shortcuts.rb', line 232 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.
283 284 285 |
# File 'lib/nmatrix/shortcuts.rb', line 283 def zeros_like(nm) NMatrix.zeros(nm.shape, dtype: nm.dtype, stype: nm.stype, capacity: nm.capacity, default: 0) end |
Instance Method Details
#!~(other) ⇒ Object
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 545 def !~ (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] != rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#%(other) ⇒ Object
77 78 79 |
# File 'lib/nmatrix/jruby/operators.rb', line 77 def %(other) raise Exception.new("modulus not supported in NMatrix-jruby") end |
#*(other) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/nmatrix/jruby/operators.rb', line 37 def *(other) result = create_dummy_nmatrix if (other.is_a?(NMatrix)) #check dimension raise(ShapeError, "Cannot multiply matrices with different dimension") if (@dim != other.dim) #check shape (0...dim).each do |i| raise(ShapeError, "Cannot multiply matrices with different shapes") if (@shape[i] != other.shape[i]) end result.s = @s.copy.ebeMultiply(other.s) else result.s = @s.copy.mapMultiplyToSelf(other) end result end |
#**(val) ⇒ Object
69 70 71 72 73 74 75 |
# File 'lib/nmatrix/jruby/operators.rb', line 69 def ** val result = NMatrix.new(:copy) result.shape = @shape result.dim = @dim result.s = @s.copy.mapToSelf(Power.new(val)) result end |
#+(other) ⇒ Object
A dummy matrix is a matrix without the elements atrribute. NMatrix#create_dummy_matrix prevents creating copies as @s is set explicitly.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/nmatrix/jruby/operators.rb', line 5 def +(other) result = create_dummy_nmatrix if (other.is_a?(NMatrix)) #check dimension raise(ShapeError, "Cannot add matrices with different dimension") if (@dim != other.dim) #check shape (0...dim).each do |i| raise(ShapeError, "Cannot add matrices with different shapes") if (@shape[i] != other.shape[i]) end result.s = @s.copy.add(other.s) else result.s = @s.copy.mapAddToSelf(other) end result end |
#-(other) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/nmatrix/jruby/operators.rb', line 21 def -(other) result = create_dummy_nmatrix if (other.is_a?(NMatrix)) #check dimension raise(ShapeError, "Cannot subtract matrices with different dimension") if (@dim != other.dim) #check shape (0...dim).each do |i| raise(ShapeError, "Cannot subtract matrices with different shapes") if (@shape[i] != other.shape[i]) end result.s = @s.copy.subtract(other.s) else result.s = @s.copy.mapSubtractToSelf(other) end result end |
#-@ ⇒ Object
253 254 255 256 257 |
# File 'lib/nmatrix/jruby/operators.rb', line 253 def -@ result = create_dummy_nmatrix result.s = @s.copy.mapMultiplyToSelf(-1) result end |
#/(other) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/nmatrix/jruby/operators.rb', line 53 def /(other) result = create_dummy_nmatrix if (other.is_a?(NMatrix)) #check dimension raise(ShapeError, "Cannot divide matrices with different dimension") if (@dim != other.dim) #check shape (0...dim).each do |i| raise(ShapeError, "Cannot divide matrices with different shapes") if (@shape[i] != other.shape[i]) end result.s = @s.copy.ebeDivide(other.s) else result.s = @s.copy.mapDivideToSelf(other) end result end |
#<(other) ⇒ Object
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 632 def < (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] < rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#<=(other) ⇒ Object
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 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 574 def <= (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] <= rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#==(otherNmatrix) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 152 def ==(otherNmatrix) result = false if (otherNmatrix.is_a?(NMatrix)) #check dimension if (@dim != otherNmatrix.dim) raise(ShapeError, "cannot compare matrices with different dimension") end #check shape (0...dim).each do |i| if (@shape[i] != otherNmatrix.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); end end #check the entries if dtype == :object result = @s == otherNmatrix.s else result = ArrayComparator.equals(@s.toArray, otherNmatrix.s.toArray) end end result end |
#=~(other) ⇒ Object
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 516 def =~ (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] == rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#>(other) ⇒ Object
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 661 def > (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] > rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#>=(other) ⇒ Object
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 603 def >= (other) lha = @s.toArray.to_a rha = other.s.toArray.to_a resultArray = Array.new(lha.length) if (other.is_a?(NMatrix)) #check dimension if (@dim != other.dim) raise(ShapeError, "cannot compare matrices with different dimension") return nil end #check shape (0...dim).each do |i| if (@shape[i] != other.shape[i]) raise(ShapeError, "cannot compare matrices with different shapes"); return nil end end #check the entries (0...lha.length).each do |i| resultArray[i] = lha[i] >= rha[i] ? true : false end result = NMatrix.new(:copy) result.shape = @shape result.dtype = :object result.s = resultArray end result end |
#[](*args) ⇒ Object
60 61 62 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 60 def [] *args return xslice(args) end |
#[]=(*args) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 58 def []=(*args) to_return = nil if args.length > @dim+1 raise(ArgumentError, "wrong number of arguments (#{args.length} for #{effective_dim(dim+1)})" ) else slice = get_slice(@dim, args, @shape) dense_storage_set(slice, args[-1]) to_return = args[-1] end return to_return end |
#__list_default_value__ ⇒ Object
160 161 162 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 160 def __list_default_value__ #not implemented currently end |
#__yale_ary__to_s(sym) ⇒ Object
:nodoc:
346 347 348 349 350 |
# File 'lib/nmatrix/nmatrix.rb', line 346 def __yale_ary__to_s(sym) #:nodoc: ary = self.send("__yale_#{sym.to_s}__".to_sym) '[' + ary.collect { |a| a ? a : 'nil'}.join(',') + ']' end |
#__yale_default_value__ ⇒ Object
164 165 166 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 164 def __yale_default_value__ #not implemented currently end |
#abs ⇒ Object
call-seq:
abs -> NMatrix
Maps all values in a matrix to their absolute values.
617 618 619 620 621 622 623 624 625 626 |
# File 'lib/nmatrix/math.rb', line 617 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).
601 602 603 604 605 606 607 608 609 |
# File 'lib/nmatrix/math.rb', line 601 def abs_dtype if self.dtype == :complex64 :float32 elsif self.dtype == :complex128 :float64 else self.dtype end end |
#acos ⇒ Object
147 148 149 150 151 |
# File 'lib/nmatrix/jruby/operators.rb', line 147 def acos result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Acos.new()) result end |
#acosh ⇒ Object
185 186 187 188 189 |
# File 'lib/nmatrix/jruby/operators.rb', line 185 def acosh result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Acosh.new()) result end |
#adjugate ⇒ Object Also known as: adjoint
call-seq:
adjugate -> NMatrix
Make a copy of the matrix and calculate the adjugate of the matrix. Only works on dense matrices.
-
Returns :
-
A dense NMatrix. Will be the same type as the input NMatrix,
except if the input is an integral dtype, in which case it will be a :float64 NMatrix.
-
-
Raises :
-
StorageTypeError
-> only implemented on dense matrices. -
ShapeError
-> matrix must be square.
-
271 272 273 274 275 276 277 278 |
# File 'lib/nmatrix/math.rb', line 271 def adjugate raise(StorageTypeError, "adjugate only works on dense matrices currently") unless self.dense? raise(ShapeError, "Cannot calculate adjugate of a non-square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1] d = self.det mat = self.invert mat.map! { |e| e * d } mat end |
#adjugate! ⇒ Object Also known as: adjoint!
call-seq:
adjugate! -> NMatrix
Calculate the adjugate of the matrix (in-place). Only works on dense matrices.
-
Raises :
-
StorageTypeError
-> only implemented on dense matrices. -
ShapeError
-> matrix must be square. -
DataTypeError
-> cannot calculate adjugate of an integer matrix in-place.
-
244 245 246 247 248 249 250 251 252 |
# File 'lib/nmatrix/math.rb', line 244 def adjugate! raise(StorageTypeError, "adjugate only works on dense matrices currently") unless self.dense? raise(ShapeError, "Cannot calculate adjugate of a non-square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1] raise(DataTypeError, "Cannot calculate adjugate of an integer matrix in-place") if self.integer_dtype? d = self.det self.invert! self.map! { |e| e * d } self end |
#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
141 142 143 144 145 |
# File 'lib/nmatrix/jruby/operators.rb', line 141 def asin result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Asin.new()) result end |
#asinh ⇒ Object
179 180 181 182 183 |
# File 'lib/nmatrix/jruby/operators.rb', line 179 def asinh result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Asinh.new()) result end |
#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.
680 681 682 683 684 685 686 687 |
# File 'lib/nmatrix/cruby/math.rb', line 680 def asum incx=1, n=nil if self.shape == [1] return self[0].abs unless self.complex_dtype? return self[0].real.abs + self[0].imag.abs end return method_missing(:asum, incx, n) unless vector? NMatrix::BLAS::asum(self, incx, self.size / incx) end |
#atan ⇒ Object
153 154 155 156 157 |
# File 'lib/nmatrix/jruby/operators.rb', line 153 def atan result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Atan.new()) result end |
#atan2(other, scalar = false) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/nmatrix/jruby/operators.rb', line 81 def atan2(other, scalar=false) result = create_dummy_nmatrix if scalar result.s = ArrayRealVector.new MathHelper.atan2Scalar(other, @s.toArray) else if other.is_a? NMatrix result.s = ArrayRealVector.new MathHelper.atan2(other.s.toArray, @s.toArray) else result.s = ArrayRealVector.new MathHelper.atan2Scalar2(other, @s.toArray) end end result end |
#atanh ⇒ Object
191 192 193 194 195 |
# File 'lib/nmatrix/jruby/operators.rb', line 191 def atanh result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Atanh.new()) result end |
#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.
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 |
# File 'lib/nmatrix/nmatrix.rb', line 960 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 51 52 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 50 def capacity end |
#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 or Complex equivalent. If no option is given, Fixnum 0 will be used.
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/nmatrix/nmatrix.rb', line 239 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(*args) ⇒ Object
147 148 149 150 151 152 153 154 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 147 def cast_full *args if args.is_a? Hash self.dtype = args[:dtype] else self.dtype = args[1] end return self end |
#cbrt ⇒ Object
241 242 243 244 245 |
# File 'lib/nmatrix/jruby/operators.rb', line 241 def cbrt result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Cbrt.new()) result end |
#ceil ⇒ Object
267 268 269 270 271 272 273 |
# File 'lib/nmatrix/jruby/operators.rb', line 267 def ceil result = create_dummy_nmatrix # Need to be changed later result.dtype = :int64 result.s = @s.copy.mapToSelf(Ceil.new()) result end |
#clone ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 118 def clone result = create_dummy_nmatrix # ArrayRealVector#clone is disable, hence use copy # that returns a deep copy of the object. result.s = @s.copy return result end |
#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
.
1036 1037 1038 1039 1040 |
# File 'lib/nmatrix/nmatrix.rb', line 1036 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.
280 281 282 |
# File 'lib/nmatrix/nmatrix.rb', line 280 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
529 530 531 |
# File 'lib/nmatrix/nmatrix.rb', line 529 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.
-
653 654 655 |
# File 'lib/nmatrix/cruby/math.rb', line 653 def complex_conjugate(new_stype = self.stype) self.cast(new_stype, NMatrix::upcast(dtype, :complex64)).complex_conjugate! end |
#complex_conjugate! ⇒ Object
161 162 163 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 161 def complex_conjugate! end |
#complex_dtype? ⇒ Boolean
call-seq:
complex_dtype?() -> Boolean
Checks if dtype is a complex type
377 378 379 |
# File 'lib/nmatrix/nmatrix.rb', line 377 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
-
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 |
# File 'lib/nmatrix/nmatrix.rb', line 695 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 concatenation. We don't know where it will end, # because each matrix may have own size along concat dimension. pos = Array.new(self.dim) { 0 } matrices.unshift(self) matrices.each do |m| # Figure out where to start and stop the concatenation. We'll use # NMatrices instead of Arrays because then we can do elementwise addition. ranges = m.shape.map.with_index { |s,i| pos[i]...(pos[i] + s) } n[*ranges] = m # Move over by the requisite amount pos[rank] = pos[rank] + 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.
-
667 668 669 |
# File 'lib/nmatrix/cruby/math.rb', line 667 def conjugate_transpose self.transpose.complex_conjugate! end |
#corr ⇒ Object
Calculate the correlation matrix.
368 369 370 371 372 |
# File 'lib/nmatrix/math.rb', line 368 def corr raise NotImplementedError, "Does not work for complex dtypes" if complex_dtype? standard_deviation = std cov / (standard_deviation.transpose.dot(standard_deviation)) end |
#cos ⇒ Object
129 130 131 132 133 |
# File 'lib/nmatrix/jruby/operators.rb', line 129 def cos result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Cos.new()) result end |
#cosh ⇒ Object
165 166 167 168 169 |
# File 'lib/nmatrix/jruby/operators.rb', line 165 def cosh result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Cosh.new()) result end |
#cov(opts = {}) ⇒ Object
Calculate the variance co-variance matrix
Options
-
:for_sample_data
- Default true. If set to false will consider the denominator for population data (i.e. N, as opposed to N-1 for sample data).
References
355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/nmatrix/math.rb', line 355 def cov(opts={}) raise TypeError, "Only works for non-integer dtypes" if integer_dtype? opts = { for_sample_data: true }.merge(opts) denominator = opts[:for_sample_data] ? rows - 1 : rows ones = NMatrix.ones [rows,1] deviation_scores = self - ones.dot(ones.transpose).dot(self) / rows deviation_scores.transpose.dot(deviation_scores) / denominator end |
#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
.
764 765 766 |
# File 'lib/nmatrix/nmatrix.rb', line 764 def dconcat(*matrices) concat(*matrices, :layer) end |
#default_value ⇒ Object
43 44 45 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 43 def default_value return nil end |
#dense? ⇒ Boolean
call-seq:
m.dense? -> true or false
Determine if m
is a dense matrix.
127 |
# File 'lib/nmatrix/shortcuts.rb', line 127 def dense?; return stype == :dense; end |
#dense_storage_coords(s, slice_pos, coords_out, stride, offset) ⇒ Object
array, int, array
181 182 183 184 185 186 187 188 189 190 |
# File 'lib/nmatrix/jruby/slice.rb', line 181 def dense_storage_coords(s, slice_pos, coords_out, stride, offset) #array, int, array temp_pos = slice_pos; (0...dim).each do |i| coords_out[i] = (temp_pos - temp_pos % stride[i])/stride[i] - offset[i]; temp_pos = temp_pos % stride[i] end return temp_pos end |
#dense_storage_get(slice, stride) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/nmatrix/jruby/slice.rb', line 118 def dense_storage_get(slice,stride) if slice[:single] return dense_storage_pos(slice[:coords],stride) else shape = @shape.dup (0...@dim).each do |i| shape[i] = slice[:lengths][i] end psrc = dense_storage_pos(slice[:coords], stride) src = {} result = NMatrix.new(:copy) result.dim = dim result.dtype = @dtype resultShape= Array.new(dim) (0...dim).each do |i| resultShape[i] = slice[:lengths][i] end result.shape = resultShape dest = {} src[:stride] = get_stride(self) if (@dtype == :object) src[:elements] = @s else src[:elements] = @s.toArray().to_a end dest[:stride] = get_stride(result) dest[:shape] = resultShape dest[:elements] = [] temp = [] s = (slice_copy(src, dest, slice[:lengths], 0, psrc,0)) # if # arr = Java::double[s.length].new if (@dtype == :object) arr = Java::boolean[s.length].new else arr = Java::double[s.length].new end (0...s.length).each do |i| arr[i] = s[i] end if (@dtype == :object) result.s = arr else result.s = ArrayRealVector.new(arr) end return result end end |
#dense_storage_pos(coords, stride) ⇒ Object
192 193 194 195 196 197 198 199 |
# File 'lib/nmatrix/jruby/slice.rb', line 192 def dense_storage_pos(coords,stride) pos = 0; offset = 0 (0...@dim).each do |i| pos += coords[i] * stride[i] ; end return pos + offset; end |
#dense_storage_set(slice, right) ⇒ Object
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 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/nmatrix/jruby/slice.rb', line 221 def dense_storage_set(slice, right) stride = get_stride(self) v_size = 1 if right.is_a?(NMatrix) right = right.s.toArray.to_a end if(right.is_a?(Array)) v_size = right.length v = right if (dtype == :RUBYOBJ) # nm_register_values(reinterpret_cast<VALUE*>(v), v_size) end (0...v_size).each do |m| v[m] = right[m] end else v = [right] if (@dtype == :RUBYOBJ) # nm_register_values(reinterpret_cast<VALUE*>(v), v_size) end end if(slice[:single]) # reinterpret_cast<D*>(s->elements)[nm_dense_storage_pos(s, slice->coords)] = v; pos = dense_storage_pos(slice[:coords],stride) if @dtype == :object @s[pos] = v[0] else @s.setEntry(pos, v[0]) end else v_offset = 0 dest = {} dest[:stride] = get_stride(self) dest[:shape] = shape # dest[:elements] = @s.toArray().to_a dense_pos = dense_storage_pos(slice[:coords],stride) slice_set(dest, slice[:lengths], dense_pos, 0, v, v_size, v_offset) end end |
#det ⇒ Object
call-seq:
det -> determinant
Calculate the determinant by way of LU decomposition. This is accomplished using clapack_getrf, and then by taking the product of 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.
Integer matrices are converted to floating point 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 :
-
ShapeError
-> Must be used on square matrices.
-
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/nmatrix/cruby/math.rb', line 611 def det raise(ShapeError, "determinant can be calculated only for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1] # Cast to a dtype for which getrf is implemented new_dtype = self.integer_dtype? ? :float64 : 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! num_perm = 0 #number of permutations pivot.each_with_index do |swap, i| #pivot indexes rows starting from 1, instead of 0, so need to subtract 1 here num_perm += 1 if swap-1 != i end prod = num_perm % 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.round : prod #prevent rounding errors end |
#det_exact ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 157 def det_exact # if (:stype != :dense) # raise Exception.new("can only calculate exact determinant for dense matrices") # return nil # end raise(DataTypeError, "cannot call det_exact on unsigned type") if(self.dtype == :byte) if (@dim != 2 || @shape[0] != @shape[1]) raise(ShapeError, "matrices must be square to have a determinant defined") return nil end to_return = nil if (dtype == :object) # to_return = *reinterpret_cast<VALUE*>(result); else to_return = LUDecomposition.new(self.twoDMat).getDeterminant() end return to_return.round(3) end |
#det_exact2 ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 273 def det_exact2 if (@dim != 2 || @shape[0] != @shape[1]) raise(ShapeError, "matrices must be square to have a determinant defined") return nil end to_return = nil if (dtype == :object) # to_return = *reinterpret_cast<VALUE*>(result); else to_return = LUDecomposition.new(self.twoDMat).getDeterminant() end return to_return.round(3) end |
#diagonal(main_diagonal = true) ⇒ Object
Return the main diagonal or antidiagonal a matrix. Only works with 2D matrices.
Arguments
-
main_diagonal
- Defaults to true. If passed ‘false’, then will return the antidiagonal of the matrix.
References
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/nmatrix/nmatrix.rb', line 294 def diagonal main_diagonal=true diag_size = [cols, rows].min diag = NMatrix.new [diag_size], dtype: dtype if main_diagonal 0.upto(diag_size-1) do |i| diag[i] = self[i,i] end else row = 0 (diag_size-1).downto(0) do |col| diag[row] = self[row,col] row += 1 end end diag end |
#dot(other) ⇒ Object
///////////////////////
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 694 def dot(other) result = nil if (other.is_a?(NMatrix)) #check dimension if (@shape.length!=2 || other.shape.length!=2) raise(NotImplementedError, "please convert array to nx1 or 1xn NMatrix first") return nil end #check shape if (@shape[1] != other.shape[0]) raise(ArgumentError, "incompatible dimensions") return nil end # if(@stype != other.stype) # raise(NotImplementedError, "matrices must have same stype") # end result = create_dummy_nmatrix result.shape = [@shape[0],other.shape[1]] twoDMat = self.twoDMat.multiply(other.twoDMat) result.s = ArrayRealVector.new(ArrayGenerator.getArrayDouble(twoDMat.getData, @shape[0],other.shape[1])) else raise(ArgumentError, "cannot have dot product with a scalar"); end return result; end |
#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.
145 146 147 148 149 150 151 |
# File 'lib/nmatrix/enumerate.rb', line 145 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.
161 162 163 164 165 166 167 |
# File 'lib/nmatrix/enumerate.rb', line 161 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 54 55 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 53 def each_ordered_stored_with_indices end |
#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.
118 119 120 121 122 123 124 |
# File 'lib/nmatrix/enumerate.rb', line 118 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.
132 133 134 135 136 137 138 |
# File 'lib/nmatrix/enumerate.rb', line 132 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
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/nmatrix/enumerate.rb', line 176 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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 52 def each_stored_with_indices nmatrix = create_dummy_nmatrix stride = get_stride(self) offset = 0 #Create indices and initialize them to zero coords = Array.new(dim){ 0 } shape_copy = Array.new(dim) (0...size).each do |k| dense_storage_coords(nmatrix, k, coords, stride, offset) slice_index = dense_storage_pos(coords,stride) ary = Array.new if (@dtype == :object) ary << self.s[slice_index] else ary << self.s.toArray.to_a[slice_index] end (0...dim).each do |p| ary << coords[p] end # yield the array which now consists of the value and the indices yield(ary) end if block_given? return nmatrix end |
#each_with_indices ⇒ Object
Iterators public methods
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 51 def each_with_indices nmatrix = create_dummy_nmatrix stride = get_stride(self) offset = 0 #Create indices and initialize them to zero coords = Array.new(dim){ 0 } shape_copy = Array.new(dim) (0...size).each do |k| dense_storage_coords(nmatrix, k, coords, stride, offset) slice_index = dense_storage_pos(coords,stride) ary = Array.new if (@dtype == :object) ary << self.s[slice_index] else ary << self.s.toArray.to_a[slice_index] end (0...dim).each do |p| ary << coords[p] end # yield the array which now consists of the value and the indices yield(ary) end if block_given? return nmatrix end |
#entries ⇒ Object
126 127 128 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 126 def entries return @s.toArray.to_a end |
#erf ⇒ Object
229 230 231 232 233 |
# File 'lib/nmatrix/jruby/operators.rb', line 229 def erf result = create_dummy_nmatrix result.s = ArrayRealVector.new MathHelper.erf(@s.toArray) result end |
#erfc ⇒ Object
235 236 237 238 239 |
# File 'lib/nmatrix/jruby/operators.rb', line 235 def erfc result = create_dummy_nmatrix result.s = ArrayRealVector.new MathHelper.erfc(@s.toArray) result end |
#exact_inverse ⇒ Object Also known as: invert_exactly
call-seq:
exact_inverse -> NMatrix
Make a copy of the matrix, then invert using exact_inverse
-
Returns :
-
A dense NMatrix. Will be the same type as the input NMatrix,
except if the input is an integral dtype, in which case it will be a :float64 NMatrix.
-
-
Raises :
-
StorageTypeError
-> only implemented on dense matrices. -
ShapeError
-> matrix must be square. -
NotImplementedError
-> cannot find exact inverse of matrix with size greater than 3
-
153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/nmatrix/math.rb', line 153 def exact_inverse #write this in terms of exact_inverse! so plugins will only have to overwrite #exact_inverse! and not exact_inverse if self.integer_dtype? cloned = self.cast(dtype: :float64) cloned.exact_inverse! else cloned = self.clone cloned.exact_inverse! end end |
#exact_inverse! ⇒ Object
call-seq:
exact_inverse! -> NMatrix
Calulates inverse_exact of a matrix of size 2 or 3. Only works on dense matrices.
-
Raises :
-
DataTypeError
-> cannot invert an integer matrix in-place. -
NotImplementedError
-> cannot find exact inverse of matrix with size greater than 3 #
-
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/nmatrix/math.rb', line 124 def exact_inverse! raise(ShapeError, "Cannot invert non-square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1] raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype? #No internal implementation of getri, so use this other function n = self.shape[0] if n>3 raise(NotImplementedError, "Cannot find exact inverse of matrix of size greater than 3") else clond=self.clone __inverse_exact__(clond, n, n) end end |
#exp ⇒ Object
197 198 199 200 201 |
# File 'lib/nmatrix/jruby/operators.rb', line 197 def exp result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Exp.new()) result end |
#factorize_cholesky ⇒ Object
call-seq:
factorize_cholesky -> [upper NMatrix, lower NMatrix]
Calculates the Cholesky factorization of a matrix and returns the upper and lower matrices such that A=LU and L=U*, where * is either the transpose or conjugate transpose.
Unlike potrf!, this makes method requires that the original is matrix is symmetric or Hermitian. However, it is still your responsibility to make sure it is positive-definite.
220 221 222 223 224 225 |
# File 'lib/nmatrix/cruby/math.rb', line 220 def factorize_cholesky raise "Matrix must be symmetric/Hermitian for Cholesky factorization" unless self.hermitian? l = self.clone.potrf_lower!.tril! u = l.conjugate_transpose [u,l] end |
#factorize_lu(with_permutation_matrix = nil) ⇒ Object
call-seq:
factorize_lu -> ...
LU factorization of a matrix. Optionally return the permutation matrix.
Note that computing the permutation matrix will introduce a slight memory
and time overhead.
Arguments
with_permutation_matrix
- If set to true will return the permutation
matrix alongwith the LU factorization as a second return value.
240 241 242 243 244 245 246 247 248 249 |
# File 'lib/nmatrix/cruby/math.rb', line 240 def factorize_lu with_permutation_matrix=nil raise(NotImplementedError, "only implemented for dense storage") unless self.stype == :dense raise(NotImplementedError, "matrix is not 2-dimensional") unless self.dimensions == 2 t = self.clone pivot = t.getrf! return t unless with_permutation_matrix [t, FactorizeLUMethods.permutation_matrix_from(pivot)] end |
#factorize_qr ⇒ Object
call-seq:
factorize_qr -> [Q,R]
QR factorization of a matrix without column pivoting. Q is orthogonal and R is upper triangular if input is square or upper trapezoidal if input is rectangular.
Only works for dense matrices.
-
Returns :
-
Array containing Q and R matrices
-
-
Raises :
-
StorageTypeError
-> only implemented for desnse storage. -
ShapeError
-> Input must be a 2-dimensional matrix to have a QR decomposition.
-
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/nmatrix/cruby/math.rb', line 268 def factorize_qr raise(NotImplementedError, "only implemented for dense storage") unless self.stype == :dense raise(ShapeError, "Input must be a 2-dimensional matrix to have a QR decomposition") unless self.dim == 2 rows, columns = self.shape r = self.clone tau = r.geqrf! #Obtain Q q = self.complex_dtype? ? r.unmqr(tau) : r.ormqr(tau) #Obtain R if rows <= columns r.upper_triangle! #Need to account for upper trapezoidal structure if R is a tall rectangle (rows > columns) else r[0...columns, 0...columns].upper_triangle! r[columns...rows, 0...columns] = 0 end [q,r] 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 |
#float_dtype? ⇒ Boolean
call-seq:
float_dtype?() -> Boolean
Checks if dtype is a floating point type
367 368 369 |
# File 'lib/nmatrix/nmatrix.rb', line 367 def float_dtype? [:float32, :float64].include?(dtype) end |
#floor ⇒ Object
259 260 261 262 263 264 265 |
# File 'lib/nmatrix/jruby/operators.rb', line 259 def floor result = create_dummy_nmatrix # Need to be changed later result.dtype = :int64 result.s = @s.copy.mapToSelf(Floor.new()) result end |
#fro_matrix_norm ⇒ Object
Norm calculation methods Frobenius norm: the Euclidean norm of the matrix, treated as if it were a vector
630 631 632 633 634 635 636 637 |
# File 'lib/nmatrix/math.rb', line 630 def fro_matrix_norm #float64 has to be used in any case, since nrm2 will not yield correct result for float32 self_cast = self.cast(:dtype => :float64) column_vector = self_cast.reshape([self.size, 1]) return column_vector.nrm2 end |
#gamma ⇒ Object
247 248 249 250 251 |
# File 'lib/nmatrix/jruby/operators.rb', line 247 def gamma result = create_dummy_nmatrix result.s = ArrayRealVector.new MathHelper.gamma(@s.toArray) result end |
#geqrf! ⇒ Object
call-seq:
geqrf! -> shape.min x 1 NMatrix
QR factorization of a general M-by-N matrix A
.
The QR factorization is A = QR, where Q is orthogonal and R is Upper Triangular A
is overwritten with the elements of R and Q with Q being represented by the elements below A’s diagonal and an array of scalar factors in the output NMatrix.
The matrix Q is represented as a product of elementary reflectors
Q = H(1) H(2) . . . H(k), where k = min(m,n).
Each H(i) has the form
H(i) = I - tau * v * v'
www.netlib.org/lapack/explore-html/d3/d69/dgeqrf_8f.html
Only works for dense matrices.
-
Returns :
-
Vector TAU. Q and R are stored in A. Q is represented by TAU and A
-
-
Raises :
-
StorageTypeError
-> LAPACK functions only work on dense matrices.
-
100 101 102 103 |
# File 'lib/nmatrix/cruby/math.rb', line 100 def geqrf! # The real implementation is in lib/nmatrix/lapacke.rb raise(NotImplementedError, "geqrf! requires the nmatrix-lapacke gem") 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. See also #gesvd.
Optionally accepts a workspace_size
parameter, which will be honored only if it is larger than what LAPACK requires.
507 508 509 |
# File 'lib/nmatrix/cruby/math.rb', line 507 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.
492 493 494 |
# File 'lib/nmatrix/cruby/math.rb', line 492 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.
475 476 477 |
# File 'lib/nmatrix/cruby/math.rb', line 475 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.
461 462 463 |
# File 'lib/nmatrix/cruby/math.rb', line 461 def gesvd!(workspace_size=1) NMatrix::LAPACK::gesvd(self, workspace_size) end |
#get_slice(dim, args, shape_array) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/nmatrix/jruby/slice.rb', line 3 def get_slice(dim, args, shape_array) slice = {} slice[:coords]=[] slice[:lengths]=[] slice[:single] = true argc = args.length t = 0 (0...dim).each do |r| v = t == argc ? nil : args[t] if(argc - t + r < dim && shape_array[r] ==1) slice[:coords][r] = 0 slice[:lengths][r] = 1 elsif v.is_a?(Fixnum) v_ = v.to_i.to_int if (v_ < 0) # checking for negative indexes slice[:coords][r] = shape_array[r]+v_ else slice[:coords][r] = v_ end slice[:lengths][r] = 1 t+=1 elsif (v.is_a?(Symbol) && v == :*) slice[:coords][r] = 0 slice[:lengths][r] = shape_array[r] slice[:single] = false t+=1 elsif v.is_a?(Range) begin_ = v.begin end_ = v.end excl = v.exclude_end? slice[:coords][r] = (begin_ < 0) ? shape[r] + begin_ : begin_ # Exclude last element for a...b range if (end_ < 0) slice[:lengths][r] = shape_array[r] + end_ - slice[:coords][r] + (excl ? 0 : 1) else slice[:lengths][r] = end_ - slice[:coords][r] + (excl ? 0 : 1) end slice[:single] = false t+=1 else raise(ArgumentError, "expected Fixnum or Range for slice component instead of #{v.class}") end if (slice[:coords][r] > shape_array[r] || slice[:coords][r] + slice[:lengths][r] > shape_array[r]) raise(RangeError, "slice is larger than matrix in dimension #{r} (slice component #{t})") end end return slice end |
#get_stride(nmatrix) ⇒ Object
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/nmatrix/jruby/slice.rb', line 59 def get_stride(nmatrix) stride = Array.new() (0...nmatrix.dim).each do |i| stride[i] = 1; (i+1...dim).each do |j| stride[i] *= nmatrix.shape[j] end end stride end |
#getrf! ⇒ Object
call-seq:
getrf! -> Array
LU factorization of a general M-by-N matrix A
using partial pivoting with row interchanges. The LU factorization is A = PLU, where P is a row permutation matrix, L is a lower triangular matrix with unit diagonals, and U is an upper triangular matrix (note that this convention is different from the clapack_getrf behavior, but matches the standard LAPACK getrf). A
is overwritten with the elements of L and U (the unit diagonal elements of L are not saved). P is not returned directly and must be constructed from the pivot array ipiv. The row indices in ipiv are indexed starting from 1. Only works for dense matrices.
-
Returns :
-
The IPIV vector. The L and U matrices are stored in A.
-
-
Raises :
-
StorageTypeError
-> ATLAS functions only work on dense matrices.
-
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/nmatrix/cruby/math.rb', line 53 def getrf! raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense? #For row-major matrices, clapack_getrf uses a different convention than #described above (U has unit diagonal elements instead of L and columns #are interchanged rather than rows). For column-major matrices, clapack #uses the stanard conventions. So we just transpose the matrix before #and after calling clapack_getrf. #Unfortunately, this is not a very good way, uses a lot of memory. temp = self.transpose ipiv = NMatrix::LAPACK::clapack_getrf(:col, self.shape[0], self.shape[1], temp, self.shape[0]) temp = temp.transpose self[0...self.shape[0], 0...self.shape[1]] = temp #for some reason, in clapack_getrf, the indices in ipiv start from 0 #instead of 1 as in LAPACK. ipiv.each_index { |i| ipiv[i]+=1 } return ipiv end |
#hconcat(*matrices) ⇒ Object
Horizontal concatenation with matrices
.
754 755 756 |
# File 'lib/nmatrix/nmatrix.rb', line 754 def hconcat(*matrices) concat(*matrices, :column) end |
#hermitian? ⇒ Boolean
150 151 152 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 150 def hermitian? return is_symmetric(true) end |
#hessenberg ⇒ Object
Reduce self to upper hessenberg form using householder transforms.
References
287 288 289 |
# File 'lib/nmatrix/math.rb', line 287 def hessenberg clone.hessenberg! end |
#hessenberg! ⇒ Object
Destructive version of #hessenberg
292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/nmatrix/math.rb', line 292 def hessenberg! raise ShapeError, "Trying to reduce non 2D matrix to hessenberg form" if shape.size != 2 raise ShapeError, "Trying to reduce non-square matrix to hessenberg form" if shape[0] != shape[1] raise StorageTypeError, "Matrix must be dense" if stype != :dense raise TypeError, "Works with float matrices only" unless [:float64,:float32].include?(dtype) __hessenberg__(self) self end |
#hypot(other, scalar = false) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/nmatrix/jruby/operators.rb', line 109 def hypot(other, scalar=false) result = create_dummy_nmatrix if scalar result.s = ArrayRealVector.new MathHelper.hypotScalar(other, @s.toArray) else if other.is_a? NMatrix result.s = ArrayRealVector.new MathHelper.hypot(other.s.toArray, @s.toArray) else result.s = ArrayRealVector.new MathHelper.hypotScalar(other, @s.toArray) end end result end |
#index(value) ⇒ Object
Returns the index of the first occurence of the specified value. Returns an array containing the position of the value, nil in case the value is not found.
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
# File 'lib/nmatrix/nmatrix.rb', line 1013 def index(value) index = nil self.each_with_indices do |yields| if yields.first == value yields.shift index = yields break end end index end |
#inf_matrix_norm(minus = false) ⇒ Object
Infinity norm: the maximum/minimum absolute row sum of the matrix
665 666 667 668 669 670 671 672 673 674 675 |
# File 'lib/nmatrix/math.rb', line 665 def inf_matrix_norm minus = false number_of_rows = self.rows row_sums = [] number_of_rows.times do |i| row_sums << self.row(i).inject(0) { |sum, number| sum += number.abs} end return row_sums.max unless minus return row_sums.min end |
#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
1005 1006 1007 1008 |
# File 'lib/nmatrix/nmatrix.rb', line 1005 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.
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 248 |
# File 'lib/nmatrix/enumerate.rb', line 218 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.dup 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:
340 341 342 343 344 |
# File 'lib/nmatrix/nmatrix.rb', line 340 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
358 359 360 |
# File 'lib/nmatrix/nmatrix.rb', line 358 def integer_dtype? [:byte, :int8, :int16, :int32, :int64].include?(self.dtype) end |
#invert ⇒ 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. Will be the same type as the input NMatrix,
except if the input is an integral dtype, in which case it will be a :float64 NMatrix.
-
-
Raises :
-
StorageTypeError
-> only implemented on dense matrices. -
ShapeError
-> matrix must be square.
-
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/nmatrix/math.rb', line 102 def invert #write this in terms of invert! so plugins will only have to overwrite #invert! and not invert if self.integer_dtype? cloned = self.cast(dtype: :float64) cloned.invert! else cloned = self.clone cloned.invert! 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.
-
Raises :
-
StorageTypeError
-> only implemented on dense matrices. -
ShapeError
-> matrix must be square. -
DataTypeError
-> cannot invert an integer matrix in-place.
-
77 78 79 80 81 82 83 84 |
# File 'lib/nmatrix/math.rb', line 77 def invert! raise(StorageTypeError, "invert only works on dense matrices currently") unless self.dense? raise(ShapeError, "Cannot invert non-square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1] raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype? #No internal implementation of getri, so use this other function __inverse__(self, true) end |
#is_ref? ⇒ Boolean
61 62 63 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 61 def is_ref? end |
#is_symmetric(hermitian) ⇒ Object
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 726 def is_symmetric(hermitian) is_symmetric = true if (@shape[0] == @shape[1] and @dim == 2) if @stype == :dense if (hermitian) #Currently, we are not dealing with complex matrices. eps = 0 is_symmetric = MatrixUtils.isSymmetric(self.twoDMat, eps) else eps = 0 is_symmetric = MatrixUtils.isSymmetric(self.twoDMat, eps) end else #TODO: Implement, at the very least, yale_is_symmetric. Model it after yale/transp.template.c. # raise Exception.new("symmetric? and hermitian? only implemented for dense currently") end end return is_symmetric ? true : false end |
#kron_prod(mat) ⇒ Object
Compute the Kronecker product of self
and other NMatrix
Arguments
* +mat+ - A 2D NMatrix object
Usage
a = NMatrix.new([2,2],[1,2,
3,4])
b = NMatrix.new([2,3],[1,1,1,
1,1,1], dtype: :float64)
a.kron_prod(b) # => [ [1.0, 1.0, 1.0, 2.0, 2.0, 2.0]
[1.0, 1.0, 1.0, 2.0, 2.0, 2.0]
[3.0, 3.0, 3.0, 4.0, 4.0, 4.0]
[3.0, 3.0, 3.0, 4.0, 4.0, 4.0] ]
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'lib/nmatrix/math.rb', line 432 def kron_prod(mat) unless self.dimensions==2 and mat.dimensions==2 raise ShapeError, "Implemented for 2D NMatrix objects only." end # compute the shape [n,m] of the product matrix n, m = self.shape[0]*mat.shape[0], self.shape[1]*mat.shape[1] # compute the entries of the product matrix kron_prod_array = [] if self.yale? # +:yale+ requires to get the row by copy in order to apply +#transpose+ to it self.each_row(getby=:copy) do |selfr| mat.each_row do |matr| kron_prod_array += (selfr.transpose.dot matr).to_flat_a end end else self.each_row do |selfr| mat.each_row do |matr| kron_prod_array += (selfr.transpose.dot matr).to_flat_a end end end NMatrix.new([n,m], kron_prod_array) end |
#last ⇒ Object
call-seq:
last -> Element of self.dtype
Returns the last element stored in an NMatrix
556 557 558 |
# File 'lib/nmatrix/nmatrix.rb', line 556 def last self[*Array.new(self.dim, -1)] end |
#laswp(ary, opts = {}) ⇒ 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
.
If :convention
is :lapack
, then ary
represents a sequence of pair-wise permutations which are performed successively. That is, the i’th entry of ary
is the index of the column to swap the i’th column with, having already applied all earlier swaps. This is the default.
If :convention
is :intuitive
, then ary
represents the order of columns after the permutation. That is, the i’th entry of ary
is the index of the column that will be in position i after the reordering (Matlab-like behaviour).
Not yet implemented for yale or list.
Arguments
-
ary
- An Array specifying the order of the columns. See above for details.
Options
-
:covention
- Possible values are:lapack
and:intuitive
. Default is:lapack
. See above for details.
582 583 584 |
# File 'lib/nmatrix/cruby/math.rb', line 582 def laswp(ary, opts={}) self.clone.laswp!(ary, opts) end |
#laswp!(ary, opts = {}) ⇒ 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 as an array ary
.
If :convention
is :lapack
, then ary
represents a sequence of pair-wise permutations which are performed successively. That is, the i’th entry of ary
is the index of the column to swap the i’th column with, having already applied all earlier swaps.
If :convention
is :intuitive
, then ary
represents the order of columns after the permutation. That is, the i’th entry of ary
is the index of the column that will be in position i after the reordering (Matlab-like behaviour). This is the default.
Not yet implemented for yale or list.
Arguments
-
ary
- An Array specifying the order of the columns. See above for details.
Options
-
:covention
- Possible values are:lapack
and:intuitive
. Default is:intuitive
. See above for details.
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/nmatrix/cruby/math.rb', line 535 def laswp!(ary, opts={}) raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense? opts = { convention: :intuitive }.merge(opts) if opts[:convention] == :intuitive if ary.length != ary.uniq.length raise(ArgumentError, "No duplicated entries in the order array are allowed under convention :intuitive") end n = self.shape[1] p = [] order = (0...n).to_a 0.upto(n-2) do |i| p[i] = order.index(ary[i]) order[i], order[p[i]] = order[p[i]], order[i] end p[n-1] = n-1 else p = ary end NMatrix::LAPACK::laswp(self, p) 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.
-
890 891 892 893 894 895 896 897 898 899 900 901 902 |
# File 'lib/nmatrix/nmatrix.rb', line 890 def layer(layer_number, get_by = :copy) layer = rank(2, layer_number, get_by) if jruby? nmatrix = NMatrix.new :copy nmatrix.shape = layer.shape nmatrix.s = layer.s return nmatrix else layer end end |
#ldexp(other, scalar = false) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/nmatrix/jruby/operators.rb', line 95 def ldexp(other, scalar=false) result = create_dummy_nmatrix if scalar result.s = ArrayRealVector.new MathHelper.ldexpScalar(other, @s.toArray) else if other.is_a? NMatrix result.s = ArrayRealVector.new MathHelper.ldexp(other.s.toArray, @s.toArray) else result.s = ArrayRealVector.new MathHelper.ldexpScalar2(other, @s.toArray) end end result end |
#least_squares(b, tolerance: 10e-6) ⇒ Object
call-seq:
least_squares(b) -> NMatrix
least_squares(b, tolerance: 10e-10) -> NMatrix
Provides the linear least squares approximation of an under-determined system using QR factorization provided that the matrix is not rank-deficient.
Only works for dense matrices.
-
Arguments :
-
b
-> The solution column vector NMatrix of A * X = b. -
tolerance:
-> Absolute tolerance to check if a diagonal element in A = QR is near 0
-
-
Returns :
-
NMatrix that is a column vector with the LLS solution
-
-
Raises :
-
ArgumentError
-> least squares approximation only works for non-complex types -
ShapeError
-> system must be under-determined ( rows > columns )
-
Examples :-
a = NMatrix.new([3,2], [2.0, 0, -1, 1, 0, 2])
b = NMatrix.new([3,1], [1.0, 0, -1])
a.least_squares(b)
=>[
[ 0.33333333333333326 ]
[ -0.3333333333333334 ]
]
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/nmatrix/cruby/math.rb', line 412 def least_squares(b, tolerance: 10e-6) raise(ArgumentError, "least squares approximation only works for non-complex types") if self.complex_dtype? rows, columns = self.shape raise(ShapeError, "system must be under-determined ( rows > columns )") unless rows > columns #Perform economical QR factorization r = self.clone tau = r.geqrf! q_transpose_b = r.ormqr(tau, :left, :transpose, b) #Obtain R from geqrf! intermediate r[0...columns, 0...columns].upper_triangle! r[columns...rows, 0...columns] = 0 diagonal = r.diagonal raise(ArgumentError, "rank deficient matrix") if diagonal.any? { |x| x == 0 } if diagonal.any? { |x| x.abs < tolerance } warn "warning: A diagonal element of R in A = QR is close to zero ;" << " indicates a possible loss of precision" end # Transform the system A * X = B to R1 * X = B2 where B2 = Q1_t * B r1 = r[0...columns, 0...columns] b2 = q_transpose_b[0...columns] nrhs = b2.shape[1] #Solve the upper triangular system NMatrix::BLAS::cblas_trsm(:row, :left, :upper, false, :nounit, r1.shape[0], nrhs, 1.0, r1, r1.shape[0], b2, nrhs) b2 end |
#list? ⇒ Boolean
call-seq:
m.list? -> true or false
Determine if m
is a list-of-lists matrix.
139 |
# File 'lib/nmatrix/shortcuts.rb', line 139 def list?; return stype == :list; end |
#log(val = :natural) ⇒ Object
203 204 205 206 207 208 209 210 211 |
# File 'lib/nmatrix/jruby/operators.rb', line 203 def log(val = :natural) result = create_dummy_nmatrix if val == :natural result.s = @s.copy.mapToSelf(Log.new()) else result.s = ArrayRealVector.new MathHelper.log(val, @s.toArray) end result end |
#log10 ⇒ Object
217 218 219 220 221 |
# File 'lib/nmatrix/jruby/operators.rb', line 217 def log10 result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Log10.new()) result end |
#log2 ⇒ Object
213 214 215 |
# File 'lib/nmatrix/jruby/operators.rb', line 213 def log2 self.log(2) end |
#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.
-
837 838 839 840 841 842 843 844 845 846 847 848 849 850 |
# File 'lib/nmatrix/nmatrix.rb', line 837 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.
-
866 867 868 869 870 871 872 873 874 875 |
# File 'lib/nmatrix/nmatrix.rb', line 866 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 78 |
# File 'lib/nmatrix/enumerate.rb', line 72 def map(&bl) return enum_for(:map) unless block_given? # NMatrix-jruby currently supports only doubles cp = jruby? ? self : self.cast(dtype: :object) cp.map!(&bl) cp end |
#map! ⇒ Object
call-seq:
map! -> Enumerator
map! { |elem| block } -> NMatrix
Maps in place.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/nmatrix/enumerate.rb', line 88 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 55 56 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 54 def map_stored end |
#matrix_norm(type = 2) ⇒ Object
call-seq:
matrix_norm -> Numeric
Calculates the selected norm (defaults to 2-norm) of a 2D matrix.
This should be used for small or medium sized matrices.
For greater matrices, there should be a separate implementation where
the norm is estimated rather than computed, for the sake of computation speed.
Currently implemented norms are 1-norm, 2-norm, Frobenius, Infinity.
A minus on the 1, 2 and inf norms returns the minimum instead of the maximum value.
Tested mainly with dense matrices. Further checks and modifications might
be necessary for sparse matrices.
-
Returns :
-
The selected norm of the matrix.
-
Raises :
-
NotImplementedError
-> norm can be calculated only for 2D matrices -
ArgumentError
-> unrecognized norm
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/nmatrix/math.rb', line 327 def matrix_norm type = 2 raise(NotImplementedError, "norm can be calculated only for 2D matrices") unless self.dim == 2 raise(NotImplementedError, "norm only implemented for dense storage") unless self.stype == :dense raise(ArgumentError, "norm not defined for byte dtype")if self.dtype == :byte case type when nil, 2, -2 return self.two_matrix_norm (type == -2) when 1, -1 return self.one_matrix_norm (type == -1) when :frobenius, :fro return self.fro_matrix_norm when :infinity, :inf, :'-inf', :'-infinity' return self.inf_matrix_norm (type == :'-inf' || type == :'-infinity') else raise ArgumentError.new("argument must be a valid integer or symbol") end end |
#matrix_solve(rhs) ⇒ Object
discussion in github.com/SciRuby/nmatrix/issues/374
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/nmatrix/jruby/decomposition.rb', line 5 def matrix_solve rhs if rhs.shape[1] > 1 nmatrix = NMatrix.new :copy nmatrix.shape = rhs.shape res = [] #Solve a matrix and store the vectors in a matrix (0...rhs.shape[1]).each do |i| res << self.solve(rhs.col(i)).s.toArray.to_a end #res is in col major format result = ArrayGenerator.getArrayColMajorDouble res.to_java :double, rhs.shape[0], rhs.shape[1] nmatrix.s = ArrayRealVector.new result return nmatrix else return self.solve rhs end end |
#max(dimen = 0) ⇒ Object
call-seq:
max() -> NMatrix
max(dimen) -> NMatrix
Calculates the maximum along the specified dimension.
545 546 547 548 549 550 551 552 553 |
# File 'lib/nmatrix/math.rb', line 545 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.
490 491 492 493 494 495 496 497 498 |
# File 'lib/nmatrix/math.rb', line 490 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.
526 527 528 529 530 531 532 533 534 |
# File 'lib/nmatrix/math.rb', line 526 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.
699 700 701 702 |
# File 'lib/nmatrix/cruby/math.rb', line 699 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.
442 443 444 |
# File 'lib/nmatrix/nmatrix.rb', line 442 def nvector? self.effective_dim < self.dim end |
#object_dtype? ⇒ Boolean
call-seq:
object_dtype?() -> Boolean
Checks if dtype is a ruby object
387 388 389 |
# File 'lib/nmatrix/nmatrix.rb', line 387 def object_dtype? dtype == :object end |
#offset ⇒ Object
47 48 49 50 51 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 47 def offset # ArrayRealVector takes care of the offset value when indexing a Vector. # Hence, return 0. 0 end |
#one_matrix_norm(minus = false) ⇒ Object
1-norm: the maximum/minimum absolute column sum of the matrix
651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/nmatrix/math.rb', line 651 def one_matrix_norm minus = false #TODO: change traversing method for sparse matrices number_of_columns = self.cols col_sums = [] number_of_columns.times do |i| col_sums << self.col(i).inject(0) { |sum, number| sum += number.abs} end return col_sums.max unless minus return col_sums.min end |
#ormqr(tau, side = :left, transpose = false, c = nil) ⇒ Object
call-seq:
ormqr(tau) -> NMatrix
ormqr(tau, side, transpose, c) -> NMatrix
Returns the product Q * c or c * Q after a call to geqrf! used in QR factorization. c
is overwritten with the elements of the result NMatrix if supplied. Q is the orthogonal matrix represented by tau and the calling NMatrix
Only works on float types, use unmqr for complex types.
Arguments
-
tau
- vector containing scalar factors of elementary reflectors -
side
- direction of multiplication [:left, :right] -
transpose
- apply Q with or without transpose [false, :transpose] -
c
- NMatrix multplication argument that is overwritten, no argument assumes c = identity -
Returns :
-
Q * c or c * Q Where Q may be transposed before multiplication.
-
-
Raises :
-
StorageTypeError
-> LAPACK functions only work on dense matrices. -
TypeError
-> Works only on floating point matrices, use unmqr for complex types -
TypeError
-> c must have the same dtype as the calling NMatrix
-
133 134 135 136 137 |
# File 'lib/nmatrix/cruby/math.rb', line 133 def ormqr(tau, side=:left, transpose=false, c=nil) # The real implementation is in lib/nmatrix/lapacke.rb raise(NotImplementedError, "ormqr requires the nmatrix-lapacke gem") end |
#pinv(tolerance = 1e-15) ⇒ Object Also known as: pseudo_inverse, pseudoinverse
call-seq:
pinv -> NMatrix
Compute the Moore-Penrose pseudo-inverse of a matrix using its singular value decomposition (SVD).
This function requires the nmatrix-atlas gem installed.
-
Arguments :
-
tolerance(optional) -> Cutoff for small singular values.
-
Returns :
-
Pseudo-inverse matrix.
-
-
Raises :
-
NotImplementedError
-> If called without nmatrix-atlas or nmatrix-lapacke gem. -
TypeError
-> If called without float or complex data type.
-
-
Examples :
a = NMatrix.new([2,2],[1,2,
3,4], dtype: :float64)
a.pinv # => [ [-2.0000000000000018, 1.0000000000000007]
[1.5000000000000016, -0.5000000000000008] ]
b = NMatrix.new([4,1],[1,2,3,4], dtype: :float64)
b.pinv # => [ [ 0.03333333, 0.06666667, 0.99999999, 0.13333333] ]
References
-
Strang, Linear Algebra and Its Applications, 2nd Ed., Orlando, FL, Academic Press
-
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/nmatrix/math.rb', line 202 def pinv(tolerance = 1e-15) raise DataTypeError, "pinv works only with matrices of float or complex data type" unless [:float32, :float64, :complex64, :complex128].include?(dtype) if self.complex_dtype? u, s, vt = self.complex_conjugate.gesvd # singular value decomposition else u, s, vt = self.gesvd end rows = self.shape[0] cols = self.shape[1] if rows < cols u_reduced = u vt_reduced = vt[0..rows - 1, 0..cols - 1].transpose else u_reduced = u[0..rows - 1, 0..cols - 1] vt_reduced = vt.transpose end largest_singular_value = s.max.to_f cutoff = tolerance * largest_singular_value (0...[rows, cols].min).each do |i| s[i] = 1 / s[i] if s[i] > cutoff s[i] = 0 if s[i] <= cutoff end multiplier = u_reduced.dot(NMatrix.diagonal(s.to_a)).transpose vt_reduced.dot(multiplier) end |
#positive_definite? ⇒ Boolean
call-seq:
positive_definite? -> boolean
A matrix is positive definite if it’s symmetric and all its eigenvalues are positive
-
Returns :
-
A boolean value telling if the NMatrix is positive definite or not.
-
-
Raises :
-
ShapeError
-> Must be used on square matrices.
-
688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/nmatrix/math.rb', line 688 def positive_definite? raise(ShapeError, "positive definite calculated only for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1] cond = 0 while cond != self.cols if self[0..cond, 0..cond].det <= 0 return false end cond += 1 end true end |
#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
. The result will be written in either the upper or lower triangular portion of the matrix, depending on whether the argument is :upper
or :lower
. Also the function only reads in the upper or lower part of the matrix, so it doesn’t actually have to be symmetric/Hermitian. However, if the matrix (i.e. the symmetric matrix implied by the lower/upper half) is not positive-definite, the function will return nonsense.
This functions requires either the nmatrix-atlas or nmatrix-lapacke gem installed.
-
Returns : the triangular portion specified by the parameter
-
Raises :
-
StorageTypeError
-> ATLAS functions only work on dense matrices. -
ShapeError
-> Must be square. -
NotImplementedError
-> If called without nmatrix-atlas or nmatrix-lapacke gem
-
195 196 197 198 |
# File 'lib/nmatrix/cruby/math.rb', line 195 def potrf!(which) # The real implementation is in the plugin files. raise(NotImplementedError, "potrf! requires either the nmatrix-atlas or nmatrix-lapacke gem") end |
#potrf_lower! ⇒ Object
204 205 206 |
# File 'lib/nmatrix/cruby/math.rb', line 204 def potrf_lower! potrf! :lower end |
#potrf_upper! ⇒ Object
200 201 202 |
# File 'lib/nmatrix/cruby/math.rb', line 200 def potrf_upper! potrf! :upper end |
#pow(n) ⇒ Object
Raise a square matrix to a power. Be careful of numeric overflows! In case n is 0, an identity matrix of the same dimension is returned. In case of negative n, the matrix is inverted and the absolute value of n taken for computing the power.
Arguments
-
n
- Integer to which self is to be raised.
References
-
R.G Dromey - How to Solve it by Computer. Link -
http://www.amazon.com/Solve-Computer-Prentice-Hall-International-Science/dp/0134340019/ref=sr_1_1?ie=UTF8&qid=1422605572&sr=8-1&keywords=how+to+solve+it+by+computer
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/nmatrix/math.rb', line 387 def pow n raise ShapeError, "Only works with 2D square matrices." if shape[0] != shape[1] or shape.size != 2 raise TypeError, "Only works with integer powers" unless n.is_a?(Integer) sequence = (integer_dtype? ? self.cast(dtype: :int64) : self).clone product = NMatrix.eye shape[0], dtype: sequence.dtype, stype: sequence.stype if n == 0 return NMatrix.eye(shape, dtype: dtype, stype: stype) elsif n == 1 return sequence elsif n < 0 n = n.abs sequence.invert! product = NMatrix.eye shape[0], dtype: sequence.dtype, stype: sequence.stype end # Decompose n to reduce the number of multiplications. while n > 0 product = product.dot(sequence) if n % 2 == 1 n = n / 2 sequence = sequence.dot(sequence) end product end |
#pretty_print(q) ⇒ Object
TODO: Make this actually pretty.
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 211 212 213 214 215 |
# File 'lib/nmatrix/nmatrix.rb', line 175 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, " [", "]\n") do q.seplist(row.to_a, -> { q.text ", " }, :each_with_index) do |v,j| q.text v.inspect.rjust(longest[j]) end end q.breakable unless i + 1 == self.shape[0] 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)
494 495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/nmatrix/nmatrix.rb', line 494 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 |
#repeat(count, axis) ⇒ Object
call-seq:
repeat(count, axis) -> NMatrix
-
Arguments :
-
count
-> how many times NMatrix should be repeated -
axis
-> index of axis along which NMatrix should be repeated
-
-
Returns :
-
NMatrix created by repeating the existing one along an axis
-
-
Examples :
m = NMatrix.new([2, 2], [1, 2, 3, 4]) m.repeat(2, 0).to_a #<= [[1, 2], [3, 4], [1, 2], [3, 4]] m.repeat(2, 1).to_a #<= [[1, 2, 1, 2], [3, 4, 3, 4]]
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
# File 'lib/nmatrix/nmatrix.rb', line 1055 def repeat(count, axis) raise(ArgumentError, 'Matrix should be repeated at least 2 times.') if count < 2 new_shape = shape new_shape[axis] *= count new_matrix = NMatrix.new(new_shape, dtype: dtype) slice = new_shape.map { |axis_size| 0...axis_size } start = 0 count.times do slice[axis] = start...(start += shape[axis]) new_matrix[*slice] = self end new_matrix 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.
-
573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'lib/nmatrix/nmatrix.rb', line 573 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.
-
598 599 600 601 602 603 604 605 606 607 608 609 |
# File 'lib/nmatrix/nmatrix.rb', line 598 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, include_all = false) ⇒ Boolean
:nodoc:
988 989 990 991 992 993 994 995 996 |
# File 'lib/nmatrix/nmatrix.rb', line 988 def respond_to?(method, include_all = false) #: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 end end |
#round ⇒ Object
143 144 145 146 147 148 149 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 143 def round result = create_dummy_nmatrix # Need to be changed later result.dtype = :int64 result.s = ArrayRealVector.new MathHelper.round(@s.toArray) result end |
#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.
-
546 547 548 |
# File 'lib/nmatrix/nmatrix.rb', line 546 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.
269 270 271 |
# File 'lib/nmatrix/nmatrix.rb', line 269 def rows shape[0] end |
#scale(alpha, incx = 1, n = nil) ⇒ Object
call-seq:
scale -> NMatrix
Arguments
- +alpha+ -> Scalar value used in the operation.
- +inc+ -> Increment used in the scaling function. Should generally be 1.
- +n+ -> Number of elements of +vector+.
Return the scaling result of the matrix. BLAS scal will be invoked if provided.
737 738 739 |
# File 'lib/nmatrix/cruby/math.rb', line 737 def scale(alpha, incx=1, n=nil) return self.clone.scale!(alpha, incx, n) end |
#scale!(alpha, incx = 1, n = nil) ⇒ Object
call-seq:
scale! -> NMatrix
Arguments
- +alpha+ -> Scalar value used in the operation.
- +inc+ -> Increment used in the scaling function. Should generally be 1.
- +n+ -> Number of elements of +vector+.
This is a destructive method, modifying the source NMatrix. See also #scale. Return the scaling result of the matrix. BLAS scal will be invoked if provided.
717 718 719 720 721 722 723 724 |
# File 'lib/nmatrix/cruby/math.rb', line 717 def scale!(alpha, incx=1, n=nil) raise(DataTypeError, "Incompatible data type for the scaling factor") unless NMatrix::upcast(self.dtype, NMatrix::min_dtype(alpha)) == self.dtype return NMatrix::BLAS::scal(alpha, self, incx, self.size / incx) if NMatrix::BLAS.method_defined? :scal self.each_stored_with_indices do |e, *i| self[*i] = e*alpha end end |
#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.
933 934 935 936 937 |
# File 'lib/nmatrix/nmatrix.rb', line 933 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.
915 916 917 918 919 920 921 |
# File 'lib/nmatrix/nmatrix.rb', line 915 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
123 124 125 126 127 |
# File 'lib/nmatrix/jruby/operators.rb', line 123 def sin result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Sin.new()) result end |
#sinh ⇒ Object
159 160 161 162 163 |
# File 'lib/nmatrix/jruby/operators.rb', line 159 def sinh result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Sinh.new()) result end |
#size ⇒ Object
call-seq:
size -> Fixnum
Returns the total size of the NMatrix based on its shape.
426 427 428 |
# File 'lib/nmatrix/nmatrix.rb', line 426 def size NMatrix.size(self.shape) end |
#slice(*args) ⇒ Object
59 60 61 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 59 def slice(*args) return xslice(args) end |
#slice_copy(src, dest, lengths, pdest, psrc, n) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/nmatrix/jruby/slice.rb', line 168 def slice_copy(src, dest,lengths, pdest, psrc,n) if @dim-n>1 (0...lengths[n]).each do |i| slice_copy(src, dest, lengths,pdest+dest[:stride][n]*i,psrc+src[:stride][n]*i,n+1) end else (0...dest[:shape][n]).each do |p| dest[:elements][p+pdest] = src[:elements][p+psrc] end end dest[:elements] end |
#slice_set(dest, lengths, pdest, rank, v, v_size, v_offset) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/nmatrix/jruby/slice.rb', line 201 def slice_set(dest, lengths, pdest, rank, v, v_size, v_offset) if (dim - rank > 1) (0...lengths[rank]).each do |i| slice_set(dest, lengths, pdest + dest[:stride][rank] * i, rank + 1, v, v_size, v_offset); end else (0...lengths[rank]).each do |p| v_offset %= v_size if(v_offset >= v_size) # elem = dest[:elements] # elem[p + pdest] = v[v_offset] if @dtype == :object @s[p + pdest] = v[v_offset] else @s.setEntry(p + pdest, v[v_offset]) end v_offset += 1 end end end |
#solve(b, opts = {}) ⇒ Object
Solve the matrix equation AX = B, where A is self
, B is the first argument, and X is returned. A must be a nxn square matrix, while B must be nxm. Only works with dense matrices and non-integer, non-object data types.
Arguments
-
b
- the right hand side
Options
-
form
- Signifies the form of the matrix A in the linear system AX=B. If not set then it defaults to:general
, which uses an LU solver. Other possible values are:lower_tri
,:upper_tri
and:pos_def
(alternatively, non-abbreviated symbols:lower_triangular
,:upper_triangular
, and:positive_definite
can be used. If:lower_tri
or:upper_tri
is set, then a specialized linear solver for linear systems AX=B with a lower or upper triangular matrix A is used. If:pos_def
is chosen, then the linear system is solved via the Cholesky factorization. Note that when:lower_tri
or:upper_tri
is used, then the algorithm just assumes that all entries in the lower/upper triangle of the matrix are zeros without checking (which can be useful in certain applications).
Usage
a = NMatrix.new [2,2], [3,1,1,2], dtype: dtype
b = NMatrix.new [2,1], [9,8], dtype: dtype
a.solve(b)
# solve an upper triangular linear system more efficiently:
require 'benchmark'
require 'nmatrix/lapacke'
rand_mat = NMatrix.random([10000, 10000], dtype: :float64)
a = rand_mat.triu
b = NMatrix.random([10000, 10], dtype: :float64)
Benchmark.bm(10) do |bm|
bm.report('general') { a.solve(b) }
bm.report('upper_tri') { a.solve(b, form: :upper_tri) }
end
# user system total real
# general 73.170000 0.670000 73.840000 ( 73.810086)
# upper_tri 0.180000 0.000000 0.180000 ( 0.182491)
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/nmatrix/cruby/math.rb', line 334 def solve(b, opts = {}) 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? opts = { form: :general }.merge(opts) x = b.clone n = self.shape[0] nrhs = b.shape[1] case opts[:form] when :general clone = self.clone ipiv = NMatrix::LAPACK.clapack_getrf(:row, n, n, clone, n) # When we call clapack_getrs with :row, actually only the first matrix # (i.e. clone) is interpreted as row-major, while the other matrix (x) # is interpreted as column-major. See here: http://math-atlas.sourceforge.net/faq.html#RowSolve # So we must transpose x before and after # calling it. x = x.transpose NMatrix::LAPACK.clapack_getrs(:row, :no_transpose, n, nrhs, clone, n, ipiv, x, n) x.transpose when :upper_tri, :upper_triangular raise(ArgumentError, "upper triangular solver does not work with complex dtypes") if complex_dtype? or b.complex_dtype? # this is the correct function call; see https://github.com/SciRuby/nmatrix/issues/374 NMatrix::BLAS::cblas_trsm(:row, :left, :upper, false, :nounit, n, nrhs, 1.0, self, n, x, nrhs) x when :lower_tri, :lower_triangular raise(ArgumentError, "lower triangular solver does not work with complex dtypes") if complex_dtype? or b.complex_dtype? NMatrix::BLAS::cblas_trsm(:row, :left, :lower, false, :nounit, n, nrhs, 1.0, self, n, x, nrhs) x when :pos_def, :positive_definite u, l = self.factorize_cholesky z = l.solve(b, form: :lower_tri) u.solve(z, form: :upper_tri) else raise(ArgumentError, "#{opts[:form]} is not a valid form option") end end |
#sorted_indices ⇒ Object
call-seq:
sorted_indices -> Array
Returns an array of the indices ordered by value sorted.
946 947 948 949 950 |
# File 'lib/nmatrix/nmatrix.rb', line 946 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
223 224 225 226 227 |
# File 'lib/nmatrix/jruby/operators.rb', line 223 def sqrt result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Sqrt.new()) result end |
#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.
590 591 592 |
# File 'lib/nmatrix/math.rb', line 590 def std(dimen=0) variance(dimen).sqrt end |
#sum(dimen = 0) ⇒ Object Also known as: cumsum
call-seq:
sum() -> NMatrix
cumsum() -> NMatrix
sum(dimen) -> NMatrix
cumsum(dimen) -> NMatrix
Calculates the sum along the specified dimension.
510 511 512 513 514 |
# File 'lib/nmatrix/math.rb', line 510 def sum(dimen=0) inject_rank(dimen, 0.0) do |sum, sub_mat| sum + sub_mat end end |
#supershape(s) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 49 def supershape s if (s[:src] == @s) return shape # easy case (not a slice) else @s = s[:src] end new_shape = Array.new(dim) (0...dim).each do |index| new_shape[index] = shape[index] end return new_shape end |
#symmetric? ⇒ Boolean
149 150 151 |
# File 'ext/nmatrix/ruby_nmatrix.c', line 149 def symmetric? return is_symmetric(false) end |
#tan ⇒ Object
135 136 137 138 139 |
# File 'lib/nmatrix/jruby/operators.rb', line 135 def tan result = create_dummy_nmatrix result.s = @s.copy.mapToSelf(Tan.new()) result end |
#tanh ⇒ Object
171 172 173 174 175 176 177 |
# File 'lib/nmatrix/jruby/operators.rb', line 171 def tanh result = NMatrix.new(:copy) result.shape = @shape result.dim = @dim result.s = @s.copy.mapToSelf(Tanh.new()) result end |
#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
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/nmatrix/nmatrix.rb', line 464 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.
401 402 403 404 |
# File 'lib/nmatrix/nmatrix.rb', line 401 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.
413 414 415 416 417 |
# File 'lib/nmatrix/nmatrix.rb', line 413 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.
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/nmatrix/nmatrix.rb', line 319 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:
431 432 433 |
# File 'lib/nmatrix/nmatrix.rb', line 431 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)
-
471 472 473 474 475 476 477 |
# File 'lib/nmatrix/math.rb', line 471 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.
-
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
# File 'lib/nmatrix/nmatrix.rb', line 625 def transpose(permute = nil) if permute.nil? if self.dim == 1 return self.clone elsif self.dim == 2 new_shape = [self.shape[1], self.shape[0]] else raise(ArgumentError, "need permutation array of size #{self.dim}") end elsif !permute.is_a?(Array) || 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 if jruby? nmatrix = NMatrix.new :copy nmatrix.shape = [@shape[1],@shape[0]] twoDMat = self.twoDMat.transpose nmatrix.s = ArrayRealVector.new(ArrayGenerator.getArrayDouble(twoDMat.getData(), shape[1],shape[0])) return nmatrix else self.clone_transpose end end end |
#two_matrix_norm(minus = false) ⇒ Object
2-norm: the largest/smallest singular value of the matrix
640 641 642 643 644 645 646 647 648 |
# File 'lib/nmatrix/math.rb', line 640 def two_matrix_norm minus = false self_cast = self.cast(:dtype => :float64) #TODO: confirm if this is the desired svd calculation svd = self_cast.gesvd return svd[1][0, 0] unless minus return svd[1][svd[1].rows-1, svd[1].cols-1] end |
#twoDMat ⇒ Object
130 131 132 |
# File 'lib/nmatrix/jruby/nmatrix_java.rb', line 130 def twoDMat return MatrixUtils.createRealMatrix MatrixGenerator.getMatrixDouble(self.s.toArray, @shape[0], @shape[1]) end |
#unmqr(tau, side = :left, transpose = false, c = nil) ⇒ Object
call-seq:
unmqr(tau) -> NMatrix
unmqr(tau, side, transpose, c) -> NMatrix
Returns the product Q * c or c * Q after a call to geqrf! used in QR factorization. c
is overwritten with the elements of the result NMatrix if it is supplied. Q is the orthogonal matrix represented by tau and the calling NMatrix
Only works on complex types, use ormqr for float types.
Arguments
-
tau
- vector containing scalar factors of elementary reflectors -
side
- direction of multiplication [:left, :right] -
transpose
- apply Q as Q or its complex conjugate [false, :complex_conjugate] -
c
- NMatrix multplication argument that is overwritten, no argument assumes c = identity -
Returns :
-
Q * c or c * Q Where Q may be transformed to its complex conjugate before multiplication.
-
-
Raises :
-
StorageTypeError
-> LAPACK functions only work on dense matrices. -
TypeError
-> Works only on floating point matrices, use unmqr for complex types -
TypeError
-> c must have the same dtype as the calling NMatrix
-
167 168 169 170 |
# File 'lib/nmatrix/cruby/math.rb', line 167 def unmqr(tau, side=:left, transpose=false, c=nil) # The real implementation is in lib/nmatrix/lapacke.rb raise(NotImplementedError, "unmqr requires the nmatrix-lapacke gem") 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.
-
782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
# File 'lib/nmatrix/nmatrix.rb', line 782 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.
-
811 812 813 814 815 816 817 818 819 820 |
# File 'lib/nmatrix/nmatrix.rb', line 811 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.
567 568 569 570 571 572 573 574 575 576 |
# File 'lib/nmatrix/math.rb', line 567 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
.
759 760 761 |
# File 'lib/nmatrix/nmatrix.rb', line 759 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?
452 453 454 |
# File 'lib/nmatrix/nmatrix.rb', line 452 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);
|
#xslice(args) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/nmatrix/jruby/slice.rb', line 70 def xslice(args) result = nil if self.dim < args.length raise(ArgumentError,"wrong number of arguments (#{args} for #{effective_dim(self)})") else result = Array.new() slice = get_slice(@dim, args, @shape) stride = get_stride(self) if slice[:single] if (@dtype == :object) result = @s[dense_storage_get(slice,stride)] else s = @s.toArray().to_a result = @s.getEntry(dense_storage_get(slice,stride)) end else result = dense_storage_get(slice,stride) end end return result end |
#xslice_ref(args) ⇒ Object
its by ref
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/nmatrix/jruby/slice.rb', line 95 def xslice_ref(args) result = nil if self.dim < args.length raise(ArgumentError,"wrong number of arguments (#{args} for #{effective_dim(self)})") else result = Array.new() slice = get_slice(@dim, args, @shape) stride = get_stride(self) if slice[:single] if (@dtype == :object) result = @s[dense_storage_get(slice,stride)] else result = @s.getEntry(dense_storage_get(slice,stride)) end else result = dense_storage_ref(slice,stride) end end return result end |
#yale? ⇒ Boolean
call-seq:
m.yale? -> true or false
Determine if m
is a Yale matrix.
133 |
# File 'lib/nmatrix/shortcuts.rb', line 133 def yale?; return stype == :yale; end |