numo-linalg 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef1ecaaf8a71faee9a7cef26bc35fae50230224856ab5dd6186cee93e5cca69d
4
- data.tar.gz: f2e5e5944ad4832ef4ad4db05f6e94142fefb780e19282d94ece2a055cf447a0
3
+ metadata.gz: c7c0b667ffa1e3720ba31c4b03b984cbb2fb357c82df6d6ad4ce063be4f38fe4
4
+ data.tar.gz: 52ecb22fc5d7a483aa0fbe82b04bd38747457661f4f6846693d2b2bbb7c9c19b
5
5
  SHA512:
6
- metadata.gz: 3fcf1506aa63ccbba57208e358102ae0dc537cd80b530e4b359b07d01a7cb1da11261dfd6d7028224175ae0f38014ec0373b99fc339caa2b952ad48c0fb26fd7
7
- data.tar.gz: c7a9eb8b65719571120a6a122721e1eaadc240164e182a5095ff45018453a90f4cc48f99ef219305827beace8839bdebb0d27d35dfb5f64ec64f54d5406a8910
6
+ metadata.gz: 38a2dc9a2bb4af3c273a11c22213a4a6db25d8d93be85e51cf3b418717e92336a14beff65b1202b7215254701593ce15970cf063be502a17640d8bc9d70b12c0
7
+ data.tar.gz: 3f7b0c47d0ced6ba5a1a58b1298bb342712a37ed6c24103bd5a41d399aa94c4cac066e6c8791cb3f283fad398e4dafe796723d7aadceca2b2a99f439882ce46c
data/README.md CHANGED
@@ -13,13 +13,13 @@ Under development!
13
13
  This is a binding of BLAS/LAPACK for Numo::NArray using dynamic linking loader.
14
14
  This desgin allows you to change backend libraries without re-compiling.
15
15
 
16
- ### [Numo::Linalg API](http://ruby-numo.github.io/linalg/yard/Numo/Linalg.html)
16
+ ### [Numo::Linalg API](http://ruby-numo.github.io/numo-linalg/yard/Numo/Linalg.html)
17
17
 
18
18
  * Matrix and vector products
19
19
  * dot, matmul
20
20
  * Decomposition
21
21
  * lu, lu\_fact, lu\_inv, lu\_solve, ldl, cholesky, cho\_fact, cho\_inv, cho\_solve,
22
- qr, svd, svdvals
22
+ qr, svd, svdvals, orth, null_space
23
23
  * Matrix eigenvalues
24
24
  * eig, eigh, eigvals, eigvalsh
25
25
  * Norms and other numbers
@@ -29,8 +29,8 @@ This desgin allows you to change backend libraries without re-compiling.
29
29
 
30
30
  ### Low-level modules
31
31
 
