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,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
|
data/spec/io/test.rua
ADDED
data/spec/io_spec.rb
ADDED
@@ -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
|