numo-tiny_linalg 0.0.4 → 0.1.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 +4 -4
- data/CHANGELOG.md +4 -1
- data/README.md +3 -3
- data/ext/numo/tiny_linalg/blas/gemm.hpp +3 -49
- data/ext/numo/tiny_linalg/blas/gemv.hpp +2 -48
- data/ext/numo/tiny_linalg/lapack/geqrf.hpp +5 -25
- data/ext/numo/tiny_linalg/lapack/gesdd.hpp +11 -11
- data/ext/numo/tiny_linalg/lapack/gesv.hpp +10 -30
- data/ext/numo/tiny_linalg/lapack/gesvd.hpp +12 -12
- data/ext/numo/tiny_linalg/lapack/getrf.hpp +9 -29
- data/ext/numo/tiny_linalg/lapack/getri.hpp +9 -29
- data/ext/numo/tiny_linalg/lapack/hegv.hpp +9 -55
- data/ext/numo/tiny_linalg/lapack/hegvd.hpp +9 -55
- data/ext/numo/tiny_linalg/lapack/hegvx.hpp +16 -72
- data/ext/numo/tiny_linalg/lapack/orgqr.hpp +5 -25
- data/ext/numo/tiny_linalg/lapack/sygv.hpp +9 -55
- data/ext/numo/tiny_linalg/lapack/sygvd.hpp +9 -55
- data/ext/numo/tiny_linalg/lapack/sygvx.hpp +16 -72
- data/ext/numo/tiny_linalg/lapack/ungqr.hpp +5 -25
- data/ext/numo/tiny_linalg/tiny_linalg.cpp +56 -21
- data/ext/numo/tiny_linalg/tiny_linalg.hpp +30 -6
- data/ext/numo/tiny_linalg/util.hpp +100 -0
- data/lib/numo/tiny_linalg/version.rb +1 -1
- data/lib/numo/tiny_linalg.rb +159 -35
- metadata +2 -1
data/lib/numo/tiny_linalg.rb
CHANGED
@@ -13,6 +13,32 @@ module Numo
|
|
13
13
|
# Computes the eigenvalues and eigenvectors of a symmetric / Hermitian matrix
|
14
14
|
# by solving an ordinary or generalized eigenvalue problem.
|
15
15
|
#
|
16
|
+
# @example
|
17
|
+
# require 'numo/tiny_linalg'
|
18
|
+
#
|
19
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
20
|
+
#
|
21
|
+
# x = Numo::DFloat.new(5, 3).rand - 0.5
|
22
|
+
# c = x.dot(x.transpose)
|
23
|
+
# vals, vecs = Numo::Linalg.eigh(c, vals_range: [2, 4])
|
24
|
+
#
|
25
|
+
# pp vals
|
26
|
+
# # =>
|
27
|
+
# # Numo::DFloat#shape=[3]
|
28
|
+
# # [0.118795, 0.434252, 0.903245]
|
29
|
+
#
|
30
|
+
# pp vecs
|
31
|
+
# # =>
|
32
|
+
# # Numo::DFloat#shape=[5,3]
|
33
|
+
# # [[0.154178, 0.60661, -0.382961],
|
34
|
+
# # [-0.349761, -0.141726, -0.513178],
|
35
|
+
# # [0.739633, -0.468202, 0.105933],
|
36
|
+
# # [0.0519655, -0.471436, -0.701507],
|
37
|
+
# # [-0.551488, -0.412883, 0.294371]]
|
38
|
+
#
|
39
|
+
# pp (x - vecs.dot(vals.diag).dot(vecs.transpose)).abs.max
|
40
|
+
# # => 3.3306690738754696e-16
|
41
|
+
#
|
16
42
|
# @param a [Numo::NArray] n-by-n symmetric / Hermitian matrix.
|
17
43
|
# @param b [Numo::NArray] n-by-n symmetric / Hermitian matrix. If nil, identity matrix is assumed.
|
18
44
|
# @param vals_only [Boolean] The flag indicating whether to return only eigenvalues.
|
@@ -56,6 +82,15 @@ module Numo
|
|
56
82
|
|
57
83
|
# Computes the determinant of matrix.
|
58
84
|
#
|
85
|
+
# @example
|
86
|
+
# require 'numo/tiny_linalg'
|
87
|
+
#
|
88
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
89
|
+
#
|
90
|
+
# a = Numo::DFloat[[0, 2, 3], [4, 5, 6], [7, 8, 9]]
|
91
|
+
# pp (3.0 - Numo::Linalg.det(a)).abs
|
92
|
+
# # => 1.3322676295501878e-15
|
93
|
+
#
|
59
94
|
# @param a [Numo::NArray] n-by-n square matrix.
|
60
95
|
# @return [Float/Complex] The determinant of `a`.
|
61
96
|
def det(a)
|
@@ -82,6 +117,21 @@ module Numo
|
|
82
117
|
|
83
118
|
# Computes the inverse matrix of a square matrix.
|
84
119
|
#
|
120
|
+
# @example
|
121
|
+
# require 'numo/tiny_linalg'
|
122
|
+
#
|
123
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
124
|
+
#
|
125
|
+
# a = Numo::DFloat.new(5, 5).rand
|
126
|
+
#
|
127
|
+
# inv_a = Numo::Linalg.inv(a)
|
128
|
+
#
|
129
|
+
# pp (inv_a.dot(a) - Numo::DFloat.eye(5)).abs.max
|
130
|
+
# # => 7.019165976816745e-16
|
131
|
+
#
|
132
|
+
# pp inv_a.dot(a).sum
|
133
|
+
# # => 5.0
|
134
|
+
#
|
85
135
|
# @param a [Numo::NArray] n-by-n square matrix.
|
86
136
|
# @param driver [String] This argument is for compatibility with Numo::Linalg.solver, and is not used.
|
87
137
|
# @param uplo [String] This argument is for compatibility with Numo::Linalg.solver, and is not used.
|
@@ -108,6 +158,21 @@ module Numo
|
|
108
158
|
|
109
159
|
# Compute the (Moore-Penrose) pseudo-inverse of a matrix using singular value decomposition.
|
110
160
|
#
|
161
|
+
# @example
|
162
|
+
# require 'numo/tiny_linalg'
|
163
|
+
#
|
164
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
165
|
+
#
|
166
|
+
# a = Numo::DFloat.new(5, 3).rand
|
167
|
+
#
|
168
|
+
# inv_a = Numo::Linalg.pinv(a)
|
169
|
+
#
|
170
|
+
# pp (inv_a.dot(a) - Numo::DFloat.eye(3)).abs.max
|
171
|
+
# # => 1.1102230246251565e-15
|
172
|
+
#
|
173
|
+
# pp inv_a.dot(a).sum
|
174
|
+
# # => 3.0
|
175
|
+
#
|
111
176
|
# @param a [Numo::NArray] The m-by-n matrix to be pseudo-inverted.
|
112
177
|
# @param driver [String] LAPACK driver to be used ('svd' or 'sdd').
|
113
178
|
# @param rcond [Float] The threshold value for small singular values of `a`, default value is `a.shape.max * EPS`.
|
@@ -123,6 +188,34 @@ module Numo
|
|
123
188
|
|
124
189
|
# Compute QR decomposition of a matrix.
|
125
190
|
#
|
191
|
+
# @example
|
192
|
+
# require 'numo/tiny_linalg'
|
193
|
+
#
|
194
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
195
|
+
#
|
196
|
+
# x = Numo::DFloat.new(5, 3).rand
|
197
|
+
#
|
198
|
+
# q, r = Numo::Linalg.qr(x, mode: 'economic')
|
199
|
+
#
|
200
|
+
# pp q
|
201
|
+
# # =>
|
202
|
+
# # Numo::DFloat#shape=[5,3]
|
203
|
+
# # [[-0.0574417, 0.635216, 0.707116],
|
204
|
+
# # [-0.187002, -0.073192, 0.422088],
|
205
|
+
# # [-0.502239, 0.634088, -0.537489],
|
206
|
+
# # [-0.0473292, 0.134867, -0.0223491],
|
207
|
+
# # [-0.840979, -0.413385, 0.180096]]
|
208
|
+
#
|
209
|
+
# pp r
|
210
|
+
# # =>
|
211
|
+
# # Numo::DFloat#shape=[3,3]
|
212
|
+
# # [[-1.07508, -0.821334, -0.484586],
|
213
|
+
# # [0, 0.513035, 0.451868],
|
214
|
+
# # [0, 0, 0.678737]]
|
215
|
+
#
|
216
|
+
# pp (q.dot(r) - x).abs.max
|
217
|
+
# # => 3.885780586188048e-16
|
218
|
+
#
|
126
219
|
# @param a [Numo::NArray] The m-by-n matrix to be decomposed.
|
127
220
|
# @param mode [String] The mode of decomposition.
|
128
221
|
# - "reduce" -- returns both Q [m, m] and R [m, n],
|
@@ -166,26 +259,74 @@ module Numo
|
|
166
259
|
|
167
260
|
# Solves linear equation `A * x = b` or `A * X = B` for `x` from square matrix `a`.
|
168
261
|
#
|
169
|
-
# @
|
262
|
+
# @example
|
263
|
+
# require 'numo/tiny_linalg'
|
264
|
+
#
|
265
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
266
|
+
#
|
267
|
+
# a = Numo::DFloat.new(3, 3).rand
|
268
|
+
# b = Numo::DFloat.eye(3)
|
269
|
+
#
|
270
|
+
# x = Numo::Linalg.solve(a, b)
|
271
|
+
#
|
272
|
+
# pp x
|
273
|
+
# # =>
|
274
|
+
# # Numo::DFloat#shape=[3,3]
|
275
|
+
# # [[-2.12332, 4.74868, 0.326773],
|
276
|
+
# # [1.38043, -3.79074, 1.25355],
|
277
|
+
# # [0.775187, 1.41032, -0.613774]]
|
278
|
+
#
|
279
|
+
# pp (b - a.dot(x)).abs.max
|
280
|
+
# # => 2.1081041547796492e-16
|
281
|
+
#
|
282
|
+
# @param a [Numo::NArray] The n-by-n square matrix.
|
170
283
|
# @param b [Numo::NArray] The n right-hand side vector, or n-by-nrhs right-hand side matrix (>= 1-dimensinal NArray).
|
171
284
|
# @param driver [String] This argument is for compatibility with Numo::Linalg.solver, and is not used.
|
172
285
|
# @param uplo [String] This argument is for compatibility with Numo::Linalg.solver, and is not used.
|
173
286
|
# @return [Numo::NArray] The solusion vector / matrix `x`.
|
174
287
|
def solve(a, b, driver: 'gen', uplo: 'U') # rubocop:disable Lint/UnusedMethodArgument
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
Lapack.cgesv(a.dup, b.dup)[1]
|
184
|
-
end
|
288
|
+
raise ArgumentError, 'input array a must be 2-dimensional' if a.ndim != 2
|
289
|
+
raise ArgumentError, 'input array a must be square' if a.shape[0] != a.shape[1]
|
290
|
+
|
291
|
+
bchr = blas_char(a, b)
|
292
|
+
raise ArgumentError, "invalid array type: #{a.class}, #{b.class}" if bchr == 'n'
|
293
|
+
|
294
|
+
gesv = "#{bchr}gesv".to_sym
|
295
|
+
Numo::TinyLinalg::Lapack.send(gesv, a.dup, b.dup)[1]
|
185
296
|
end
|
186
297
|
|
187
298
|
# Calculates the Singular Value Decomposition (SVD) of a matrix: `A = U * S * V^T`
|
188
299
|
#
|
300
|
+
# @example
|
301
|
+
# require 'numo/tiny_linalg'
|
302
|
+
#
|
303
|
+
# Numo::Linalg = Numo::TinyLinalg unless defined?(Numo::Linalg)
|
304
|
+
#
|
305
|
+
# x = Numo::DFloat.new(5, 2).rand.dot(Numo::DFloat.new(2, 3).rand)
|
306
|
+
# pp x
|
307
|
+
# # =>
|
308
|
+
# # Numo::DFloat#shape=[5,3]
|
309
|
+
# # [[0.104945, 0.0284236, 0.117406],
|
310
|
+
# # [0.862634, 0.210945, 0.922135],
|
311
|
+
# # [0.324507, 0.0752655, 0.339158],
|
312
|
+
# # [0.67085, 0.102594, 0.600882],
|
313
|
+
# # [0.404631, 0.116868, 0.46644]]
|
314
|
+
#
|
315
|
+
# s, u, vt = Numo::Linalg.svd(x, job: 'S')
|
316
|
+
#
|
317
|
+
# z = u.dot(s.diag).dot(vt)
|
318
|
+
# pp z
|
319
|
+
# # =>
|
320
|
+
# # Numo::DFloat#shape=[5,3]
|
321
|
+
# # [[0.104945, 0.0284236, 0.117406],
|
322
|
+
# # [0.862634, 0.210945, 0.922135],
|
323
|
+
# # [0.324507, 0.0752655, 0.339158],
|
324
|
+
# # [0.67085, 0.102594, 0.600882],
|
325
|
+
# # [0.404631, 0.116868, 0.46644]]
|
326
|
+
#
|
327
|
+
# pp (x - z).abs.max
|
328
|
+
# # => 4.440892098500626e-16
|
329
|
+
#
|
189
330
|
# @param a [Numo::NArray] Matrix to be decomposed.
|
190
331
|
# @param driver [String] LAPACK driver to be used ('svd' or 'sdd').
|
191
332
|
# @param job [String] Job option ('A', 'S', or 'N').
|
@@ -193,33 +334,16 @@ module Numo
|
|
193
334
|
def svd(a, driver: 'svd', job: 'A')
|
194
335
|
raise ArgumentError, "invalid job: #{job}" unless /^[ASN]/i.match?(job.to_s)
|
195
336
|
|
337
|
+
bchr = blas_char(a)
|
338
|
+
raise ArgumentError, "invalid array type: #{a.class}" if bchr == 'n'
|
339
|
+
|
196
340
|
case driver.to_s
|
197
341
|
when 'sdd'
|
198
|
-
|
199
|
-
|
200
|
-
Numo::TinyLinalg::Lapack.dgesdd(a.dup, jobz: job)
|
201
|
-
when Numo::SFloat
|
202
|
-
Numo::TinyLinalg::Lapack.sgesdd(a.dup, jobz: job)
|
203
|
-
when Numo::DComplex
|
204
|
-
Numo::TinyLinalg::Lapack.zgesdd(a.dup, jobz: job)
|
205
|
-
when Numo::SComplex
|
206
|
-
Numo::TinyLinalg::Lapack.cgesdd(a.dup, jobz: job)
|
207
|
-
else
|
208
|
-
raise ArgumentError, "invalid array type: #{a.class}"
|
209
|
-
end
|
342
|
+
gesdd = "#{bchr}gesdd".to_sym
|
343
|
+
s, u, vt, info = Numo::TinyLinalg::Lapack.send(gesdd, a.dup, jobz: job)
|
210
344
|
when 'svd'
|
211
|
-
|
212
|
-
|
213
|
-
Numo::TinyLinalg::Lapack.dgesvd(a.dup, jobu: job, jobvt: job)
|
214
|
-
when Numo::SFloat
|
215
|
-
Numo::TinyLinalg::Lapack.sgesvd(a.dup, jobu: job, jobvt: job)
|
216
|
-
when Numo::DComplex
|
217
|
-
Numo::TinyLinalg::Lapack.zgesvd(a.dup, jobu: job, jobvt: job)
|
218
|
-
when Numo::SComplex
|
219
|
-
Numo::TinyLinalg::Lapack.cgesvd(a.dup, jobu: job, jobvt: job)
|
220
|
-
else
|
221
|
-
raise ArgumentError, "invalid array type: #{a.class}"
|
222
|
-
end
|
345
|
+
gesvd = "#{bchr}gesvd".to_sym
|
346
|
+
s, u, vt, info = Numo::TinyLinalg::Lapack.send(gesvd, a.dup, jobu: job, jobvt: job)
|
223
347
|
else
|
224
348
|
raise ArgumentError, "invalid driver: #{driver}"
|
225
349
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: numo-tiny_linalg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshoku
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- ext/numo/tiny_linalg/lapack/ungqr.hpp
|
63
63
|
- ext/numo/tiny_linalg/tiny_linalg.cpp
|
64
64
|
- ext/numo/tiny_linalg/tiny_linalg.hpp
|
65
|
+
- ext/numo/tiny_linalg/util.hpp
|
65
66
|
- lib/numo/tiny_linalg.rb
|
66
67
|
- lib/numo/tiny_linalg/version.rb
|
67
68
|
- vendor/tmp/.gitkeep
|