32
- * [Numo::Linalg::Blas](http://ruby-numo.github.io/linalg/yard/Numo/Linalg/Blas.html) - Low-level BLAS functions
33
- * [Numo::Linalg::Lapack](http://ruby-numo.github.io/linalg/yard/Numo/Linalg/Lapack.html) - Low-level LAPACK functions
32
+ * [Numo::Linalg::Blas](http://ruby-numo.github.io/numo-linalg/yard/Numo/Linalg/Blas.html) - Low-level BLAS functions
33
+ * [Numo::Linalg::Lapack](http://ruby-numo.github.io/numo-linalg/yard/Numo/Linalg/Lapack.html) - Low-level LAPACK functions
34
34
 
35
35
  ## Installation
36
36
 
@@ -82,7 +82,7 @@ require "numo/linalg"
82
82
  * Makoto Kishimoto
83
83
  * Atsushi Tatsuma
84
84
 
85
- ## Acknowledgement
85
+ ## Acknowledgments
86
86
 
87
87
  * This work is partly supported by 2016 Ruby Association Grant.
88
88
 
@@ -89,14 +89,58 @@ module Numo; module Linalg
89
89
  func = blas_char(a, b) =~ /c|z/ ? :dotu : :dot
90
90
  Blas.call(func, a, b)
91
91
  else
92
- Blas.call(:gemv, b, a, trans:'t')
92
+ if b.contiguous?
93
+ trans = 't'
94
+ else
95
+ if b.fortran_contiguous?
96
+ trans = 'n'
97
+ b = b.transpose
98
+ else
99
+ trans = 't'
100
+ b = b.dup
101
+ end
102
+ end
103
+ Blas.call(:gemv, b, a, trans:trans)
93
104
  end
94
105
  else
95
106
  case b.ndim
96
107
  when 1
97
- Blas.call(:gemv, a, b)
108
+ if a.contiguous?
109
+ trans = 'n'
110
+ else
111
+ if a.fortran_contiguous?
112
+ trans = 't'
113
+ a = a.transpose
114
+ else
115
+ trans = 'n'
116
+ a = a.dup
117
+ end
118
+ end
119
+ Blas.call(:gemv, a, b, trans:trans)
98
120
  else
99
- Blas.call(:gemm, a, b)
121
+ if a.contiguous?
122
+ transa = 'n'
123
+ else
124
+ if a.fortran_contiguous?
125
+ transa = 't'
126
+ a = a.transpose
127
+ else
128
+ transa = 'n'
129
+ a = a.dup
130
+ end
131
+ end
132
+ if b.contiguous?
133
+ transb = 'n'
134
+ else
135
+ if b.fortran_contiguous?
136
+ transb='t'
137
+ b = b.transpose
138
+ else
139
+ transb='n'
140
+ b = b.dup
141
+ end
142
+ end
143
+ Blas.call(:gemm, a, b, transa:transa, transb:transb)
100
144
  end
101
145
  end
102
146
  end
@@ -296,6 +340,42 @@ module Numo; module Linalg
296
340
  end
297
341
  end
298
342
 
343
+ # Computes an orthonormal basis for the range of matrix A.
344
+ #
345
+ # @param a [Numo::NArray] m-by-n matrix A (>= 2-dimensional NArray).
346
+ # @param rcond [Float] (optional)
347
+ # rcond is used to determine the effective rank of A.
348
+ # Singular values `s[i] <= rcond * s.max` are treated as zero.
349
+ # If rcond < 0, machine precision is used instead.
350
+ # @return [Numo::NArray] The orthonormal basis for the range of matrix A.
351
+
352
+ def orth(a, rcond: -1)
353
+ raise NArray::ShapeError, '2-d array is required' if a.ndim < 2
354
+ s, u, = svd(a)
355
+ tol = s.max * (rcond.nil? || rcond < 0 ? a.class::EPSILON * a.shape.max : rcond)
356
+ k = (s > tol).count
357
+ u[true, 0...k]
358
+ end
359
+
360
+ # Computes an orthonormal basis for the null space of matrix A.
361
+ #
362
+ # @param a [Numo::NArray] m-by-n matrix A (>= 2-dimensional NArray).
363
+ # @param rcond [Float] (optional)
364
+ # rcond is used to determine the effective rank of A.
365
+ # Singular values `s[i] <= rcond * s.max` are treated as zero.
366
+ # If rcond < 0, machine precision is used instead.
367
+ # @return [Numo::NArray] The orthonormal basis for the null space of matrix A.
368
+
369
+ def null_space(a, rcond: -1)
370
+ raise NArray::ShapeError, '2-d array is required' if a.ndim < 2
371
+ s, _u, vh = svd(a)
372
+ tol = s.max * (rcond.nil? || rcond < 0 ? a.class::EPSILON * a.shape.max : rcond)
373
+ k = (s > tol).count
374
+ return a.class.new if k == vh.shape[0]
375
+ r = vh[k..-1, true].transpose.dup
376
+ blas_char(vh) =~ /c|z/ ? r.conj : r
377
+ end
378
+
299
379
  # Computes an LU factorization of a M-by-N matrix A
300
380
  # using partial pivoting with row interchanges.
301
381
  #
@@ -1,5 +1,5 @@
1
1
  module Numo
2
2
  module Linalg
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  end
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.extensions = ["ext/numo/linalg/blas/extconf.rb",
21
21
  "ext/numo/linalg/lapack/extconf.rb"]
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake", "~> 12.0"
25
- spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency "bundler"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
26
  spec.add_runtime_dependency "numo-narray", ">= 0.9.0.7"
27
27
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Numo::Linalg do
6
+ describe 'null_space' do
7
+ let(:r) { 2 }
8
+ let(:m) { 6 }
9
+ let(:n) { 4 }
10
+ let(:mat_a) { rand_rect_real_mat(m, r).dot(rand_rect_real_mat(r, n)) }
11
+ let(:mat_b) { rand_rect_complex_mat(m, r).dot(rand_rect_complex_mat(r, n)) }
12
+ let(:mat_c) { mat_a + 1.0e-6 * Numo::DFloat.new(m, n).rand }
13
+
14
+ it 'raises ShapeError given a vector' do
15
+ expect { described_class.lu(Numo::DFloat.new(3).rand) }.to raise_error(Numo::NArray::ShapeError)
16
+ end
17
+
18
+ it 'calculates an orthonormal basis for the null space of a real matrix' do
19
+ basis = described_class.null_space(mat_a)
20
+ expect(basis.shape[0]).to eq(n)
21
+ expect(basis.shape[1]).to eq(r)
22
+ expect((basis.transpose.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
23
+ end
24
+
25
+ it 'calculates an orthonormal basis for the null space of a complex matrix' do
26
+ basis = described_class.null_space(mat_b)
27
+ expect(basis.shape[0]).to eq(n)
28
+ expect(basis.shape[1]).to eq(r)
29
+ expect((basis.transpose.conj.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
30
+ end
31
+
32
+ it 'calculates an orthonormal basis according to the given rcond value' do
33
+ basis = described_class.null_space(mat_c, rcond: 1.0e-4)
34
+ expect(basis.shape[0]).to eq(n)
35
+ expect(basis.shape[1]).to eq(r)
36
+ expect((basis.transpose.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
37
+ basis = described_class.null_space(mat_c, rcond: 1.0e-8)
38
+ expect(basis.shape).to be_empty
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Numo::Linalg do
6
+ describe 'orth' do
7
+ let(:r) { 2 }
8
+ let(:m) { 6 }
9
+ let(:n) { 3 }
10
+ let(:mat_a) { rand_rect_real_mat(m, r).dot(rand_rect_real_mat(r, n)) }
11
+ let(:mat_b) { rand_rect_complex_mat(m, r).dot(rand_rect_complex_mat(r, n)) }
12
+ let(:mat_c) { mat_a + 1.0e-6 * Numo::DFloat.new(m, n).rand }
13
+
14
+ it 'raises ShapeError given a vector' do
15
+ expect { described_class.lu(Numo::DFloat.new(3).rand) }.to raise_error(Numo::NArray::ShapeError)
16
+ end
17
+
18
+ it 'calculates an orthonormal basis for the range of a real matrix' do
19
+ basis = described_class.orth(mat_a)
20
+ expect(basis.shape[0]).to eq(m)
21
+ expect(basis.shape[1]).to eq(r)
22
+ expect((basis.transpose.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
23
+ end
24
+
25
+ it 'calculates an orthonormal basis for the range of a complex matrix' do
26
+ basis = described_class.orth(mat_b)
27
+ expect(basis.shape[0]).to eq(m)
28
+ expect(basis.shape[1]).to eq(r)
29
+ expect((basis.transpose.conj.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
30
+ end
31
+
32
+ it 'calculates an orthonormal basis according to the given rcond value' do
33
+ basis = described_class.orth(mat_c, rcond: 1.0e-4)
34
+ expect(basis.shape[0]).to eq(m)
35
+ expect(basis.shape[1]).to eq(r)
36
+ expect((basis.transpose.dot(basis) - Numo::DFloat.eye(r)).abs.max).to be < ERR_TOL
37
+ basis = described_class.orth(mat_c, rcond: 1.0e-8)
38
+ expect(basis.shape[0]).to eq(m)
39
+ expect(basis.shape[1]).to eq(n)
40
+ expect((basis.transpose.dot(basis) - Numo::DFloat.eye(n)).abs.max).to be < ERR_TOL
41
+ end
42
+ end
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-linalg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro TANAKA
@@ -9,50 +9,50 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-08-23 00:00:00.000000000 Z
12
+ date: 2019-01-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '1.3'
20
+ version: '0'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '1.3'
27
+ version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '12.0'
34
+ version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '12.0'
41
+ version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '3.0'
48
+ version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: '3.0'
55
+ version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: numo-narray
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -185,6 +185,8 @@ files:
185
185
  - spec/linalg/function/matrix_power_spec.rb
186
186
  - spec/linalg/function/matrix_rank_spec.rb
187
187
  - spec/linalg/function/norm_spec.rb
188
+ - spec/linalg/function/null_space_spec.rb
189
+ - spec/linalg/function/orth_spec.rb
188
190
  - spec/linalg/function/pinv_spec.rb
189
191
  - spec/linalg/function/qr_spec.rb
190
192
  - spec/linalg/function/slogdet_spec.rb
@@ -211,8 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
213
  - !ruby/object:Gem::Version
212
214
  version: '0'
213
215
  requirements: []
214
- rubyforge_project:
215
- rubygems_version: 2.7.3
216
+ rubygems_version: 3.0.1
216
217
  signing_key:
217
218
  specification_version: 4
218
219
  summary: Ruby/Numo Linear Algebra library with BLAS/LAPACK
@@ -240,6 +241,8 @@ test_files:
240
241
  - spec/linalg/function/matrix_power_spec.rb
241
242
  - spec/linalg/function/matrix_rank_spec.rb
242
243
  - spec/linalg/function/norm_spec.rb
244
+ - spec/linalg/function/null_space_spec.rb
245
+ - spec/linalg/function/orth_spec.rb
243
246
  - spec/linalg/function/pinv_spec.rb
244
247
  - spec/linalg/function/qr_spec.rb
245
248
  - spec/linalg/function/slogdet_spec.rb