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.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/ext/nmatrix/data/complex.h +364 -0
  3. data/ext/nmatrix/data/data.h +638 -0
  4. data/ext/nmatrix/data/meta.h +64 -0
  5. data/ext/nmatrix/data/ruby_object.h +389 -0
  6. data/ext/nmatrix/math/asum.h +120 -0
  7. data/ext/nmatrix/math/cblas_enums.h +36 -0
  8. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  9. data/ext/nmatrix/math/gemm.h +241 -0
  10. data/ext/nmatrix/math/gemv.h +178 -0
  11. data/ext/nmatrix/math/getrf.h +255 -0
  12. data/ext/nmatrix/math/getrs.h +121 -0
  13. data/ext/nmatrix/math/imax.h +79 -0
  14. data/ext/nmatrix/math/laswp.h +165 -0
  15. data/ext/nmatrix/math/long_dtype.h +49 -0
  16. data/ext/nmatrix/math/math.h +744 -0
  17. data/ext/nmatrix/math/nrm2.h +160 -0
  18. data/ext/nmatrix/math/rot.h +117 -0
  19. data/ext/nmatrix/math/rotg.h +106 -0
  20. data/ext/nmatrix/math/scal.h +71 -0
  21. data/ext/nmatrix/math/trsm.h +332 -0
  22. data/ext/nmatrix/math/util.h +148 -0
  23. data/ext/nmatrix/nm_memory.h +60 -0
  24. data/ext/nmatrix/nmatrix.h +408 -0
  25. data/ext/nmatrix/ruby_constants.h +106 -0
  26. data/ext/nmatrix/storage/common.h +176 -0
  27. data/ext/nmatrix/storage/dense/dense.h +128 -0
  28. data/ext/nmatrix/storage/list/list.h +137 -0
  29. data/ext/nmatrix/storage/storage.h +98 -0
  30. data/ext/nmatrix/storage/yale/class.h +1139 -0
  31. data/ext/nmatrix/storage/yale/iterators/base.h +142 -0
  32. data/ext/nmatrix/storage/yale/iterators/iterator.h +130 -0
  33. data/ext/nmatrix/storage/yale/iterators/row.h +449 -0
  34. data/ext/nmatrix/storage/yale/iterators/row_stored.h +139 -0
  35. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +168 -0
  36. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +123 -0
  37. data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
  38. data/ext/nmatrix/storage/yale/yale.h +202 -0
  39. data/ext/nmatrix/types.h +54 -0
  40. data/ext/nmatrix/util/io.h +115 -0
  41. data/ext/nmatrix/util/sl_list.h +143 -0
  42. data/ext/nmatrix/util/util.h +78 -0
  43. data/ext/nmatrix_lapacke/extconf.rb +200 -0
  44. data/ext/nmatrix_lapacke/lapacke.cpp +100 -0
  45. data/ext/nmatrix_lapacke/lapacke/include/lapacke.h +16445 -0
  46. data/ext/nmatrix_lapacke/lapacke/include/lapacke_config.h +119 -0
  47. data/ext/nmatrix_lapacke/lapacke/include/lapacke_mangling.h +17 -0
  48. data/ext/nmatrix_lapacke/lapacke/include/lapacke_mangling_with_flags.h +17 -0
  49. data/ext/nmatrix_lapacke/lapacke/include/lapacke_utils.h +579 -0
  50. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeev.c +89 -0
  51. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeev_work.c +141 -0
  52. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesdd.c +106 -0
  53. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesdd_work.c +158 -0
  54. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesvd.c +94 -0
  55. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgesvd_work.c +149 -0
  56. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrf.c +51 -0
  57. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrf_work.c +83 -0
  58. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetri.c +77 -0
  59. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetri_work.c +89 -0
  60. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrs.c +56 -0
  61. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgetrs_work.c +102 -0
  62. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrf.c +50 -0
  63. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrf_work.c +82 -0
  64. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotri.c +50 -0
  65. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotri_work.c +82 -0
  66. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrs.c +55 -0
  67. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cpotrs_work.c +101 -0
  68. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeev.c +78 -0
  69. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeev_work.c +136 -0
  70. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesdd.c +88 -0
  71. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesdd_work.c +153 -0
  72. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesvd.c +83 -0
  73. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgesvd_work.c +144 -0
  74. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrf.c +50 -0
  75. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrf_work.c +81 -0
  76. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetri.c +75 -0
  77. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetri_work.c +87 -0
  78. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrs.c +55 -0
  79. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgetrs_work.c +99 -0
  80. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrf.c +50 -0
  81. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrf_work.c +81 -0
  82. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotri.c +50 -0
  83. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotri_work.c +81 -0
  84. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrs.c +54 -0
  85. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dpotrs_work.c +97 -0
  86. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeev.c +78 -0
  87. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeev_work.c +134 -0
  88. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesdd.c +88 -0
  89. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesdd_work.c +152 -0
  90. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesvd.c +83 -0
  91. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgesvd_work.c +143 -0
  92. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrf.c +50 -0
  93. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrf_work.c +81 -0
  94. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetri.c +75 -0
  95. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetri_work.c +87 -0
  96. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrs.c +55 -0
  97. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgetrs_work.c +99 -0
  98. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrf.c +50 -0
  99. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrf_work.c +81 -0
  100. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotri.c +50 -0
  101. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotri_work.c +81 -0
  102. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrs.c +54 -0
  103. data/ext/nmatrix_lapacke/lapacke/src/lapacke_spotrs_work.c +97 -0
  104. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeev.c +89 -0
  105. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeev_work.c +141 -0
  106. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesdd.c +106 -0
  107. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesdd_work.c +158 -0
  108. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesvd.c +94 -0
  109. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgesvd_work.c +149 -0
  110. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrf.c +51 -0
  111. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrf_work.c +83 -0
  112. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetri.c +77 -0
  113. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetri_work.c +89 -0
  114. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrs.c +56 -0
  115. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgetrs_work.c +102 -0
  116. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrf.c +50 -0
  117. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrf_work.c +82 -0
  118. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotri.c +50 -0
  119. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotri_work.c +82 -0
  120. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrs.c +55 -0
  121. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zpotrs_work.c +101 -0
  122. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cge_nancheck.c +62 -0
  123. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cge_trans.c +65 -0
  124. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cpo_nancheck.c +43 -0
  125. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_cpo_trans.c +45 -0
  126. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ctr_nancheck.c +85 -0
  127. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ctr_trans.c +85 -0
  128. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dge_nancheck.c +62 -0
  129. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dge_trans.c +65 -0
  130. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dpo_nancheck.c +43 -0
  131. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dpo_trans.c +45 -0
  132. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dtr_nancheck.c +85 -0
  133. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_dtr_trans.c +85 -0
  134. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_lsame.c +41 -0
  135. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_sge_nancheck.c +62 -0
  136. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_sge_trans.c +65 -0
  137. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_spo_nancheck.c +43 -0
  138. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_spo_trans.c +45 -0
  139. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_str_nancheck.c +85 -0
  140. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_str_trans.c +85 -0
  141. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_xerbla.c +46 -0
  142. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zge_nancheck.c +62 -0
  143. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zge_trans.c +65 -0
  144. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zpo_nancheck.c +43 -0
  145. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_zpo_trans.c +45 -0
  146. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ztr_nancheck.c +85 -0
  147. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_ztr_trans.c +85 -0
  148. data/ext/nmatrix_lapacke/lapacke_nmatrix.h +16 -0
  149. data/ext/nmatrix_lapacke/make_lapacke_cpp.rb +9 -0
  150. data/ext/nmatrix_lapacke/math_lapacke.cpp +967 -0
  151. data/ext/nmatrix_lapacke/math_lapacke/cblas_local.h +576 -0
  152. data/ext/nmatrix_lapacke/math_lapacke/cblas_templates_lapacke.h +51 -0
  153. data/ext/nmatrix_lapacke/math_lapacke/lapacke_templates.h +356 -0
  154. data/ext/nmatrix_lapacke/nmatrix_lapacke.cpp +42 -0
  155. data/lib/nmatrix/lapack_ext_common.rb +69 -0
  156. data/lib/nmatrix/lapacke.rb +213 -0
  157. data/spec/00_nmatrix_spec.rb +730 -0
  158. data/spec/01_enum_spec.rb +190 -0
  159. data/spec/02_slice_spec.rb +389 -0
  160. data/spec/03_nmatrix_monkeys_spec.rb +78 -0
  161. data/spec/2x2_dense_double.mat +0 -0
  162. data/spec/4x4_sparse.mat +0 -0
  163. data/spec/4x5_dense.mat +0 -0
  164. data/spec/blas_spec.rb +193 -0
  165. data/spec/elementwise_spec.rb +303 -0
  166. data/spec/homogeneous_spec.rb +99 -0
  167. data/spec/io/fortran_format_spec.rb +88 -0
  168. data/spec/io/harwell_boeing_spec.rb +98 -0
  169. data/spec/io/test.rua +9 -0
  170. data/spec/io_spec.rb +149 -0
  171. data/spec/lapack_core_spec.rb +482 -0
  172. data/spec/leakcheck.rb +16 -0
  173. data/spec/math_spec.rb +730 -0
  174. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  175. data/spec/nmatrix_yale_spec.rb +286 -0
  176. data/spec/plugins/lapacke/lapacke_spec.rb +303 -0
  177. data/spec/rspec_monkeys.rb +56 -0
  178. data/spec/rspec_spec.rb +34 -0
  179. data/spec/shortcuts_spec.rb +310 -0
  180. data/spec/slice_set_spec.rb +157 -0
  181. data/spec/spec_helper.rb +140 -0
  182. data/spec/stat_spec.rb +203 -0
  183. data/spec/test.pcd +20 -0
  184. data/spec/utm5940.mtx +83844 -0
  185. metadata +262 -0
