numo-linalg 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7c0b667ffa1e3720ba31c4b03b984cbb2fb357c82df6d6ad4ce063be4f38fe4
4
- data.tar.gz: 52ecb22fc5d7a483aa0fbe82b04bd38747457661f4f6846693d2b2bbb7c9c19b
3
+ metadata.gz: f1a7f32e07db68cc87340dc3245d9205026bd33c4ebc18b1cbef28f605f1a1d6
4
+ data.tar.gz: 1cb21ea35b2dacb1fb02d44317fb3684d9827635e4191aa7ecffd069edd214b1
5
5
  SHA512:
6
- metadata.gz: 38a2dc9a2bb4af3c273a11c22213a4a6db25d8d93be85e51cf3b418717e92336a14beff65b1202b7215254701593ce15970cf063be502a17640d8bc9d70b12c0
7
- data.tar.gz: 3f7b0c47d0ced6ba5a1a58b1298bb342712a37ed6c24103bd5a41d399aa94c4cac066e6c8791cb3f283fad398e4dafe796723d7aadceca2b2a99f439882ce46c
6
+ metadata.gz: c6125b1b665a2fbd87ecda093e1afea1ef85ca057e62921d95fa424dbe7e30d41d26c5c4caca57719d4c284ec33e179508b13d12c4de5e535c65c186eedc42eb
7
+ data.tar.gz: 1d7b3ac0fa98d70bb772674b4491d4d0285ef3303668a59299075c7a1595ff1796df745b73c30f34e295260d0b79df0aaf395b2742a912a292c1a618d92f116b
@@ -19,13 +19,15 @@ module Numo
19
19
  # @return [String] name of loaded backend library (mkl/openblas/lapack)
20
20
  def load_library
21
21
  mkl_dirs = ['/opt/intel/lib', '/opt/intel/lib64', '/opt/intel/mkl/lib', '/opt/intel/mkl/lib64']
22
- openblas_dirs = ['/opt/openblas/lib', '/opt/openblas/lib64', '/usr/local/opt/openblas/lib']
22
+ openblas_dirs = ['/opt/OpenBLAS/lib', '/opt/OpenBLAS/lib64', '/opt/openblas/lib', '/opt/openblas/lib64',
23
+ '/usr/local/opt/openblas/lib']
23
24
  atlas_dirs = ['/opt/atlas/lib', '/opt/atlas/lib64',
24
25
  '/usr/lib/atlas', '/usr/lib64/atlas', '/usr/local/opt/atlas/lib']
25
26
  lapacke_dirs = ['/opt/lapack/lib', '/opt/lapack/lib64', '/opt/local/lib/lapack',
26
27
  '/usr/local/opt/lapack/lib']
27
28
  opt_dirs = ['/opt/local/lib', '/opt/local/lib64', '/opt/lib', '/opt/lib64']
28
- base_dirs = ['/usr/local/lib', '/usr/local/lib64', '/usr/lib', '/usr/lib64']
29
+ base_dirs = ['/usr/local/lib', '/usr/local/lib64', '/usr/lib', '/usr/lib64',
30
+ "/usr/lib/#{RbConfig::CONFIG['host_cpu']}-#{RbConfig::CONFIG['host_os']}"]
29
31
  base_dirs.unshift(*ENV['LD_LIBRARY_PATH'].split(':')) unless ENV['LD_LIBRARY_PATH'].nil?
30
32
 
31
33
  mkl_libs = find_mkl_libs([*base_dirs, *opt_dirs, *mkl_dirs])
@@ -12,12 +12,19 @@ module Numo; module Linalg
12
12
  # defined from data-types of arguments.
13
13
  # @param [Symbol] func function name without BLAS char.
14
14
  # @param args arguments passed to Blas function.
15
+ # @param kwargs keyword arguments passed to Blas function.
15
16
  # @example
16
17
  # c = Numo::Linalg::Blas.call(:gemm, a, b)
17
- def self.call(func,*args)
18
+ def self.call(func, *args, **kwargs)
18
19
  fn = (Linalg.blas_char(*args) + func.to_s).to_sym
19
20
  fn = FIXNAME[fn] || fn
