nmatrix-lapacke 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/nmatrix/data/complex.h +364 -0
- data/ext/nmatrix/data/data.h +638 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +389 -0
- data/ext/nmatrix/math/asum.h +120 -0
- data/ext/nmatrix/math/cblas_enums.h +36 -0
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +241 -0
- data/ext/nmatrix/math/gemv.h +178 -0
- data/ext/nmatrix/math/getrf.h +255 -0
- data/ext/nmatrix/math/getrs.h +121 -0
- data/ext/nmatrix/math/imax.h +79 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +49 -0
- data/ext/nmatrix/math/math.h +744 -0
- data/ext/nmatrix/math/nrm2.h +160 -0
- data/ext/nmatrix/math/rot.h +117 -0
- data/ext/nmatrix/math/rotg.h +106 -0
- data/ext/nmatrix/math/scal.h +71 -0
- data/ext/nmatrix/math/trsm.h +332 -0
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.h +408 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/storage/common.h +176 -0
- data/ext/nmatrix/storage/dense/dense.h +128 -0
- data/ext/nmatrix/storage/list/list.h +137 -0
- data/ext/nmatrix/storage/storage.h +98 -0
- data/ext/nmatrix/storage/yale/class.h +1139 -0
- data/ext/nmatrix/storage/yale/iterators/base.h +142 -0
- data/ext/nmatrix/storage/yale/iterators/iterator.h +130 -0
- data/ext/nmatrix/storage/yale/iterators/row.h +449 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +139 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +168 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +123 -0
- data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
- data/ext/nmatrix/storage/yale/yale.h +202 -0
- data/ext/nmatrix/types.h +54 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.h +143 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/ext/nmatrix_lapacke/extconf.rb +200 -0
- data/ext/nmatrix_lapacke/lapacke.cpp +100 -0
- data/ext/nmatrix_lapacke/lapacke/include/lapacke.h +16445 -0
- data/ext/nmatrix_lapacke/lapacke/include/lapacke_config.h +119 -0
- data/ext/nmatrix_lapacke/lapacke/include/lapacke_mangling.h +17 -0
- data/ext/nmatrix_lapacke/lapacke/include/lapacke_mangling_with_flags.h +17 -0
- data/ext/nmatrix_lapacke/lapacke/include/lapacke_utils.h +579 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeev.c +89 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeev_work.c +141 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesdd.c +106 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesdd_work.c +158 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesvd.c +94 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesvd_work.c +149 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrf.c +51 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrf_work.c +83 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetri.c +77 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetri_work.c +89 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrs.c +56 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrs_work.c +102 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrf_work.c +82 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotri.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotri_work.c +82 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrs.c +55 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrs_work.c +101 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeev.c +78 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeev_work.c +136 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesdd.c +88 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesdd_work.c +153 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesvd.c +83 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesvd_work.c +144 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrf_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetri.c +75 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetri_work.c +87 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrs.c +55 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrs_work.c +99 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrf_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotri.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotri_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrs.c +54 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrs_work.c +97 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeev.c +78 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeev_work.c +134 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesdd.c +88 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesdd_work.c +152 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesvd.c +83 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesvd_work.c +143 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrf_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetri.c +75 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetri_work.c +87 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrs.c +55 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrs_work.c +99 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrf_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotri.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotri_work.c +81 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrs.c +54 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrs_work.c +97 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeev.c +89 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeev_work.c +141 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesdd.c +106 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesdd_work.c +158 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesvd.c +94 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesvd_work.c +149 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrf.c +51 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrf_work.c +83 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetri.c +77 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetri_work.c +89 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrs.c +56 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrs_work.c +102 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrf.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrf_work.c +82 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotri.c +50 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotri_work.c +82 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrs.c +55 -0
- data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrs_work.c +101 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cge_nancheck.c +62 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cge_trans.c +65 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cpo_nancheck.c +43 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cpo_trans.c +45 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ctr_nancheck.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ctr_trans.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dge_nancheck.c +62 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dge_trans.c +65 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dpo_nancheck.c +43 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dpo_trans.c +45 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dtr_nancheck.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dtr_trans.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_lsame.c +41 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_sge_nancheck.c +62 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_sge_trans.c +65 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_spo_nancheck.c +43 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_spo_trans.c +45 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_str_nancheck.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_str_trans.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_xerbla.c +46 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zge_nancheck.c +62 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zge_trans.c +65 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zpo_nancheck.c +43 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zpo_trans.c +45 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ztr_nancheck.c +85 -0
- data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ztr_trans.c +85 -0
- data/ext/nmatrix_lapacke/lapacke_nmatrix.h +16 -0
- data/ext/nmatrix_lapacke/make_lapacke_cpp.rb +9 -0
- data/ext/nmatrix_lapacke/math_lapacke.cpp +967 -0
- data/ext/nmatrix_lapacke/math_lapacke/cblas_local.h +576 -0
- data/ext/nmatrix_lapacke/math_lapacke/cblas_templates_lapacke.h +51 -0
- data/ext/nmatrix_lapacke/math_lapacke/lapacke_templates.h +356 -0
- data/ext/nmatrix_lapacke/nmatrix_lapacke.cpp +42 -0
- data/lib/nmatrix/lapack_ext_common.rb +69 -0
- data/lib/nmatrix/lapacke.rb +213 -0
- data/spec/00_nmatrix_spec.rb +730 -0
- data/spec/01_enum_spec.rb +190 -0
- data/spec/02_slice_spec.rb +389 -0
- data/spec/03_nmatrix_monkeys_spec.rb +78 -0
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +193 -0
- data/spec/elementwise_spec.rb +303 -0
- data/spec/homogeneous_spec.rb +99 -0
- data/spec/io/fortran_format_spec.rb +88 -0
- data/spec/io/harwell_boeing_spec.rb +98 -0
- data/spec/io/test.rua +9 -0
- data/spec/io_spec.rb +149 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +730 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/plugins/lapacke/lapacke_spec.rb +303 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +310 -0
- data/spec/slice_set_spec.rb +157 -0
- data/spec/spec_helper.rb +140 -0
- data/spec/stat_spec.rb +203 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +262 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# = NMatrix
|
|
3
|
+
#
|
|
4
|
+
# A linear algebra library for scientific computation in Ruby.
|
|
5
|
+
# NMatrix is part of SciRuby.
|
|
6
|
+
#
|
|
7
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
|
8
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
|
9
|
+
#
|
|
10
|
+
# == Copyright Information
|
|
11
|
+
#
|
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
|
13
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
|
14
|
+
#
|
|
15
|
+
# Please see LICENSE.txt for additional copyright notices.
|
|
16
|
+
#
|
|
17
|
+
# == Contributing
|
|
18
|
+
#
|
|
19
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
|
20
|
+
# our Contributor Agreement:
|
|
21
|
+
#
|
|
22
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
|
23
|
+
#
|
|
24
|
+
# == lapack_ext_common.rb
|
|
25
|
+
#
|
|
26
|
+
# Contains functions shared by nmatrix-atlas and nmatrix-lapacke gems.
|
|
27
|
+
#++
|
|
28
|
+
|
|
29
|
+
class NMatrix
|
|
30
|
+
def NMatrix.register_lapack_extension(name)
|
|
31
|
+
if (defined? @@lapack_extension)
|
|
32
|
+
raise "Attempting to load #{name} when #{@@lapack_extension} is already loaded. You can only load one LAPACK extension."
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@@lapack_extension = name
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
alias_method :internal_dot, :dot
|
|
39
|
+
|
|
40
|
+
def dot(right_v)
|
|
41
|
+
if (right_v.is_a?(NMatrix) && self.stype == :dense && right_v.stype == :dense &&
|
|
42
|
+
self.dim == 2 && right_v.dim == 2 && self.shape[1] == right_v.shape[0])
|
|
43
|
+
|
|
44
|
+
result_dtype = NMatrix.upcast(self.dtype,right_v.dtype)
|
|
45
|
+
left = self.dtype == result_dtype ? self : self.cast(dtype: result_dtype)
|
|
46
|
+
right = right_v.dtype == result_dtype ? right_v : right_v.cast(dtype: result_dtype)
|
|
47
|
+
|
|
48
|
+
left = left.clone if left.is_ref?
|
|
49
|
+
right = right.clone if right.is_ref?
|
|
50
|
+
|
|
51
|
+
result_m = left.shape[0]
|
|
52
|
+
result_n = right.shape[1]
|
|
53
|
+
left_n = left.shape[1]
|
|
54
|
+
vector = result_n == 1
|
|
55
|
+
result = NMatrix.new([result_m,result_n], dtype: result_dtype)
|
|
56
|
+
|
|
57
|
+
if vector
|
|
58
|
+
NMatrix::BLAS.cblas_gemv(false, result_m, left_n, 1, left, left_n, right, 1, 0, result, 1)
|
|
59
|
+
else
|
|
60
|
+
NMatrix::BLAS.cblas_gemm(:row, false, false, result_m, result_n, left_n, 1, left, left_n, right, result_n, 0, result, result_n)
|
|
61
|
+
end
|
|
62
|
+
return result
|
|
63
|
+
else
|
|
64
|
+
#internal_dot will handle non-dense matrices (and also dot-products for NMatrix's with dim=1),
|
|
65
|
+
#and also all error-handling if the input is not valid
|
|
66
|
+
self.internal_dot(right_v)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# = NMatrix
|
|
3
|
+
#
|
|
4
|
+
# A linear algebra library for scientific computation in Ruby.
|
|
5
|
+
# NMatrix is part of SciRuby.
|
|
6
|
+
#
|
|
7
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
|
8
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
|
9
|
+
#
|
|
10
|
+
# == Copyright Information
|
|
11
|
+
#
|
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
|
13
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
|
14
|
+
#
|
|
15
|
+
# Please see LICENSE.txt for additional copyright notices.
|
|
16
|
+
#
|
|
17
|
+
# == Contributing
|
|
18
|
+
#
|
|
19
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
|
20
|
+
# our Contributor Agreement:
|
|
21
|
+
#
|
|
22
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
|
23
|
+
#
|
|
24
|
+
# == lapacke.rb
|
|
25
|
+
#
|
|
26
|
+
# ruby file for the nmatrix-lapacke gem. Loads the C extension and defines
|
|
27
|
+
# nice ruby interfaces for LAPACK functions.
|
|
28
|
+
#++
|
|
29
|
+
|
|
30
|
+
require 'nmatrix/nmatrix.rb' #need to have nmatrix required first or else bad things will happen
|
|
31
|
+
require_relative 'lapack_ext_common'
|
|
32
|
+
|
|
33
|
+
NMatrix.register_lapack_extension("nmatrix-lapacke")
|
|
34
|
+
|
|
35
|
+
require "nmatrix_lapacke.so"
|
|
36
|
+
|
|
37
|
+
class NMatrix
|
|
38
|
+
#Add functions from the LAPACKE C extension to the main LAPACK and BLAS modules.
|
|
39
|
+
#This will overwrite the original functions where applicable.
|
|
40
|
+
module LAPACK
|
|
41
|
+
class << self
|
|
42
|
+
NMatrix::LAPACKE::LAPACK.singleton_methods.each do |m|
|
|
43
|
+
define_method m, NMatrix::LAPACKE::LAPACK.method(m).to_proc
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module BLAS
|
|
49
|
+
class << self
|
|
50
|
+
NMatrix::LAPACKE::BLAS.singleton_methods.each do |m|
|
|
51
|
+
define_method m, NMatrix::LAPACKE::BLAS.method(m).to_proc
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module LAPACK
|
|
57
|
+
class << self
|
|
58
|
+
def posv(uplo, a, b)
|
|
59
|
+
raise(ShapeError, "a must be square") unless a.dim == 2 && a.shape[0] == a.shape[1]
|
|
60
|
+
raise(ShapeError, "number of rows of b must equal number of cols of a") unless a.shape[1] == b.shape[0]
|
|
61
|
+
raise(StorageTypeError, "only works with dense matrices") unless a.stype == :dense && b.stype == :dense
|
|
62
|
+
raise(DataTypeError, "only works for non-integer, non-object dtypes") if
|
|
63
|
+
a.integer_dtype? || a.object_dtype? || b.integer_dtype? || b.object_dtype?
|
|
64
|
+
|
|
65
|
+
x = b.clone
|
|
66
|
+
clone = a.clone
|
|
67
|
+
n = a.shape[0]
|
|
68
|
+
nrhs = b.shape[1]
|
|
69
|
+
lapacke_potrf(:row, uplo, n, clone, n)
|
|
70
|
+
lapacke_potrs(:row, uplo, n, nrhs, clone, n, x, b.shape[1])
|
|
71
|
+
x
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def geev(matrix, which=:both)
|
|
75
|
+
raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless matrix.dense?
|
|
76
|
+
raise(ShapeError, "eigenvalues can only be computed for square matrices") unless matrix.dim == 2 && matrix.shape[0] == matrix.shape[1]
|
|
77
|
+
|
|
78
|
+
jobvl = (which == :both || which == :left) ? :t : false
|
|
79
|
+
jobvr = (which == :both || which == :right) ? :t : false
|
|
80
|
+
|
|
81
|
+
# Copy the matrix so it doesn't get overwritten.
|
|
82
|
+
temporary_matrix = matrix.clone
|
|
83
|
+
n = matrix.shape[0]
|
|
84
|
+
|
|
85
|
+
# Outputs
|
|
86
|
+
eigenvalues = NMatrix.new([n, 1], dtype: matrix.dtype) # For real dtypes this holds only the real part of the eigenvalues.
|
|
87
|
+
imag_eigenvalues = matrix.complex_dtype? ? nil : NMatrix.new([n, 1], dtype: matrix.dtype) # For complex dtypes, this is unused.
|
|
88
|
+
left_output = jobvl ? matrix.clone_structure : nil
|
|
89
|
+
right_output = jobvr ? matrix.clone_structure : nil
|
|
90
|
+
|
|
91
|
+
NMatrix::LAPACK::lapacke_geev(:row,
|
|
92
|
+
jobvl, # compute left eigenvectors of A?
|
|
93
|
+
jobvr, # compute right eigenvectors of A? (left eigenvectors of A**T)
|
|
94
|
+
n, # order of the matrix
|
|
95
|
+
temporary_matrix,# input matrix (used as work)
|
|
96
|
+
n, # leading dimension of matrix
|
|
97
|
+
eigenvalues,# real part of computed eigenvalues
|
|
98
|
+
imag_eigenvalues,# imag part of computed eigenvalues
|
|
99
|
+
left_output, # left eigenvectors, if applicable
|
|
100
|
+
n, # leading dimension of left_output
|
|
101
|
+
right_output, # right eigenvectors, if applicable
|
|
102
|
+
n) # leading dimension of right_output
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# For real dtypes, transform left_output and right_output into correct forms.
|
|
106
|
+
# If the j'th and the (j+1)'th eigenvalues form a complex conjugate
|
|
107
|
+
# pair, then the j'th and (j+1)'th columns of the matrix are
|
|
108
|
+
# the real and imag parts of the eigenvector corresponding
|
|
109
|
+
# to the j'th eigenvalue.
|
|
110
|
+
if !matrix.complex_dtype?
|
|
111
|
+
complex_indices = []
|
|
112
|
+
n.times do |i|
|
|
113
|
+
complex_indices << i if imag_eigenvalues[i] != 0.0
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
if !complex_indices.empty?
|
|
117
|
+
# For real dtypes, put the real and imaginary parts together
|
|
118
|
+
eigenvalues = eigenvalues + imag_eigenvalues*Complex(0.0,1.0)
|
|
119
|
+
left_output = left_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if left_output
|
|
120
|
+
right_output = right_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if right_output
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
complex_indices.each_slice(2) do |i, _|
|
|
124
|
+
if right_output
|
|
125
|
+
right_output[0...n,i] = right_output[0...n,i] + right_output[0...n,i+1]*Complex(0.0,1.0)
|
|
126
|
+
right_output[0...n,i+1] = right_output[0...n,i].complex_conjugate
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if left_output
|
|
130
|
+
left_output[0...n,i] = left_output[0...n,i] + left_output[0...n,i+1]*Complex(0.0,1.0)
|
|
131
|
+
left_output[0...n,i+1] = left_output[0...n,i].complex_conjugate
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
if which == :both
|
|
137
|
+
return [eigenvalues, left_output, right_output]
|
|
138
|
+
elsif which == :left
|
|
139
|
+
return [eigenvalues, left_output]
|
|
140
|
+
else
|
|
141
|
+
return [eigenvalues, right_output]
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def gesvd(matrix, workspace_size=1)
|
|
146
|
+
result = alloc_svd_result(matrix)
|
|
147
|
+
|
|
148
|
+
m = matrix.shape[0]
|
|
149
|
+
n = matrix.shape[1]
|
|
150
|
+
|
|
151
|
+
superb = NMatrix.new([[m,n].min], dtype: matrix.abs_dtype)
|
|
152
|
+
|
|
153
|
+
NMatrix::LAPACK::lapacke_gesvd(:row, :a, :a, m, n, matrix, n, result[1], result[0], m, result[2], n, superb)
|
|
154
|
+
result
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def gesdd(matrix, workspace_size=nil)
|
|
158
|
+
result = alloc_svd_result(matrix)
|
|
159
|
+
|
|
160
|
+
m = matrix.shape[0]
|
|
161
|
+
n = matrix.shape[1]
|
|
162
|
+
|
|
163
|
+
NMatrix::LAPACK::lapacke_gesdd(:row, :a, m, n, matrix, n, result[1], result[0], m, result[2], n)
|
|
164
|
+
result
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def getrf!
|
|
170
|
+
raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless self.dense?
|
|
171
|
+
|
|
172
|
+
ipiv = NMatrix::LAPACK::lapacke_getrf(:row, self.shape[0], self.shape[1], self, self.shape[1])
|
|
173
|
+
|
|
174
|
+
return ipiv
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def invert!
|
|
178
|
+
raise(StorageTypeError, "invert only works on dense matrices currently") unless self.dense?
|
|
179
|
+
raise(ShapeError, "Cannot invert non-square matrix") unless shape[0] == shape[1]
|
|
180
|
+
raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype?
|
|
181
|
+
|
|
182
|
+
# Get the pivot array; factor the matrix
|
|
183
|
+
n = self.shape[0]
|
|
184
|
+
pivot = NMatrix::LAPACK::lapacke_getrf(:row, n, n, self, n)
|
|
185
|
+
# Now calculate the inverse using the pivot array
|
|
186
|
+
NMatrix::LAPACK::lapacke_getri(:row, n, self, n, pivot)
|
|
187
|
+
|
|
188
|
+
self
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def potrf!(which)
|
|
192
|
+
raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless self.dense?
|
|
193
|
+
raise(ShapeError, "Cholesky decomposition only valid for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1]
|
|
194
|
+
|
|
195
|
+
NMatrix::LAPACK::lapacke_potrf(:row, which, self.shape[0], self, self.shape[1])
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def solve b
|
|
199
|
+
raise(ShapeError, "Must be called on square matrix") unless self.dim == 2 && self.shape[0] == self.shape[1]
|
|
200
|
+
raise(ShapeError, "number of rows of b must equal number of cols of self") if
|
|
201
|
+
self.shape[1] != b.shape[0]
|
|
202
|
+
raise ArgumentError, "only works with dense matrices" if self.stype != :dense
|
|
203
|
+
raise ArgumentError, "only works for non-integer, non-object dtypes" if
|
|
204
|
+
integer_dtype? or object_dtype? or b.integer_dtype? or b.object_dtype?
|
|
205
|
+
|
|
206
|
+
x = b.clone
|
|
207
|
+
clone = self.clone
|
|
208
|
+
n = self.shape[0]
|
|
209
|
+
ipiv = NMatrix::LAPACK.lapacke_getrf(:row, n, n, clone, n)
|
|
210
|
+
NMatrix::LAPACK.lapacke_getrs(:row, :no_transpose, n, b.shape[1], clone, n, ipiv, x, b.shape[1])
|
|
211
|
+
x
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
# = NMatrix
|
|
2
|
+
#
|
|
3
|
+
# A linear algebra library for scientific computation in Ruby.
|
|
4
|
+
# NMatrix is part of SciRuby.
|
|
5
|
+
#
|
|
6
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
|
7
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
|
8
|
+
#
|
|
9
|
+
# == Copyright Information
|
|
10
|
+
#
|
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
|
12
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
|
13
|
+
#
|
|
14
|
+
# Please see LICENSE.txt for additional copyright notices.
|
|
15
|
+
#
|
|
16
|
+
# == Contributing
|
|
17
|
+
#
|
|
18
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
|
19
|
+
# our Contributor Agreement:
|
|
20
|
+
#
|
|
21
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
|
22
|
+
#
|
|
23
|
+
# == 00_nmatrix_spec.rb
|
|
24
|
+
#
|
|
25
|
+
# Basic tests for NMatrix. These should load first, as they're
|
|
26
|
+
# essential to NMatrix operation.
|
|
27
|
+
#
|
|
28
|
+
require 'spec_helper'
|
|
29
|
+
|
|
30
|
+
describe NMatrix do
|
|
31
|
+
it "creates a matrix with the new constructor" do
|
|
32
|
+
n = NMatrix.new([2,2], [0,1,2,3], dtype: :int64)
|
|
33
|
+
expect(n.shape).to eq([2,2])
|
|
34
|
+
expect(n.entries).to eq([0,1,2,3])
|
|
35
|
+
expect(n.dtype).to eq(:int64)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "adequately requires information to access a single entry of a dense matrix" do
|
|
39
|
+
n = NMatrix.new(:dense, 4, [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], :float64)
|
|
40
|
+
expect(n[0,0]).to eq(0)
|
|
41
|
+
expect { n[0] }.to raise_error(ArgumentError)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "calculates exact determinants on small square matrices" do
|
|
45
|
+
expect(NMatrix.new(2, [1,2,3,4], stype: :dense, dtype: :int64).det_exact).to eq(-2)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "calculates determinants" do
|
|
49
|
+
expect(NMatrix.new(3, [-2,2,3,-1,1,3,2,0,-1], stype: :dense, dtype: :int64).det).to eq(6)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "allows casting to Ruby objects" do
|
|
53
|
+
m = NMatrix.new([3,3], [0,0,1,0,2,0,3,4,5], dtype: :int64, stype: :dense)
|
|
54
|
+
n = m.cast(:dense, :object)
|
|
55
|
+
expect(n).to eq(m)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "allows casting from Ruby objects" do
|
|
59
|
+
m = NMatrix.new(:dense, [3,3], [0,0,1,0,2,0,3,4,5], :object)
|
|
60
|
+
n = m.cast(:dense, :int64)
|
|
61
|
+
expect(m).to eq(n)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "allows stype casting of a dim 2 matrix between dense, sparse, and list (different dtypes)" do
|
|
65
|
+
m = NMatrix.new(:dense, [3,3], [0,0,1,0,2,0,3,4,5], :int64).
|
|
66
|
+
cast(:yale, :int32).
|
|
67
|
+
cast(:dense, :float64).
|
|
68
|
+
cast(:list, :object).
|
|
69
|
+
cast(:dense, :int16).
|
|
70
|
+
cast(:list, :int32).
|
|
71
|
+
cast(:yale, :int64) #.
|
|
72
|
+
#cast(:list, :int32).
|
|
73
|
+
#cast(:dense, :int16)
|
|
74
|
+
#m.should.equal?(original)
|
|
75
|
+
# For some reason this causes some weird garbage collector problems when we uncomment these. The above lines won't
|
|
76
|
+
# work at all in IRB, but work fine when run in a regular Ruby session.
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "fills dense Ruby object matrix with nil" do
|
|
80
|
+
n = NMatrix.new([4,3], dtype: :object)
|
|
81
|
+
expect(n[0,0]).to eq(nil)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "fills dense with individual assignments" do
|
|
85
|
+
n = NMatrix.new([4,3], dtype: :float64)
|
|
86
|
+
n[0,0] = 14.0
|
|
87
|
+
n[0,1] = 9.0
|
|
88
|
+
n[0,2] = 3.0
|
|
89
|
+
n[1,0] = 2.0
|
|
90
|
+
n[1,1] = 11.0
|
|
91
|
+
n[1,2] = 15.0
|
|
92
|
+
n[2,0] = 0.0
|
|
93
|
+
n[2,1] = 12.0
|
|
94
|
+
n[2,2] = 17.0
|
|
95
|
+
n[3,0] = 5.0
|
|
96
|
+
n[3,1] = 2.0
|
|
97
|
+
n[3,2] = 3.0
|
|
98
|
+
|
|
99
|
+
expect(n[0,0]).to eq(14.0)
|
|
100
|
+
expect(n[0,1]).to eq(9.0)
|
|
101
|
+
expect(n[0,2]).to eq(3.0)
|
|
102
|
+
expect(n[1,0]).to eq(2.0)
|
|
103
|
+
expect(n[1,1]).to eq(11.0)
|
|
104
|
+
expect(n[1,2]).to eq(15.0)
|
|
105
|
+
expect(n[2,0]).to eq(0.0)
|
|
106
|
+
expect(n[2,1]).to eq(12.0)
|
|
107
|
+
expect(n[2,2]).to eq(17.0)
|
|
108
|
+
expect(n[3,0]).to eq(5.0)
|
|
109
|
+
expect(n[3,1]).to eq(2.0)
|
|
110
|
+
expect(n[3,2]).to eq(3.0)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "fills dense with a single mass assignment" do
|
|
114
|
+
n = NMatrix.new([4,3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0])
|
|
115
|
+
|
|
116
|
+
expect(n[0,0]).to eq(14.0)
|
|
117
|
+
expect(n[0,1]).to eq(9.0)
|
|
118
|
+
expect(n[0,2]).to eq(3.0)
|
|
119
|
+
expect(n[1,0]).to eq(2.0)
|
|
120
|
+
expect(n[1,1]).to eq(11.0)
|
|
121
|
+
expect(n[1,2]).to eq(15.0)
|
|
122
|
+
expect(n[2,0]).to eq(0.0)
|
|
123
|
+
expect(n[2,1]).to eq(12.0)
|
|
124
|
+
expect(n[2,2]).to eq(17.0)
|
|
125
|
+
expect(n[3,0]).to eq(5.0)
|
|
126
|
+
expect(n[3,1]).to eq(2.0)
|
|
127
|
+
expect(n[3,2]).to eq(3.0)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "fills dense with a single mass assignment, with dtype specified" do
|
|
131
|
+
m = NMatrix.new([4,3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0], dtype: :float32)
|
|
132
|
+
|
|
133
|
+
expect(m[0,0]).to eq(14.0)
|
|
134
|
+
expect(m[0,1]).to eq(9.0)
|
|
135
|
+
expect(m[0,2]).to eq(3.0)
|
|
136
|
+
expect(m[1,0]).to eq(2.0)
|
|
137
|
+
expect(m[1,1]).to eq(11.0)
|
|
138
|
+
expect(m[1,2]).to eq(15.0)
|
|
139
|
+
expect(m[2,0]).to eq(0.0)
|
|
140
|
+
expect(m[2,1]).to eq(12.0)
|
|
141
|
+
expect(m[2,2]).to eq(17.0)
|
|
142
|
+
expect(m[3,0]).to eq(5.0)
|
|
143
|
+
expect(m[3,1]).to eq(2.0)
|
|
144
|
+
expect(m[3,2]).to eq(3.0)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "dense handles missing initialization value" do
|
|
148
|
+
n = NMatrix.new(3, dtype: :int8)
|
|
149
|
+
expect(n.stype).to eq(:dense)
|
|
150
|
+
expect(n.dtype).to eq(:int8)
|
|
151
|
+
|
|
152
|
+
m = NMatrix.new(4, dtype: :float64)
|
|
153
|
+
expect(m.stype).to eq(:dense)
|
|
154
|
+
expect(m.dtype).to eq(:float64)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
[:dense, :list, :yale].each do |storage_type|
|
|
158
|
+
context storage_type do
|
|
159
|
+
it "can be duplicated" do
|
|
160
|
+
n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64)
|
|
161
|
+
expect(n.stype).to eq(storage_type)
|
|
162
|
+
|
|
163
|
+
n[0,0] = 0.0
|
|
164
|
+
n[0,1] = 0.1
|
|
165
|
+
n[1,0] = 1.0
|
|
166
|
+
|
|
167
|
+
m = n.dup
|
|
168
|
+
expect(m.shape).to eq(n.shape)
|
|
169
|
+
expect(m.dim).to eq(n.dim)
|
|
170
|
+
expect(m.object_id).not_to eq(n.object_id)
|
|
171
|
+
expect(m.stype).to eq(storage_type)
|
|
172
|
+
expect(m[0,0]).to eq(n[0,0])
|
|
173
|
+
m[0,0] = 3.0
|
|
174
|
+
expect(m[0,0]).not_to eq(n[0,0])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "enforces shape boundaries" do
|
|
178
|
+
expect { NMatrix.new([1,10], 0, dtype: :int8, stype: storage_type, default: 0)[1,0] }.to raise_error(RangeError)
|
|
179
|
+
expect { NMatrix.new([1,10], 0, dtype: :int8, stype: storage_type, default: 0)[0,10] }.to raise_error(RangeError)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "sets and gets" do
|
|
183
|
+
n = NMatrix.new(2, 0, stype: storage_type, dtype: :int8)
|
|
184
|
+
n[0,1] = 1
|
|
185
|
+
expect(n[0,0]).to eq(0)
|
|
186
|
+
expect(n[1,0]).to eq(0)
|
|
187
|
+
expect(n[0,1]).to eq(1)
|
|
188
|
+
expect(n[1,1]).to eq(0)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "sets and gets references" do
|
|
192
|
+
n = NMatrix.new(2, stype: storage_type, dtype: :int8, default: 0)
|
|
193
|
+
expect(n[0,1] = 1).to eq(1)
|
|
194
|
+
expect(n[0,1]).to eq(1)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Tests Ruby object versus any C dtype (in this case we use :int64)
|
|
198
|
+
[:object, :int64].each do |dtype|
|
|
199
|
+
c = dtype == :object ? "Ruby object" : "non-Ruby object"
|
|
200
|
+
context c do
|
|
201
|
+
it "allows iteration of matrices" do
|
|
202
|
+
n = nil
|
|
203
|
+
if storage_type == :dense
|
|
204
|
+
n = NMatrix.new(:dense, [3,3], [1,2,3,4,5,6,7,8,9], dtype)
|
|
205
|
+
else
|
|
206
|
+
n = NMatrix.new([3,4], 0, stype: storage_type, dtype: dtype)
|
|
207
|
+
n[0,0] = 1
|
|
208
|
+
n[0,1] = 2
|
|
209
|
+
n[2,3] = 4
|
|
210
|
+
n[2,0] = 3
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
ary = []
|
|
214
|
+
n.each do |x|
|
|
215
|
+
ary << x
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
if storage_type == :dense
|
|
219
|
+
expect(ary).to eq([1,2,3,4,5,6,7,8,9])
|
|
220
|
+
else
|
|
221
|
+
expect(ary).to eq([1,2,0,0,0,0,0,0,3,0,0,4])
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "allows storage-based iteration of matrices" do
|
|
226
|
+
STDERR.puts storage_type.inspect
|
|
227
|
+
STDERR.puts dtype.inspect
|
|
228
|
+
n = NMatrix.new([3,3], 0, stype: storage_type, dtype: dtype)
|
|
229
|
+
n[0,0] = 1
|
|
230
|
+
n[0,1] = 2
|
|
231
|
+
n[2,0] = 5 if storage_type == :yale
|
|
232
|
+
n[2,1] = 4
|
|
233
|
+
n[2,2] = 3
|
|
234
|
+
|
|
235
|
+
values = []
|
|
236
|
+
is = []
|
|
237
|
+
js = []
|
|
238
|
+
|
|
239
|
+
n.each_stored_with_indices do |v,i,j|
|
|
240
|
+
values << v
|
|
241
|
+
is << i
|
|
242
|
+
js << j
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
if storage_type == :yale
|
|
246
|
+
expect(is).to eq([0,1,2,0,2,2])
|
|
247
|
+
expect(js).to eq([0,1,2,1,0,1])
|
|
248
|
+
expect(values).to eq([1,0,3,2,5,4])
|
|
249
|
+
elsif storage_type == :list
|
|
250
|
+
expect(values).to eq([1,2,4,3])
|
|
251
|
+
expect(is).to eq([0,0,2,2])
|
|
252
|
+
expect(js).to eq([0,1,1,2])
|
|
253
|
+
elsif storage_type == :dense
|
|
254
|
+
expect(values).to eq([1,2,0,0,0,0,0,4,3])
|
|
255
|
+
expect(is).to eq([0,0,0,1,1,1,2,2,2])
|
|
256
|
+
expect(js).to eq([0,1,2,0,1,2,0,1,2])
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# dense and list, not yale
|
|
264
|
+
context "(storage: #{storage_type})" do
|
|
265
|
+
it "gets default value" do
|
|
266
|
+
expect(NMatrix.new(3, 0, stype: storage_type)[1,1]).to eq(0)
|
|
267
|
+
expect(NMatrix.new(3, 0.1, stype: storage_type)[1,1]).to eq(0.1)
|
|
268
|
+
expect(NMatrix.new(3, 1, stype: storage_type)[1,1]).to eq(1)
|
|
269
|
+
|
|
270
|
+
end
|
|
271
|
+
it "returns shape and dim" do
|
|
272
|
+
expect(NMatrix.new([3,2,8], 0, stype: storage_type).shape).to eq([3,2,8])
|
|
273
|
+
expect(NMatrix.new([3,2,8], 0, stype: storage_type).dim).to eq(3)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it "returns number of rows and columns" do
|
|
277
|
+
expect(NMatrix.new([7, 4], 3, stype: storage_type).rows).to eq(7)
|
|
278
|
+
expect(NMatrix.new([7, 4], 3, stype: storage_type).cols).to eq(4)
|
|
279
|
+
end
|
|
280
|
+
end unless storage_type == :yale
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
it "handles dense construction" do
|
|
285
|
+
expect(NMatrix.new(3,0)[1,1]).to eq(0)
|
|
286
|
+
expect(lambda { NMatrix.new(3,dtype: :int8)[1,1] }).to_not raise_error
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "converts from list to yale properly" do
|
|
290
|
+
m = NMatrix.new(3, 0, stype: :list)
|
|
291
|
+
m[0,2] = 333
|
|
292
|
+
m[2,2] = 777
|
|
293
|
+
n = m.cast(:yale, :int32)
|
|
294
|
+
#puts n.capacity
|
|
295
|
+
#n.extend NMatrix::YaleFunctions
|
|
296
|
+
#puts n.yale_ija.inspect
|
|
297
|
+
#puts n.yale_a.inspect
|
|
298
|
+
|
|
299
|
+
expect(n[0,0]).to eq(0)
|
|
300
|
+
expect(n[0,1]).to eq(0)
|
|
301
|
+
expect(n[0,2]).to eq(333)
|
|
302
|
+
expect(n[1,0]).to eq(0)
|
|
303
|
+
expect(n[1,1]).to eq(0)
|
|
304
|
+
expect(n[1,2]).to eq(0)
|
|
305
|
+
expect(n[2,0]).to eq(0)
|
|
306
|
+
expect(n[2,1]).to eq(0)
|
|
307
|
+
expect(n[2,2]).to eq(777)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "should return an enumerator when each is called without a block" do
|
|
311
|
+
a = NMatrix.new(2, 1)
|
|
312
|
+
b = NMatrix.new(2, [-1,0,1,0])
|
|
313
|
+
enums = [a.each, b.each]
|
|
314
|
+
|
|
315
|
+
begin
|
|
316
|
+
atans = []
|
|
317
|
+
atans << Math.atan2(*enums.map(&:next)) while true
|
|
318
|
+
rescue StopIteration
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "dense" do
|
|
323
|
+
it "should return the matrix being iterated over when each is called with a block" do
|
|
324
|
+
a = NMatrix.new(2, 1)
|
|
325
|
+
val = (a.each { })
|
|
326
|
+
expect(val).to eq(a)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it "should return the matrix being iterated over when each_stored_with_indices is called with a block" do
|
|
330
|
+
a = NMatrix.new(2,1)
|
|
331
|
+
val = (a.each_stored_with_indices { })
|
|
332
|
+
expect(val).to eq(a)
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
[:list, :yale].each do |storage_type|
|
|
337
|
+
context storage_type do
|
|
338
|
+
it "should return the matrix being iterated over when each_stored_with_indices is called with a block" do
|
|
339
|
+
n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64, default: 0)
|
|
340
|
+
val = (n.each_stored_with_indices { })
|
|
341
|
+
expect(val).to eq(n)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it "should return an enumerator when each_stored_with_indices is called without a block" do
|
|
345
|
+
n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64, default: 0)
|
|
346
|
+
val = n.each_stored_with_indices
|
|
347
|
+
expect(val).to be_a Enumerator
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it "should iterate through element 256 without a segfault" do
|
|
353
|
+
t = NVector.random(256)
|
|
354
|
+
t.each { |x| x + 0 }
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
describe 'NMatrix' do
|
|
360
|
+
context "#upper_triangle" do
|
|
361
|
+
it "should create a copy with the lower corner set to zero" do
|
|
362
|
+
n = NMatrix.seq(4)+1
|
|
363
|
+
expect(n.upper_triangle).to eq(NMatrix.new(4, [1,2,3,4,0,6,7,8,0,0,11,12,0,0,0,16]))
|
|
364
|
+
expect(n.upper_triangle(2)).to eq(NMatrix.new(4, [1,2,3,4,5,6,7,8,9,10,11,12,0,14,15,16]))
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
context "#lower_triangle" do
|
|
369
|
+
it "should create a copy with the lower corner set to zero" do
|
|
370
|
+
n = NMatrix.seq(4)+1
|
|
371
|
+
expect(n.lower_triangle).to eq(NMatrix.new(4, [1,0,0,0,5,6,0,0,9,10,11,0,13,14,15,16]))
|
|
372
|
+
expect(n.lower_triangle(2)).to eq(NMatrix.new(4, [1,2,3,0,5,6,7,8,9,10,11,12,13,14,15,16]))
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
context "#upper_triangle!" do
|
|
377
|
+
it "should create a copy with the lower corner set to zero" do
|
|
378
|
+
n = NMatrix.seq(4)+1
|
|
379
|
+
expect(n.upper_triangle!).to eq(NMatrix.new(4, [1,2,3,4,0,6,7,8,0,0,11,12,0,0,0,16]))
|
|
380
|
+
n = NMatrix.seq(4)+1
|
|
381
|
+
expect(n.upper_triangle!(2)).to eq(NMatrix.new(4, [1,2,3,4,5,6,7,8,9,10,11,12,0,14,15,16]))
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
context "#lower_triangle!" do
|
|
386
|
+
it "should create a copy with the lower corner set to zero" do
|
|
387
|
+
n = NMatrix.seq(4)+1
|
|
388
|
+
expect(n.lower_triangle!).to eq(NMatrix.new(4, [1,0,0,0,5,6,0,0,9,10,11,0,13,14,15,16]))
|
|
389
|
+
n = NMatrix.seq(4)+1
|
|
390
|
+
expect(n.lower_triangle!(2)).to eq(NMatrix.new(4, [1,2,3,0,5,6,7,8,9,10,11,12,13,14,15,16]))
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
context "#rank" do
|
|
395
|
+
it "should get the rank of a 2-dimensional matrix" do
|
|
396
|
+
n = NMatrix.seq([2,3])
|
|
397
|
+
expect(n.rank(0, 0)).to eq(N[[0,1,2]])
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it "should raise an error when the rank is out of bounds" do
|
|
401
|
+
n = NMatrix.seq([2,3])
|
|
402
|
+
expect { n.rank(2, 0) }.to raise_error(RangeError)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
context "#reshape" do
|
|
407
|
+
it "should change the shape of a matrix without the contents changing" do
|
|
408
|
+
n = NMatrix.seq(4)+1
|
|
409
|
+
expect(n.reshape([8,2]).to_flat_array).to eq(n.to_flat_array)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "should permit a change of dimensionality" do
|
|
413
|
+
n = NMatrix.seq(4)+1
|
|
414
|
+
expect(n.reshape([8,1,2]).to_flat_array).to eq(n.to_flat_array)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
it "should prevent a resize" do
|
|
418
|
+
n = NMatrix.seq(4)+1
|
|
419
|
+
expect { n.reshape([5,2]) }.to raise_error(ArgumentError)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
it "should do the reshape operation in place" do
|
|
423
|
+
n = NMatrix.seq(4)+1
|
|
424
|
+
expect(n.reshape!([8,2]).eql?(n)).to eq(true) # because n itself changes
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
it "reshape and reshape! must produce same result" do
|
|
428
|
+
n = NMatrix.seq(4)+1
|
|
429
|
+
a = NMatrix.seq(4)+1
|
|
430
|
+
expect(n.reshape!([8,2])==a.reshape(8,2)).to eq(true) # because n itself changes
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it "should prevent a resize in place" do
|
|
434
|
+
n = NMatrix.seq(4)+1
|
|
435
|
+
expect { n.reshape([5,2]) }.to raise_error(ArgumentError)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
context "#transpose" do
|
|
440
|
+
[:dense, :list, :yale].each do |stype|
|
|
441
|
+
context(stype) do
|
|
442
|
+
it "should transpose a #{stype} matrix (2-dimensional)" do
|
|
443
|
+
n = NMatrix.seq(4, stype: stype)
|
|
444
|
+
expect(n.transpose.to_a.flatten).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15])
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
[:dense, :list].each do |stype|
|
|
450
|
+
context(stype) do
|
|
451
|
+
it "should transpose a #{stype} matrix (3-dimensional)" do
|
|
452
|
+
n = NMatrix.new([4,4,1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], stype: stype)
|
|
453
|
+
expect(n.transpose([2,1,0]).to_flat_array).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15])
|
|
454
|
+
expect(n.transpose([1,0,2]).to_flat_array).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15])
|
|
455
|
+
expect(n.transpose([0,2,1]).to_flat_array).to eq(n.to_flat_array) # for dense, make this reshape!
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it "should just copy a 1-dimensional #{stype} matrix" do
|
|
460
|
+
n = NMatrix.new([3], [1,2,3], stype: stype)
|
|
461
|
+
expect(n.transpose).to eq n
|
|
462
|
+
expect(n.transpose).not_to be n
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
context "#dot_product" do
|
|
468
|
+
[:dense].each do |stype| # list storage transpose not yet implemented
|
|
469
|
+
context(stype) do # yale support only 2-dim matrix
|
|
470
|
+
it "should work like vector product on a #{stype} (1-dimensional)" do
|
|
471
|
+
m = NMatrix.new([3], [1,2,3], stype: stype)
|
|
472
|
+
expect(m.dot(m)).to eq (NMatrix.new([1],[14]))
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
context "#==" do
|
|
479
|
+
[:dense, :list, :yale].each do |left|
|
|
480
|
+
[:dense, :list, :yale].each do |right|
|
|
481
|
+
context ("#{left}?#{right}") do
|
|
482
|
+
it "tests equality of two equal matrices" do
|
|
483
|
+
n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: left)
|
|
484
|
+
m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right)
|
|
485
|
+
|
|
486
|
+
expect(n==m).to eq(true)
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
it "tests equality of two unequal matrices" do
|
|
490
|
+
n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,1], stype: left)
|
|
491
|
+
m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right)
|
|
492
|
+
|
|
493
|
+
expect(n==m).to eq(false)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
it "tests equality of matrices with different shapes" do
|
|
497
|
+
n = NMatrix.new([2,2], [1,2, 3,4], stype: left)
|
|
498
|
+
m = NMatrix.new([2,3], [1,2, 3,4, 5,6], stype: right)
|
|
499
|
+
x = NMatrix.new([1,4], [1,2, 3,4], stype: right)
|
|
500
|
+
|
|
501
|
+
expect{n==m}.to raise_error(ShapeError)
|
|
502
|
+
expect{n==x}.to raise_error(ShapeError)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
it "tests equality of matrices with different dimension" do
|
|
506
|
+
n = NMatrix.new([2,1], [1,2], stype: left)
|
|
507
|
+
m = NMatrix.new([2], [1,2], stype: right)
|
|
508
|
+
|
|
509
|
+
expect{n==m}.to raise_error(ShapeError)
|
|
510
|
+
end if left != :yale && right != :yale # yale must have dimension 2
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
context "#concat" do
|
|
517
|
+
it "should default to horizontal concatenation" do
|
|
518
|
+
n = NMatrix.new([1,3], [1,2,3])
|
|
519
|
+
expect(n.concat(n)).to eq(NMatrix.new([1,6], [1,2,3,1,2,3]))
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it "should permit vertical concatenation" do
|
|
523
|
+
n = NMatrix.new([1,3], [1,2,3])
|
|
524
|
+
expect(n.vconcat(n)).to eq(NMatrix.new([2,3], [1,2,3]))
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
it "should permit depth concatenation on tensors" do
|
|
528
|
+
n = NMatrix.new([1,3,1], [1,2,3])
|
|
529
|
+
expect(n.dconcat(n)).to eq(NMatrix.new([1,3,2], [1,1,2,2,3,3]))
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
context "#[]" do
|
|
534
|
+
it "should return values based on indices" do
|
|
535
|
+
n = NMatrix.new([2,5], [1,2,3,4,5,6,7,8,9,0])
|
|
536
|
+
expect(n[1,0]).to eq 6
|
|
537
|
+
expect(n[1,0..3]).to eq NMatrix.new([1,4],[6,7,8,9])
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
it "should work for negative indices" do
|
|
541
|
+
n = NMatrix.new([1,5], [1,2,3,4,5])
|
|
542
|
+
expect(n[-1]).to eq(5)
|
|
543
|
+
expect(n[0,0..-2]).to eq(NMatrix.new([1,4],[1,2,3,4]))
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
context "#complex_conjugate!" do
|
|
548
|
+
[:dense, :yale, :list].each do |stype|
|
|
549
|
+
context(stype) do
|
|
550
|
+
it "should work in-place for complex dtypes" do
|
|
551
|
+
pending("not yet implemented for list stype") if stype == :list
|
|
552
|
+
n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128)
|
|
553
|
+
n.complex_conjugate!
|
|
554
|
+
expect(n).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128))
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
[:object, :int64].each do |dtype|
|
|
558
|
+
it "should work in-place for non-complex dtypes" do
|
|
559
|
+
pending("not yet implemented for list stype") if stype == :list
|
|
560
|
+
n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype)
|
|
561
|
+
n.complex_conjugate!
|
|
562
|
+
expect(n).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype))
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
context "#complex_conjugate" do
|
|
570
|
+
[:dense, :yale, :list].each do |stype|
|
|
571
|
+
context(stype) do
|
|
572
|
+
it "should work out-of-place for complex dtypes" do
|
|
573
|
+
pending("not yet implemented for list stype") if stype == :list
|
|
574
|
+
n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128)
|
|
575
|
+
expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128))
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
[:object, :int64].each do |dtype|
|
|
579
|
+
it "should work out-of-place for non-complex dtypes" do
|
|
580
|
+
pending("not yet implemented for list stype") if stype == :list
|
|
581
|
+
n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype)
|
|
582
|
+
expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype))
|
|
583
|
+
end
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
context "#inject" do
|
|
590
|
+
it "should sum columns of yale matrix correctly" do
|
|
591
|
+
n = NMatrix.new([4, 3], stype: :yale, default: 0)
|
|
592
|
+
n[0,0] = 1
|
|
593
|
+
n[1,1] = 2
|
|
594
|
+
n[2,2] = 4
|
|
595
|
+
n[3,2] = 8
|
|
596
|
+
column_sums = []
|
|
597
|
+
n.cols.times do |i|
|
|
598
|
+
column_sums << n.col(i).inject(:+)
|
|
599
|
+
end
|
|
600
|
+
expect(column_sums).to eq([1, 2, 12])
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
context "#index" do
|
|
605
|
+
it "returns index of first occurence of an element for a vector" do
|
|
606
|
+
n = NMatrix.new([5], [0,22,22,11,11])
|
|
607
|
+
|
|
608
|
+
expect(n.index(22)).to eq([1])
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
it "returns index of first occurence of an element for 2-D matrix" do
|
|
612
|
+
n = NMatrix.new([3,3], [23,11,23,
|
|
613
|
+
44, 2, 0,
|
|
614
|
+
33, 0, 32])
|
|
615
|
+
|
|
616
|
+
expect(n.index(0)).to eq([1,2])
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it "returns index of first occerence of an element for N-D matrix" do
|
|
620
|
+
n = NMatrix.new([3,3,3], [23,11,23, 44, 2, 0, 33, 0, 32,
|
|
621
|
+
23,11,23, 44, 2, 0, 33, 0, 32,
|
|
622
|
+
23,11,23, 44, 2, 0, 33, 0, 32])
|
|
623
|
+
|
|
624
|
+
expect(n.index(44)).to eq([0,1,0])
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
context "#diagonal" do
|
|
629
|
+
ALL_DTYPES.each do |dtype|
|
|
630
|
+
before do
|
|
631
|
+
@square_matrix = NMatrix.new([3,3], [
|
|
632
|
+
23,11,23,
|
|
633
|
+
44, 2, 0,
|
|
634
|
+
33, 0, 32
|
|
635
|
+
], dtype: dtype
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
@rect_matrix = NMatrix.new([4,3], [
|
|
639
|
+
23,11,23,
|
|
640
|
+
44, 2, 0,
|
|
641
|
+
33, 0,32,
|
|
642
|
+
11,22,33
|
|
643
|
+
], dtype: dtype
|
|
644
|
+
)
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
it "returns main diagonal for square matrix" do
|
|
648
|
+
expect(@square_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32])
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
it "returns main diagonal for rectangular matrix" do
|
|
652
|
+
expect(@rect_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32])
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
it "returns anti-diagonal for square matrix" do
|
|
656
|
+
expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33])
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
it "returns anti-diagonal for rectangular matrix" do
|
|
660
|
+
expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33])
|
|
661
|
+
end
|
|
662
|
+
end
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
context "#repeat" do
|
|
666
|
+
before do
|
|
667
|
+
@sample_matrix = NMatrix.new([2, 2], [1, 2, 3, 4])
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
it "checks count argument" do
|
|
671
|
+
expect{@sample_matrix.repeat(1, 0)}.to raise_error(ArgumentError)
|
|
672
|
+
expect{@sample_matrix.repeat(-2, 0)}.to raise_error(ArgumentError)
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
it "returns repeated matrix" do
|
|
676
|
+
expect(@sample_matrix.repeat(2, 0)).to eq(NMatrix.new([4, 2], [1, 2, 3, 4, 1, 2, 3, 4]))
|
|
677
|
+
expect(@sample_matrix.repeat(2, 1)).to eq(NMatrix.new([2, 4], [1, 2, 1, 2, 3, 4, 3, 4]))
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
context "#meshgrid" do
|
|
682
|
+
before do
|
|
683
|
+
@x, @y, @z = [1, 2, 3], NMatrix.new([2, 1], [4, 5]), [6, 7]
|
|
684
|
+
@two_dim = NMatrix.new([2, 2], [1, 2, 3, 4])
|
|
685
|
+
@two_dim_array = [[4], [5]]
|
|
686
|
+
@expected_result = [NMatrix.new([2, 3], [1, 2, 3, 1, 2, 3]), NMatrix.new([2, 3], [4, 4, 4, 5, 5, 5])]
|
|
687
|
+
@expected_for_ij = [NMatrix.new([3, 2], [1, 1, 2, 2, 3, 3]), NMatrix.new([3, 2], [4, 5, 4, 5, 4, 5])]
|
|
688
|
+
@expected_for_sparse = [NMatrix.new([1, 3], [1, 2, 3]), NMatrix.new([2, 1], [4, 5])]
|
|
689
|
+
@expected_for_sparse_ij = [NMatrix.new([3, 1], [1, 2, 3]), NMatrix.new([1, 2], [4, 5])]
|
|
690
|
+
@expected_3dim = [NMatrix.new([1, 3, 1], [1, 2, 3]).repeat(2, 0).repeat(2, 2),
|
|
691
|
+
NMatrix.new([2, 1, 1], [4, 5]).repeat(3, 1).repeat(2, 2),
|
|
692
|
+
NMatrix.new([1, 1, 2], [6, 7]).repeat(2, 0).repeat(3, 1)]
|
|
693
|
+
@expected_3dim_sparse_ij = [NMatrix.new([3, 1, 1], [1, 2, 3]),
|
|
694
|
+
NMatrix.new([1, 2, 1], [4, 5]),
|
|
695
|
+
NMatrix.new([1, 1, 2], [6, 7])]
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
it "checks arrays count" do
|
|
699
|
+
expect{NMatrix.meshgrid([@x])}.to raise_error(ArgumentError)
|
|
700
|
+
expect{NMatrix.meshgrid([])}.to raise_error(ArgumentError)
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
it "flattens input arrays before use" do
|
|
704
|
+
expect(NMatrix.meshgrid([@two_dim, @two_dim_array])).to eq(NMatrix.meshgrid([@two_dim.to_flat_array, @two_dim_array.flatten]))
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
it "returns new NMatrixes" do
|
|
708
|
+
expect(NMatrix.meshgrid([@x, @y])).to eq(@expected_result)
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
it "has option :sparse" do
|
|
712
|
+
expect(NMatrix.meshgrid([@x, @y], sparse: true)).to eq(@expected_for_sparse)
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
it "has option :indexing" do
|
|
716
|
+
expect(NMatrix.meshgrid([@x, @y], indexing: :ij)).to eq(@expected_for_ij)
|
|
717
|
+
expect(NMatrix.meshgrid([@x, @y], indexing: :xy)).to eq(@expected_result)
|
|
718
|
+
expect{NMatrix.meshgrid([@x, @y], indexing: :not_ij_not_xy)}.to raise_error(ArgumentError)
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
it "works well with both options set" do
|
|
722
|
+
expect(NMatrix.meshgrid([@x, @y], sparse: true, indexing: :ij)).to eq(@expected_for_sparse_ij)
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
it "is able to take more than two arrays as arguments and works well with options" do
|
|
726
|
+
expect(NMatrix.meshgrid([@x, @y, @z])).to eq(@expected_3dim)
|
|
727
|
+
expect(NMatrix.meshgrid([@x, @y, @z], sparse: true, indexing: :ij)).to eq(@expected_3dim_sparse_ij)
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
end
|