@@ -0,0 +1,99 @@
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
+ # == homogeneous_spec.rb
24
+ #
25
+ # Specs for the homogeneous transformation matrix methods.
26
+ #
27
+
28
+ require 'spec_helper'
29
+ require "./lib/nmatrix/homogeneous.rb"
30
+
31
+ require 'pry'
32
+
33
+ describe 'NMatrix' do
34
+ context ".x_rotation" do
35
+ it "should generate a matrix representing a rotation about the x axis" do
36
+ x = NMatrix.x_rotation(Math::PI/6)
37
+ expect(x).to be_within(1e-8).of(NMatrix.new([4,4], [1.0, 0.0, 0.0, 0.0,
38
+ 0.0, Math.cos(Math::PI/6), -0.5, 0.0,
39
+ 0.0, 0.5, Math.cos(Math::PI/6), 0.0,
40
+ 0.0, 0.0, 0.0, 1.0] ))
41
+ end
42
+ end
43
+
44
+
45
+ context ".y_rotation" do
46
+ it "should generate a matrix representing a rotation about the y axis" do
47
+ y = NMatrix.y_rotation(Math::PI/6)
48
+ expect(y).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), 0.0, 0.5, 0.0,
49
+ 0.0, 1.0, 0.0, 0.0,
50
+ -0.5, 0.0, Math.cos(Math::PI/6), 0.0,
51
+ 0.0, 0.0, 0.0, 1.0] ))
52
+ end
53
+ end
54
+
55
+ context ".z_rotation" do
56
+ it "should generate a matrix representing a rotation about the z axis" do
57
+ z = NMatrix.z_rotation(Math::PI/6)
58
+ expect(z).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), -0.5, 0.0, 0.0,
59
+ 0.5, Math.cos(Math::PI/6), 0.0, 0.0,
60
+ 0.0, 0.0, 1.0, 0.0,
61
+ 0.0, 0.0, 0.0, 1.0] ))
62
+ end
63
+ end
64
+
65
+ context ".translation" do
66
+ it "should generate a translation matrix from an Array" do
67
+ t = NMatrix.translation([4,5,6])
68
+ expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
69
+ 0, 1, 0, 5,
70
+ 0, 0, 1, 6,
71
+ 0, 0, 0, 1] ))
72
+ end
73
+
74
+ it "should generate a translation matrix from x, y, and z values" do
75
+ t = NMatrix.translation(4,5,6)
76
+ expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
77
+ 0, 1, 0, 5,
78
+ 0, 0, 1, 6,
79
+ 0, 0, 0, 1] ))
80
+ end
81
+
82
+ it "should generate a translation matrix from an NMatrix with correctly inferred dtype" do
83
+ t = NMatrix.translation(NMatrix.new([3,1], [4,5,6], dtype: :float64) )
84
+ expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
85
+ 0, 1, 0, 5,
86
+ 0, 0, 1, 6,
87
+ 0, 0, 0, 1] ))
88
+ expect(t.dtype).to be(:float64)
89
+ end
90
+ end
91
+
92
+ context "#quaternion" do
93
+ it "should generate a singularity-free quaternion" do
94
+ transform = NMatrix.new([4,4], [-0.9995825,-0.02527934,-0.0139845,50.61761,-0.02732551,0.9844284,0.1736463,-22.95566,0.009376526,0.1739562,-0.9847089,7.1521,0,0,0,1])
95
+ q = transform.quaternion
96
+ expect(Math.sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)).to be_within(1e-6).of(1.0)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,88 @@
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
+ # == fortran_format_spec.rb
24
+ #
25
+ # Basic tests for NMatrix::IO::FortranFormat.
26
+ #
27
+
28
+ require './lib/nmatrix'
29
+
30
+ describe NMatrix::IO::FortranFormat do
31
+ it "parses integer FORTRAN formats" do
32
+ int_fmt = NMatrix::IO::FortranFormat::Reader.new('(16I5)').parse
33
+
34
+ expect(int_fmt[:format_code]).to eq "INT_ID"
35
+ expect(int_fmt[:repeat]) .to eq 16
36
+ expect(int_fmt[:field_width]).to eq 5
37
+
38
+ int_fmt = NMatrix::IO::FortranFormat::Reader.new('(I4)').parse
39
+
40
+ expect(int_fmt[:format_code]).to eq "INT_ID"
41
+ expect(int_fmt[:field_width]).to eq 4
42
+ end
43
+
44
+ it "parses floating point FORTRAN formats" do
45
+ fp_fmt = NMatrix::IO::FortranFormat::Reader.new('(10F7.1)').parse
46
+
47
+ expect(fp_fmt[:format_code]) .to eq "FP_ID"
48
+ expect(fp_fmt[:repeat]) .to eq 10
49
+ expect(fp_fmt[:field_width]) .to eq 7
50
+ expect(fp_fmt[:post_decimal_width]).to eq 1
51
+
52
+ fp_fmt = NMatrix::IO::FortranFormat::Reader.new('(F4.2)').parse
53
+
54
+ expect(fp_fmt[:format_code]) .to eq "FP_ID"
55
+ expect(fp_fmt[:field_width]) .to eq 4
56
+ expect(fp_fmt[:post_decimal_width]).to eq 2
57
+ end
58
+
59
+ it "parses exponential FORTRAN formats" do
60
+ exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(2E8.3E3)').parse
61
+
62
+ expect(exp_fmt[:format_code]) .to eq "EXP_ID"
63
+ expect(exp_fmt[:repeat]) .to eq 2
64
+ expect(exp_fmt[:field_width]) .to eq 8
65
+ expect(exp_fmt[:post_decimal_width]).to eq 3
66
+ expect(exp_fmt[:exponent_width]) .to eq 3
67
+
68
+ exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(3E3.6)').parse
69
+
70
+ expect(exp_fmt[:format_code]) .to eq "EXP_ID"
71
+ expect(exp_fmt[:repeat]) .to eq 3
72
+ expect(exp_fmt[:field_width]) .to eq 3
73
+ expect(exp_fmt[:post_decimal_width]).to eq 6
74
+
75
+ exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(E4.5)').parse
76
+ expect(exp_fmt[:format_code]) .to eq "EXP_ID"
77
+ expect(exp_fmt[:field_width]) .to eq 4
78
+ expect(exp_fmt[:post_decimal_width]).to eq 5
79
+ end
80
+
81
+ ['I3', '(F4)', '(E3.', '(E4.E5)'].each do |bad_format|
82
+ it "doesn't let bad input through : #{bad_format}" do
83
+ expect {
84
+ NMatrix::IO::FortranFormat::Reader.new(bad_format).parse
85
+ }.to raise_error(IOError)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,98 @@
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
+ # == io_spec.rb
24
+ #
25
+ # Basic tests for NMatrix::IO::HarwelBoeing.
26
+
27
+ # TODO : After the fortran format thing is done
28
+ require 'spec_helper'
29
+ require "./lib/nmatrix"
30
+
31
+ describe NMatrix::IO::HarwellBoeing do
32
+ def check_file_header header
33
+ expect(header[:title]) .to eq("Title")
34
+ expect(header[:key]) .to eq("Key")
35
+
36
+ expect(header[:totcrd]) .to eq(5)
37
+ expect(header[:ptrcrd]) .to eq(1)
38
+ expect(header[:indcrd]) .to eq(1)
39
+ expect(header[:valcrd]) .to eq(3)
40
+ expect(header[:rhscrd]) .to eq(0)
41
+
42
+ expect(header[:mxtype]) .to eq('RUA')
43
+ expect(header[:nrow]) .to eq(5)
44
+ expect(header[:ncol]) .to eq(5)
45
+ expect(header[:nnzero]) .to eq(13)
46
+ expect(header[:neltvl]) .to eq(0)
47
+
48
+ expect(header[:ptrfmt]) .to eq({
49
+ format_code: "INT_ID",
50
+ repeat: 6,
51
+ field_width: 3
52
+ })
53
+ expect(header[:indfmt]) .to eq({
54
+ format_code: "INT_ID",
55
+ repeat: 13,
56
+ field_width: 3
57
+ })
58
+ expect(header[:valfmt]) .to eq({
59
+ format_code: "EXP_ID",
60
+ repeat: 5,
61
+ field_width: 15,
62
+ post_decimal_width: 8
63
+ })
64
+ expect(header[:rhsfmt]) .to eq({
65
+ format_code: "EXP_ID",
66
+ repeat: 5,
67
+ field_width: 15,
68
+ post_decimal_width: 8
69
+ })
70
+ end
71
+
72
+ it "loads a Harwell Boeing file values and header (currently real only)" do
73
+ n, h = NMatrix::IO::HarwellBoeing.load("spec/io/test.rua")
74
+
75
+ expect(n.is_a? NMatrix).to eq(true)
76
+ expect(n.cols) .to eq(5)
77
+ expect(n.rows) .to eq(5)
78
+
79
+ expect(n[0,0]) .to eq(11)
80
+ expect(n[4,4]) .to eq(55)
81
+
82
+ expect(h.is_a? Hash).to eq(true)
83
+ check_file_header(h)
84
+ end
85
+
86
+ it "loads only the header of the file when specified" do
87
+ h = NMatrix::IO::HarwellBoeing.load("spec/io/test.rua", header: true)
88
+
89
+ expect(h.is_a? Hash).to eq(true)
90
+ check_file_header(h)
91
+ end
92
+
93
+ it "raises error for wrong Harwell Boeing file name" do
94
+ expect{
95
+ NMatrix::IO::HarwellBoeing.load("spec/io/wrong.afx")
96
+ }.to raise_error(IOError)
97
+ end
98
+ end
@@ -0,0 +1,9 @@
1
+ Title Key
2
+ 5 1 1 3 0
3
+ RUA 5 5 13 0
4
+ (6I3) (13I3) (5E15.8) (5E15.8)
5
+ 1 4 7 8 11 14
6
+ 1 3 5 2 3 5 3 1 3 4 3 4 5
7
+ 11.0 31.0 51.0 22.0 32.0
8
+ 52.0 33.0 14.0 34.0 44.0
9
+ 35.0 45.0 55.0
@@ -0,0 +1,149 @@
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
+ # == io_spec.rb
24
+ #
25
+ # Basic tests for NMatrix::IO.
26
+ #
27
+ require "tmpdir" # Used to avoid cluttering the repository.
28
+ require 'spec_helper'
29
+ require "./lib/nmatrix"
30
+
31
+ describe NMatrix::IO do
32
+ let(:tmp_dir) { Dir.mktmpdir }
33
+ let(:test_out) { File.join(tmp_dir, 'test-out') }
34
+
35
+ it "repacks a string" do
36
+ expect(NMatrix::IO::Matlab.repack("hello", :miUINT8, :byte)).to eq("hello")
37
+ end
38
+
39
+ it "creates yale from internal byte-string function" do
40
+ ia = NMatrix::IO::Matlab.repack("\0\1\3\3\4", :miUINT8, :itype)
41
+ ja = NMatrix::IO::Matlab.repack("\0\1\3\0\0\0\0\0\0\0\0", :miUINT8, :itype)
42
+ n = NMatrix.new(:yale, [4,4], :byte, ia, ja, "\2\3\5\4", :byte)
43
+ expect(n[0,0]).to eq(2)
44
+ expect(n[1,1]).to eq(3)
45
+ expect(n[1,3]).to eq(5)
46
+ expect(n[3,0]).to eq(4)
47
+ expect(n[2,2]).to eq(0)
48
+ expect(n[3,3]).to eq(0)
49
+ end
50
+
51
+ it "reads MATLAB .mat file containing a single square sparse matrix" do
52
+ # Note: same matrix as above
53
+ n = NMatrix::IO::Matlab.load_mat("spec/4x4_sparse.mat")
54
+ expect(n[0,0]).to eq(2)
55
+ expect(n[1,1]).to eq(3)
56
+ expect(n[1,3]).to eq(5)
57
+ expect(n[3,0]).to eq(4)
58
+ expect(n[2,2]).to eq(0)
59
+ expect(n[3,3]).to eq(0)
60
+ end
61
+
62
+ it "reads MATLAB .mat file containing a single dense integer matrix" do
63
+ n = NMatrix::IO::Matlab.load_mat("spec/4x5_dense.mat")
64
+ m = NMatrix.new([4,5], [16,17,18,19,20,15,14,13,12,11,6,7,8,9,10,5,4,3,2,1])
65
+ expect(n).to eq(m)
66
+ end
67
+
68
+ it "reads MATLAB .mat file containing a single dense double matrix" do
69
+ n = NMatrix::IO::Matlab.load_mat("spec/2x2_dense_double.mat")
70
+ m = NMatrix.new(2, [1.1, 2.0, 3.0, 4.0], dtype: :float64)
71
+ expect(n).to eq(m)
72
+ end
73
+
74
+ it "loads and saves MatrixMarket .mtx file containing a single large sparse double matrix" do
75
+ pending "spec disabled because it's so slow"
76
+ n = NMatrix::IO::Market.load("spec/utm5940.mtx")
77
+ NMatrix::IO::Market.save(n, "spec/utm5940.saved.mtx")
78
+ expect(`wc -l spec/utm5940.mtx`.split[0]).to eq(`wc -l spec/utm5940.saved.mtx`.split[0])
79
+ end
80
+
81
+ it "loads a Point Cloud Library PCD file" do
82
+ n = NMatrix::IO::PointCloud.load("spec/test.pcd")
83
+ expect(n.column(0).sort.uniq.size).to eq(1)
84
+ expect(n.column(0).sort.uniq.first).to eq(207.008)
85
+ expect(n[0,3]).to eq(0)
86
+ end
87
+
88
+ it "raises an error when reading a non-existent file" do
89
+ fn = rand(10000000).to_i.to_s
90
+ while File.exist?(fn)
91
+ fn = rand(10000000).to_i.to_s
92
+ end
93
+ expect{ NMatrix.read(fn) }.to raise_error(Errno::ENOENT)
94
+ end
95
+
96
+ it "reads and writes NMatrix dense" do
97
+ n = NMatrix.new(:dense, [4,3], [0,1,2,3,4,5,6,7,8,9,10,11], :int32)
98
+ n.write(test_out)
99
+
100
+ m = NMatrix.read(test_out)
101
+ expect(n).to eq(m)
102
+ end
103
+
104
+ it "reads and writes NMatrix dense as symmetric" do
105
+ n = NMatrix.new(:dense, 3, [0,1,2,1,3,4,2,4,5], :int16)
106
+ n.write(test_out, :symmetric)
107
+
108
+ m = NMatrix.read(test_out)
109
+ expect(n).to eq(m)
110
+ end
111
+
112
+ it "reads and writes NMatrix dense as skew" do
113
+ n = NMatrix.new(:dense, 3, [0,1,2,-1,3,4,-2,-4,5], :float64)
114
+ n.write(test_out, :skew)
115
+
116
+ m = NMatrix.read(test_out)
117
+ expect(n).to eq(m)
118
+ end
119
+
120
+ it "reads and writes NMatrix dense as hermitian" do
121
+ n = NMatrix.new(:dense, 3, [0,1,2,1,3,4,2,4,5], :complex64)
122
+ n.write(test_out, :hermitian)
123
+
124
+ m = NMatrix.read(test_out)
125
+ expect(n).to eq(m)
126
+ end
127
+
128
+ it "reads and writes NMatrix dense as upper" do
129
+ n = NMatrix.new(:dense, 3, [-1,1,2,3,4,5,6,7,8], :int32)
130
+ n.write(test_out, :upper)
131
+
132
+ m = NMatrix.new(:dense, 3, [-1,1,2,0,4,5,0,0,8], :int32) # lower version of the same
133
+
134
+ o = NMatrix.read(test_out)
135
+ expect(o).to eq(m)
136
+ expect(o).not_to eq(n)
137
+ end
138
+
139
+ it "reads and writes NMatrix dense as lower" do
140
+ n = NMatrix.new(:dense, 3, [-1,1,2,3,4,5,6,7,8], :int32)
141
+ n.write(test_out, :lower)
142
+
143
+ m = NMatrix.new(:dense, 3, [-1,0,0,3,4,0,6,7,8], :int32) # lower version of the same
144
+
145
+ o = NMatrix.read(test_out)
146
+ expect(o).to eq(m)
147
+ expect(o).not_to eq(n)
148
+ end
149
+ end
@@ -0,0 +1,482 @@
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
+ # == lapack_core_spec.rb
24
+ #
25
+ # Tests for LAPACK functions that have internal implementations (i.e. they
26
+ # don't rely on external libraries) and also functions that are implemented
27
+ # by both nmatrix-atlas and nmatrix-lapacke. These tests will also be run for the
28
+ # plugins that do use external libraries, since they will override the
29
+ # internal implmentations.
30
+ #
31
+
32
+ require 'spec_helper'
33
+
34
+ describe "NMatrix::LAPACK functions with internal implementations" do
35
+ # where integer math is allowed
36
+ [:byte, :int8, :int16, :int32, :int64, :float32, :float64, :complex64, :complex128].each do |dtype|
37
+ context dtype do
38
+ # This spec seems a little weird. It looks like laswp ignores the last
39
+ # element of piv, though maybe I misunderstand smth. It would make
40
+ # more sense if piv were [2,1,3,3]
41
+ it "exposes clapack laswp" do
42
+ a = NMatrix.new(:dense, [3,4], [1,2,3,4,5,6,7,8,9,10,11,12], dtype)
43
+ NMatrix::LAPACK::clapack_laswp(3, a, 4, 0, 3, [2,1,3,0], 1)
44
+ b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype)
45
+ expect(a).to eq(b)
46
+ end
47
+
48
+ # This spec is OK, because the default behavior for permute_columns
49
+ # is :intuitive, which is different from :lapack (default laswp behavior)
50
+ it "exposes NMatrix#permute_columns and #permute_columns! (user-friendly laswp)" do
51
+ a = NMatrix.new(:dense, [3,4], [1,2,3,4,5,6,7,8,9,10,11,12], dtype)
52
+ b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype)
53
+ piv = [2,1,3,0]
54
+ r = a.permute_columns(piv)
55
+ expect(r).not_to eq(a)
56
+ expect(r).to eq(b)
57
+ a.permute_columns!(piv)
58
+ expect(a).to eq(b)
59
+ end
60
+ end
61
+ end
62
+
63
+ # where integer math is not allowed
64
+ [:float32, :float64, :complex64, :complex128].each do |dtype|
65
+ context dtype do
66
+
67
+ # clapack_getrf performs a LU decomposition, but unlike the
68
+ # standard LAPACK getrf, it's the upper matrix that has unit diagonals
69
+ # and the permutation is done in columns not rows. See the code for
70
+ # details.
71
+ # Also the rows in the pivot vector are indexed starting from 0,
72
+ # rather than 1 as in LAPACK
73
+ it "calculates LU decomposition using clapack_getrf (row-major, square)" do
74
+ a = NMatrix.new(3, [4,9,2,3,5,7,8,1,6], dtype: dtype)
75
+ ipiv = NMatrix::LAPACK::clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1])
76
+ b = NMatrix.new(3,[9, 2.0/9, 4.0/9,
77
+ 5, 53.0/9, 7.0/53,
78
+ 1, 52.0/9, 360.0/53], dtype: dtype)
79
+ ipiv_true = [1,2,2]
80
+
81
+ # delta varies for different dtypes
82
+ err = case dtype
83
+ when :float32, :complex64
84
+ 1e-6
85
+ when :float64, :complex128
86
+ 1e-15
87
+ end
88
+
89
+ expect(a).to be_within(err).of(b)
90
+ expect(ipiv).to eq(ipiv_true)
91
+ end
92
+
93
+ it "calculates LU decomposition using clapack_getrf (row-major, rectangular)" do
94
+ a = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype)
95
+ ipiv = NMatrix::LAPACK::clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1])
96
+ #we can't use GETRF_SOLUTION_ARRAY here, because of the different
97
+ #conventions of clapack_getrf
98
+ b = NMatrix.new([3,4],[10.0, -0.1, 0.0, 0.4,
99
+ 3.0, 9.3, 20.0/93, 38.0/93,
100
+ 1.0, 7.1, 602.0/93, 251.0/602], dtype: dtype)
101
+ ipiv_true = [2,2,2]
102
+
103
+ # delta varies for different dtypes
104
+ err = case dtype
105
+ when :float32, :complex64
106
+ 1e-6
107
+ when :float64, :complex128
108
+ 1e-15
109
+ end
110
+
111
+ expect(a).to be_within(err).of(b)
112
+ expect(ipiv).to eq(ipiv_true)
113
+ end
114
+
115
+ #Normally we wouldn't check column-major routines, since all our matrices
116
+ #are row-major, but we use the column-major version in #getrf!, so we
117
+ #want to test it here.
118
+ it "calculates LU decomposition using clapack_getrf (col-major, rectangular)" do
119
+ #this is supposed to represent the 3x2 matrix
120
+ # -1 2
121
+ # 0 3
122
+ # 1 -2
123
+ a = NMatrix.new([1,6], [-1,0,1,2,3,-2], dtype: dtype)
124
+ ipiv = NMatrix::LAPACK::clapack_getrf(:col, 3, 2, a, 3)
125
+ b = NMatrix.new([1,6], [-1,0,-1,2,3,0], dtype: dtype)
126
+ ipiv_true = [0,1]
127
+
128
+ # delta varies for different dtypes
129
+ err = case dtype
130
+ when :float32, :complex64
131
+ 1e-6
132
+ when :float64, :complex128
133
+ 1e-15
134
+ end
135
+
136
+ expect(a).to be_within(err).of(b)
137
+ expect(ipiv).to eq(ipiv_true)
138
+ end
139
+
140
+ it "calculates LU decomposition using #getrf! (rectangular)" do
141
+ a = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype)
142
+ ipiv = a.getrf!
143
+ b = NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype)
144
+ ipiv_true = [2,3,3]
145
+
146
+ # delta varies for different dtypes
147
+ err = case dtype
148
+ when :float32, :complex64
149
+ 1e-6
150
+ when :float64, :complex128
151
+ 1e-14
152
+ end
153
+
154
+ expect(a).to be_within(err).of(b)
155
+ expect(ipiv).to eq(ipiv_true)
156
+ end
157
+
158
+ it "calculates LU decomposition using #getrf! (square)" do
159
+ a = NMatrix.new([4,4], [0,1,2,3, 1,1,1,1, 0,-1,-2,0, 0,2,0,2], dtype: dtype)
160
+ ipiv = a.getrf!
161
+
162
+ b = NMatrix.new([4,4], [1,1,1,1, 0,2,0,2, 0,-0.5,-2,1, 0,0.5,-1,3], dtype: dtype)
163
+ ipiv_true = [2,4,3,4]
164
+
165
+ expect(a).to eq(b)
166
+ expect(ipiv).to eq(ipiv_true)
167
+ end
168
+
169
+ # Together, these calls are basically xGESV from LAPACK: http://www.netlib.org/lapack/double/dgesv.f
170
+ it "exposes clapack_getrs" do
171
+ a = NMatrix.new(3, [-2,4,-3, 3,-2,1, 0,-4,3], dtype: dtype)
172
+ ipiv = NMatrix::LAPACK::clapack_getrf(:row, 3, 3, a, 3)
173
+ b = NMatrix.new([3,1], [-1, 17, -9], dtype: dtype)
174
+
175
+ NMatrix::LAPACK::clapack_getrs(:row, false, 3, 1, a, 3, ipiv, b, 3)
176
+
177
+ expect(b[0]).to eq(5)
178
+ expect(b[1]).to eq(-15.0/2)
179
+ expect(b[2]).to eq(-13)
180
+ end
181
+
182
+ it "solves matrix equation (non-vector rhs) using clapack_getrs" do
183
+ a = NMatrix.new(3, [-2,4,-3, 3,-2,1, 0,-4,3], dtype: dtype)
184
+ b = NMatrix.new([3,2], [-1,2, 17,1, -9,-4], dtype: dtype)
185
+
186
+ n = a.shape[0]
187
+ nrhs = b.shape[1]
188
+
189
+ ipiv = NMatrix::LAPACK::clapack_getrf(:row, n, n, a, n)
190
+ # Even though we pass :row to clapack_getrs, it still interprets b as
191
+ # column-major, so need to transpose b before and after:
192
+ b = b.transpose
193
+ NMatrix::LAPACK::clapack_getrs(:row, false, n, nrhs, a, n, ipiv, b, n)
194
+ b = b.transpose
195
+
196
+ b_true = NMatrix.new([3,2], [5,1, -7.5,1, -13,0], dtype: dtype)
197
+ expect(b).to eq(b_true)
198
+ end
199
+
200
+ #posv is like potrf+potrs
201
+ #posv is implemented in both nmatrix-atlas and nmatrix-lapacke, so the spec
202
+ #needs to be shared here
203
+ it "solves a (symmetric positive-definite) matrix equation using posv (vector rhs)" do
204
+ a = NMatrix.new(3, [4, 0,-1,
205
+ 0, 2, 1,
206
+ 0, 0, 1], dtype: dtype)
207
+ b = NMatrix.new([3,1], [4,2,0], dtype: dtype)
208
+
209
+ begin
210
+ x = NMatrix::LAPACK::posv(:upper, a, b)
211
+ rescue NotImplementedError => e
212
+ pending e.to_s
213
+ end
214
+
215
+ x_true = NMatrix.new([3,1], [1, 1, 0], dtype: dtype)
216
+
217
+ err = case dtype
218
+ when :float32, :complex64
219
+ 1e-5
220
+ when :float64, :complex128
221
+ 1e-14
222
+ end
223
+
224
+ expect(x).to be_within(err).of(x_true)
225
+ end
226
+
227
+ it "solves a (symmetric positive-definite) matrix equation using posv (non-vector rhs)" do
228
+ a = NMatrix.new(3, [4, 0,-1,
229
+ 0, 2, 1,
230
+ 0, 0, 1], dtype: dtype)
231
+ b = NMatrix.new([3,2], [4,-1, 2,-1, 0,0], dtype: dtype)
232
+
233
+ begin
234
+ x = NMatrix::LAPACK::posv(:upper, a, b)
235
+ rescue NotImplementedError => e
236
+ pending e.to_s
237
+ end
238
+
239
+ x_true = NMatrix.new([3,2], [1,0, 1,-1, 0,1], dtype: dtype)
240
+
241
+ err = case dtype
242
+ when :float32, :complex64
243
+ 1e-5
244
+ when :float64, :complex128
245
+ 1e-14
246
+ end
247
+
248
+ expect(x).to be_within(err).of(x_true)
249
+ end
250
+
251
+ it "calculates the singular value decomposition with NMatrix#gesvd" do
252
+ #example from Wikipedia
253
+ m = 4
254
+ n = 5
255
+ mn_min = [m,n].min
256
+ a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype)
257
+
258
+ begin
259
+ u, s, vt = a.gesvd
260
+ rescue NotImplementedError => e
261
+ pending e.to_s
262
+ end
263
+
264
+ s_true = NMatrix.new([mn_min,1], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype)
265
+ u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype)
266
+ vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype)
267
+
268
+ err = case dtype
269
+ when :float32, :complex64
270
+ 1e-5
271
+ when :float64, :complex128
272
+ 1e-14
273
+ end
274
+
275
+ expect(s).to be_within(err).of(s_true)
276
+ expect(u).to be_within(err).of(u_true)
277
+ expect(vt).to be_within(err).of(vt_true)
278
+
279
+ expect(s.dtype).to eq(a.abs_dtype)
280
+ expect(u.dtype).to eq(dtype)
281
+ expect(vt.dtype).to eq(dtype)
282
+ end
283
+
284
+ it "calculates the singular value decomposition with NMatrix#gesdd" do
285
+ #example from Wikipedia
286
+ m = 4
287
+ n = 5
288
+ mn_min = [m,n].min
289
+ a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype)
290
+
291
+ begin
292
+ u, s, vt = a.gesdd
293
+ rescue NotImplementedError => e
294
+ pending e.to_s
295
+ end
296
+
297
+ s_true = NMatrix.new([mn_min,1], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype)
298
+ u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype)
299
+ vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype)
300
+
301
+ err = case dtype
302
+ when :float32, :complex64
303
+ 1e-5
304
+ when :float64, :complex128
305
+ 1e-14
306
+ end
307
+
308
+ expect(s).to be_within(err).of(s_true)
309
+ expect(u).to be_within(err).of(u_true)
310
+ expect(vt).to be_within(err).of(vt_true)
311
+ end
312
+
313
+
314
+ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (real matrix, complex eigenvalues)" do
315
+ n = 3
316
+ a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype)
317
+
318
+ begin
319
+ eigenvalues, vl, vr = NMatrix::LAPACK.geev(a)
320
+ rescue NotImplementedError => e
321
+ pending e.to_s
322
+ end
323
+
324
+ eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64))
325
+ vr_true = NMatrix.new([n,n],[0,0,1,
326
+ 2/Math.sqrt(6),2/Math.sqrt(6),0,
327
+ Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64))
328
+ vl_true = NMatrix.new([n,n],[0,0,1,
329
+ Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0,
330
+ 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64))
331
+
332
+ err = case dtype
333
+ when :float32, :complex64
334
+ 1e-6
335
+ when :float64, :complex128
336
+ 1e-15
337
+ end
338
+
339
+ expect(eigenvalues).to be_within(err).of(eigenvalues_true)
340
+ expect(vr).to be_within(err).of(vr_true)
341
+ expect(vl).to be_within(err).of(vl_true)
342
+
343
+ expect(eigenvalues.dtype).to eq(NMatrix.upcast(dtype, :complex64))
344
+ expect(vr.dtype).to eq(NMatrix.upcast(dtype, :complex64))
345
+ expect(vl.dtype).to eq(NMatrix.upcast(dtype, :complex64))
346
+ end
347
+
348
+ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (real matrix, real eigenvalues)" do
349
+ n = 3
350
+ a = NMatrix.new([n,n], [2,0,0, 0,3,2, 0,1,2], dtype: dtype)
351
+
352
+ begin
353
+ eigenvalues, vl, vr = NMatrix::LAPACK.geev(a)
354
+ rescue NotImplementedError => e
355
+ pending e.to_s
356
+ end
357
+
358
+ eigenvalues_true = NMatrix.new([n,1], [1, 4, 2], dtype: dtype)
359
+
360
+ # For some reason, some of the eigenvectors have different signs
361
+ # when we use the complex versions of geev. This is totally fine, since
362
+ # they are still normalized eigenvectors even with the sign flipped.
363
+ if a.complex_dtype?
364
+ vr_true = NMatrix.new([n,n],[0,0,1,
365
+ 1/Math.sqrt(2),2/Math.sqrt(5),0,
366
+ -1/Math.sqrt(2),1/Math.sqrt(5),0], dtype: dtype)
367
+ vl_true = NMatrix.new([n,n],[0,0,1,
368
+ -1/Math.sqrt(5),1/Math.sqrt(2),0,
369
+ 2/Math.sqrt(5),1/Math.sqrt(2),0], dtype: dtype)
370
+ else
371
+ vr_true = NMatrix.new([n,n],[0,0,1,
372
+ 1/Math.sqrt(2),-2/Math.sqrt(5),0,
373
+ -1/Math.sqrt(2),-1/Math.sqrt(5),0], dtype: dtype)
374
+ vl_true = NMatrix.new([n,n],[0,0,1,
375
+ 1/Math.sqrt(5),-1/Math.sqrt(2),0,
376
+ -2/Math.sqrt(5),-1/Math.sqrt(2),0], dtype: dtype)
377
+ end
378
+
379
+ err = case dtype
380
+ when :float32, :complex64
381
+ 1e-6
382
+ when :float64, :complex128
383
+ 1e-15
384
+ end
385
+
386
+ expect(eigenvalues).to be_within(err).of(eigenvalues_true)
387
+ expect(vr).to be_within(err).of(vr_true)
388
+ expect(vl).to be_within(err).of(vl_true)
389
+
390
+ expect(eigenvalues.dtype).to eq(dtype)
391
+ expect(vr.dtype).to eq(dtype)
392
+ expect(vl.dtype).to eq(dtype)
393
+ end
394
+
395
+ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (left eigenvectors only)" do
396
+ n = 3
397
+ a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype)
398
+
399
+ begin
400
+ eigenvalues, vl = NMatrix::LAPACK.geev(a, :left)
401
+ rescue NotImplementedError => e
402
+ pending e.to_s
403
+ end
404
+
405
+ eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64))
406
+ vl_true = NMatrix.new([n,n],[0,0,1,
407
+ Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0,
408
+ 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64))
409
+
410
+ err = case dtype
411
+ when :float32, :complex64
412
+ 1e-6
413
+ when :float64, :complex128
414
+ 1e-15
415
+ end
416
+
417
+ expect(eigenvalues).to be_within(err).of(eigenvalues_true)
418
+ expect(vl).to be_within(err).of(vl_true)
419
+ end
420
+
421
+ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (right eigenvectors only)" do
422
+ n = 3
423
+ a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype)
424
+
425
+ begin
426
+ eigenvalues, vr = NMatrix::LAPACK.geev(a, :right)
427
+ rescue NotImplementedError => e
428
+ pending e.to_s
429
+ end
430
+
431
+ eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64))
432
+ vr_true = NMatrix.new([n,n],[0,0,1,
433
+ 2/Math.sqrt(6),2/Math.sqrt(6),0,
434
+ Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64))
435
+
436
+ err = case dtype
437
+ when :float32, :complex64
438
+ 1e-6
439
+ when :float64, :complex128
440
+ 1e-15
441
+ end
442
+
443
+ expect(eigenvalues).to be_within(err).of(eigenvalues_true)
444
+ expect(vr).to be_within(err).of(vr_true)
445
+ end
446
+ end
447
+ end
448
+
449
+ [:complex64, :complex128].each do |dtype|
450
+ context dtype do
451
+ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (complex matrix)" do
452
+ n = 3
453
+ a = NMatrix.new([n,n], [Complex(0,1),0,0, 0,3,2, 0,1,2], dtype: dtype)
454
+
455
+ begin
456
+ eigenvalues, vl, vr = NMatrix::LAPACK.geev(a)
457
+ rescue NotImplementedError => e
458
+ pending e.to_s
459
+ end
460
+
461
+ eigenvalues_true = NMatrix.new([n,1], [1, 4, Complex(0,1)], dtype: dtype)
462
+ vr_true = NMatrix.new([n,n],[0,0,1,
463
+ 1/Math.sqrt(2),2/Math.sqrt(5),0,
464
+ -1/Math.sqrt(2),1/Math.sqrt(5),0], dtype: dtype)
465
+ vl_true = NMatrix.new([n,n],[0,0,1,
466
+ -1/Math.sqrt(5),1/Math.sqrt(2),0,
467
+ 2/Math.sqrt(5),1/Math.sqrt(2),0], dtype: dtype)
468
+
469
+ err = case dtype
470
+ when :float32, :complex64
471
+ 1e-6
472
+ when :float64, :complex128
473
+ 1e-15
474
+ end
475
+
476
+ expect(eigenvalues).to be_within(err).of(eigenvalues_true)
477
+ expect(vr).to be_within(err).of(vr_true)
478
+ expect(vl).to be_within(err).of(vl_true)
479
+ end
480
+ end
481
+ end
482
+ end