20
- send(fn,*args)
21
+ if kwargs.empty?
22
+ # This conditional branch is necessary to prevent ArgumentError
23
+ # that occurs in Ruby 2.6 or earlier.
24
+ send(fn, *args)
25
+ else
26
+ send(fn, *args, **kwargs)
27
+ end
21
28
  end
22
29
 
23
30
  end
@@ -34,12 +41,19 @@ module Numo; module Linalg
34
41
  # defined from data-types of arguments.
35
42
  # @param [Symbol,String] func function name without BLAS char.
36
43
  # @param args arguments passed to Lapack function.
44
+ # @param kwargs keyword arguments passed to Lapack function.
37
45
  # @example
38
46
  # s = Numo::Linalg::Lapack.call(:gesv, a)
39
- def self.call(func,*args)
47
+ def self.call(func, *args, **kwargs)
40
48
  fn = (Linalg.blas_char(*args) + func.to_s).to_sym
41
49
  fn = FIXNAME[fn] || fn
42
- send(fn,*args)
50
+ if kwargs.empty?
51
+ # This conditional branch is necessary to prevent ArgumentError
52
+ # that occurs in Ruby 2.6 or earlier.
53
+ send(fn, *args)
54
+ else
55
+ send(fn, *args, **kwargs)
56
+ end
43
57
  end
44
58
 
45
59
  end
@@ -1084,14 +1098,11 @@ module Numo; module Linalg
1084
1098
  when n
1085
1099
  resids = (x[n..-1,true].abs**2).sum(axis:0)
1086
1100
  when NArray
1087
- if true
1088
- resids = (x[false,n..-1,true].abs**2).sum(axis:-2)
1089
- else
1090
- resids = x[false,0,true].new_zeros
1091
- mask = rank.eq(n)
1092
- # NArray does not suppurt this yet.
1093
- resids[mask,true] = (x[mask,n..-1,true].abs**2).sum(axis:-2)
1094
- end
1101
+ resids = (x[false,n..-1,true].abs**2).sum(axis:-2)
1102
+ ## NArray does not suppurt this yet.
1103
+ # resids = x[false,0,true].new_zeros
1104
+ # mask = rank.eq(n)
1105
+ # resids[mask,true] = (x[mask,n..-1,true].abs**2).sum(axis:-2)
1095
1106
  end
1096
1107
  end
1097
1108
  x = x[false,0...n,true]
@@ -1163,6 +1174,49 @@ module Numo; module Linalg
1163
1174
  end
1164
1175
  end
1165
1176
 
1177
+ # Compute the matrix exponential using Pade approximation method.
1178
+ #
1179
+ # @param a [Numo::NArray] square matrix (>= 2-dimensinal NArray)
1180
+ # @param ord [Integer] order of approximation
1181
+ # @return [Numo::NArray]
1182
+ # @example
1183
+ # a = Numo::Linalg.expm(Numo::DFloat.zeros([2,2]))
1184
+ # => Numo::DFloat#shape=[2,2]
1185
+ # [[1, 0],
1186
+ # [0, 1]]
1187
+ # b = Numo::Linalg.expm(Numo::DFloat[[1, 2], [-1, 3]] * Complex::I)
1188
+ # => Numo::DComplex#shape=[2,2]
1189
+ # [[0.426459+1.89218i, -2.13721-0.978113i],
1190
+ # [1.06861+0.489056i, -1.71076+0.914063i]]
1191
+
1192
+ def expm(a, ord=8)
1193
+ raise NArray::ShapeError, 'matrix a is not square matrix' if a.shape[0] != a.shape[1]
1194
+
1195
+ inf_norm = norm(a, 'inf')
1196
+ n_squarings = inf_norm.zero? ? 0 : [0, Math.log2(inf_norm).ceil.to_i].max
1197
+ a = a / (2**n_squarings)
1198
+
1199
+ sz_mat = a.shape[0]
1200
+ c = 1
1201
+ s = -1
1202
+ x = Numo::DFloat.eye(sz_mat)
1203
+ n = Numo::DFloat.eye(sz_mat)
1204
+ d = Numo::DFloat.eye(sz_mat)
1205
+
1206
+ (1..ord).each do |k|
1207
+ c *= (ord - k + 1).fdiv((2 * ord - k + 1) * k)
1208
+ x = a.dot(x)
1209
+ cx = c * x
1210
+ n += cx
1211
+ d += s * cx
1212
+ s *= -1
1213
+ end
1214
+
1215
+ res = solve(d, n)
1216
+ n_squarings.times { res = res.dot(res) }
1217
+ res
1218
+ end
1219
+
1166
1220
  # @!visibility private
