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 +4 -4
- data/lib/numo/linalg/autoloader.rb +4 -2
- data/lib/numo/linalg/function.rb +66 -12
- data/lib/numo/linalg/version.rb +1 -1
- data/numo-linalg.gemspec +1 -1
- data/spec/linalg/function/expm_spec.rb +36 -0
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1a7f32e07db68cc87340dc3245d9205026bd33c4ebc18b1cbef28f605f1a1d6
|
|
4
|
+
data.tar.gz: 1cb21ea35b2dacb1fb02d44317fb3684d9827635e4191aa7ecffd069edd214b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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/
|
|
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])
|
data/lib/numo/linalg/function.rb
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
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)
|
data/lib/numo/linalg/version.rb
CHANGED
data/numo-linalg.gemspec
CHANGED
|
@@ -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.
|
|
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
|
+
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-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|