1167
1221
  def _make_complex_eigvecs(w, vin) # :nodoc:
1168
1222
  v = w.class.cast(vin)
@@ -1,5 +1,5 @@
1
1
  module Numo
2
2
  module Linalg
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
5
5
  end
@@ -23,5 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency "rspec"
26
- spec.add_runtime_dependency "numo-narray", ">= 0.9.0.7"
26
+ spec.add_runtime_dependency "numo-narray", ">= 0.9.1.4"
27
27
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Numo::Linalg do
6
+ describe 'det' do
7
+ it 'raises ShapeError given a rectangular matrix as matrix A' do
8
+ expect { described_class.expm(Numo::DFloat.new(2, 3).rand) }.to raise_error(Numo::NArray::ShapeError)
9
+ end
10
+
11
+ it 'calculates matrix exponential of matrix without full eigenvectors' do
12
+ e = Math.exp(1)
13
+ err = (described_class.expm(Numo::DFloat[[1, 2], [0, 1]]) - Numo::DFloat[[e, 2 * e], [0, e]]).abs.sum(1).max
14
+ expect(err).to be < 1e-6
15
+ end
16
+
17
+ it 'calculates matrix exponential for matrix with large norm' do
18
+ tmp = Numo::DFloat[[-0.0995741, 0.0746806], [-0.199148, 0.149361]]
19
+ err = (described_class.expm(Numo::DFloat[[-147, 72], [-192, 93]]) - tmp).abs.sum(1).max
20
+ expect(err).to be < 1e-6
21
+ end
22
+
23
+ it 'calculates matrix exponential for diagonal matrix' do
24
+ err = (described_class.expm(Numo::DFloat[2, 3].diag) - Numo::NMath.exp(Numo::DFloat[2, 3]).diag).abs.sum(1).max
25
+ expect(err).to be < 1e-6
26
+ end
27
+
28
+ it 'returns identity matrix when given zero matrix' do
29
+ expect(described_class.expm(Numo::DFloat.zeros([2, 2]))).to eq(Numo::DFloat.eye(2))
30
+ end
31
+
32
+ it 'returns complex matrix when given complex matrix' do
33
+ expect(described_class.expm(rand_rect_complex_mat(2, 2))).to be_a(Numo::DComplex)
34
+ end
35
+ end
36
+ 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.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro TANAKA
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-01-10 00:00:00.000000000 Z
12
+ date: 2019-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 0.9.0.7
62
+ version: 0.9.1.4
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 0.9.0.7
69
+ version: 0.9.1.4
70
70
  description: Ruby/Numo Linear Algebra library with interface to BLAS/LAPACK.
71
71
  email:
72
72
  - masa16.tanaka@gmail.com
@@ -174,6 +174,7 @@ files:
174
174
  - spec/linalg/function/eigh_spec.rb
175
175
  - spec/linalg/function/eigvals_spec.rb
176
176
  - spec/linalg/function/eigvalsh_spec.rb
177
+ - spec/linalg/function/expm_spec.rb
177
178
  - spec/linalg/function/inv_spec.rb
178
179
  - spec/linalg/function/ldl_spec.rb
179
180
  - spec/linalg/function/lstsq_spec.rb
@@ -213,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
214
  - !ruby/object:Gem::Version
214
215
  version: '0'
215
216
  requirements: []
216
- rubygems_version: 3.0.1
217
+ rubygems_version: 3.1.2
217
218
  signing_key:
218
219
  specification_version: 4
219
220
  summary: Ruby/Numo Linear Algebra library with BLAS/LAPACK
@@ -230,6 +231,7 @@ test_files:
230
231
  - spec/linalg/function/eigh_spec.rb
231
232
  - spec/linalg/function/eigvals_spec.rb
232
233
  - spec/linalg/function/eigvalsh_spec.rb
234
+ - spec/linalg/function/expm_spec.rb
233
235
  - spec/linalg/function/inv_spec.rb
234
236
  - spec/linalg/function/ldl_spec.rb
235
237
  - spec/linalg/function/lstsq_spec.rb