nmatrix-atlas 0.2.1 → 0.2.3
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/ext/nmatrix/data/data.h +7 -8
- data/ext/nmatrix/data/ruby_object.h +1 -4
- data/ext/nmatrix/math/asum.h +10 -31
- data/ext/nmatrix/math/cblas_templates_core.h +10 -10
- data/ext/nmatrix/math/getrf.h +2 -2
- data/ext/nmatrix/math/imax.h +12 -9
- data/ext/nmatrix/math/laswp.h +3 -3
- data/ext/nmatrix/math/long_dtype.h +16 -3
- data/ext/nmatrix/math/magnitude.h +54 -0
- data/ext/nmatrix/math/nrm2.h +19 -14
- data/ext/nmatrix/math/trsm.h +40 -36
- data/ext/nmatrix/math/util.h +14 -0
- data/ext/nmatrix/nmatrix.h +39 -1
- data/ext/nmatrix/storage/common.h +9 -3
- data/ext/nmatrix/storage/yale/class.h +1 -1
- data/ext/nmatrix_atlas/extconf.rb +3 -131
- data/ext/nmatrix_atlas/math_atlas.cpp +15 -15
- data/lib/nmatrix/atlas.rb +59 -28
- data/spec/00_nmatrix_spec.rb +50 -1
- data/spec/02_slice_spec.rb +21 -21
- data/spec/blas_spec.rb +25 -3
- data/spec/math_spec.rb +233 -5
- data/spec/shortcuts_spec.rb +145 -5
- data/spec/spec_helper.rb +24 -1
- metadata +18 -8
@@ -368,11 +368,11 @@ static VALUE nm_atlas_cblas_nrm2(VALUE self, VALUE n, VALUE x, VALUE incx) {
|
|
368
368
|
|
369
369
|
static void (*ttable[nm::NUM_DTYPES])(const int N, const void* X, const int incX, void* sum) = {
|
370
370
|
NULL, NULL, NULL, NULL, NULL, // no help for integers
|
371
|
-
nm::math::atlas::cblas_nrm2<float32_t
|
372
|
-
nm::math::atlas::cblas_nrm2<float64_t
|
373
|
-
nm::math::atlas::cblas_nrm2<
|
374
|
-
nm::math::atlas::cblas_nrm2<
|
375
|
-
nm::math::atlas::cblas_nrm2<nm::RubyObject
|
371
|
+
nm::math::atlas::cblas_nrm2<float32_t>,
|
372
|
+
nm::math::atlas::cblas_nrm2<float64_t>,
|
373
|
+
nm::math::atlas::cblas_nrm2<nm::Complex64>,
|
374
|
+
nm::math::atlas::cblas_nrm2<nm::Complex128>,
|
375
|
+
nm::math::atlas::cblas_nrm2<nm::RubyObject>
|
376
376
|
};
|
377
377
|
|
378
378
|
nm::dtype_t dtype = NM_DTYPE(x);
|
@@ -417,16 +417,16 @@ static VALUE nm_atlas_cblas_nrm2(VALUE self, VALUE n, VALUE x, VALUE incx) {
|
|
417
417
|
static VALUE nm_atlas_cblas_asum(VALUE self, VALUE n, VALUE x, VALUE incx) {
|
418
418
|
|
419
419
|
static void (*ttable[nm::NUM_DTYPES])(const int N, const void* X, const int incX, void* sum) = {
|
420
|
-
nm::math::atlas::cblas_asum<uint8_t
|
421
|
-
nm::math::atlas::cblas_asum<int8_t
|
422
|
-
nm::math::atlas::cblas_asum<int16_t
|
423
|
-
nm::math::atlas::cblas_asum<int32_t
|
424
|
-
nm::math::atlas::cblas_asum<int64_t
|
425
|
-
nm::math::atlas::cblas_asum<float32_t
|
426
|
-
nm::math::atlas::cblas_asum<float64_t
|
427
|
-
nm::math::atlas::cblas_asum<
|
428
|
-
nm::math::atlas::cblas_asum<
|
429
|
-
nm::math::atlas::cblas_asum<nm::RubyObject
|
420
|
+
nm::math::atlas::cblas_asum<uint8_t>,
|
421
|
+
nm::math::atlas::cblas_asum<int8_t>,
|
422
|
+
nm::math::atlas::cblas_asum<int16_t>,
|
423
|
+
nm::math::atlas::cblas_asum<int32_t>,
|
424
|
+
nm::math::atlas::cblas_asum<int64_t>,
|
425
|
+
nm::math::atlas::cblas_asum<float32_t>,
|
426
|
+
nm::math::atlas::cblas_asum<float64_t>,
|
427
|
+
nm::math::atlas::cblas_asum<nm::Complex64>,
|
428
|
+
nm::math::atlas::cblas_asum<nm::Complex128>,
|
429
|
+
nm::math::atlas::cblas_asum<nm::RubyObject>
|
430
430
|
};
|
431
431
|
|
432
432
|
nm::dtype_t dtype = NM_DTYPE(x);
|
data/lib/nmatrix/atlas.rb
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
#
|
10
10
|
# == Copyright Information
|
11
11
|
#
|
12
|
-
# SciRuby is Copyright (c) 2010 -
|
13
|
-
# NMatrix is Copyright (c) 2012 -
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2016, Ruby Science Foundation
|
13
|
+
# NMatrix is Copyright (c) 2012 - 2016, John Woods and the Ruby Science Foundation
|
14
14
|
#
|
15
15
|
# Please see LICENSE.txt for additional copyright notices.
|
16
16
|
#
|
@@ -27,7 +27,8 @@
|
|
27
27
|
# nice ruby interfaces for ATLAS functions.
|
28
28
|
#++
|
29
29
|
|
30
|
-
require 'nmatrix/nmatrix.rb'
|
30
|
+
require 'nmatrix/nmatrix.rb'
|
31
|
+
#need to have nmatrix required first or else bad things will happen
|
31
32
|
require_relative 'lapack_ext_common'
|
32
33
|
|
33
34
|
NMatrix.register_lapack_extension("nmatrix-atlas")
|
@@ -57,26 +58,37 @@ class NMatrix
|
|
57
58
|
module LAPACK
|
58
59
|
class << self
|
59
60
|
def posv(uplo, a, b)
|
60
|
-
raise(ShapeError, "a must be square") unless a.dim == 2
|
61
|
-
|
62
|
-
|
63
|
-
raise(
|
64
|
-
|
61
|
+
raise(ShapeError, "a must be square") unless a.dim == 2 \
|
62
|
+
&& a.shape[0] == a.shape[1]
|
63
|
+
|
64
|
+
raise(ShapeError, "number of rows of b must equal number of cols of a") \
|
65
|
+
unless a.shape[1] == b.shape[0]
|
66
|
+
|
67
|
+
raise(StorageTypeError, "only works with dense matrices") \
|
68
|
+
unless a.stype == :dense && b.stype == :dense
|
69
|
+
|
70
|
+
raise(DataTypeError, "only works for non-integer, non-object dtypes") \
|
71
|
+
if a.integer_dtype? || a.object_dtype? || \
|
72
|
+
b.integer_dtype? || b.object_dtype?
|
65
73
|
|
66
74
|
x = b.clone
|
67
75
|
clone = a.clone
|
68
76
|
n = a.shape[0]
|
69
77
|
nrhs = b.shape[1]
|
70
78
|
clapack_potrf(:row, uplo, n, clone, n)
|
71
|
-
# Must transpose b before and after:
|
79
|
+
# Must transpose b before and after:
|
80
|
+
# http://math-atlas.sourceforge.net/faq.html#RowSolve
|
72
81
|
x = x.transpose
|
73
82
|
clapack_potrs(:row, uplo, n, nrhs, clone, n, x, n)
|
74
83
|
x.transpose
|
75
84
|
end
|
76
85
|
|
77
86
|
def geev(matrix, which=:both)
|
78
|
-
raise(StorageTypeError, "LAPACK functions only work on dense matrices")
|
79
|
-
|
87
|
+
raise(StorageTypeError, "LAPACK functions only work on dense matrices") \
|
88
|
+
unless matrix.dense?
|
89
|
+
|
90
|
+
raise(ShapeError, "eigenvalues can only be computed for square matrices") \
|
91
|
+
unless matrix.dim == 2 && matrix.shape[0] == matrix.shape[1]
|
80
92
|
|
81
93
|
jobvl = (which == :both || which == :left) ? :t : false
|
82
94
|
jobvr = (which == :both || which == :right) ? :t : false
|
@@ -84,8 +96,10 @@ class NMatrix
|
|
84
96
|
n = matrix.shape[0]
|
85
97
|
|
86
98
|
# Outputs
|
87
|
-
eigenvalues = NMatrix.new([n, 1], dtype: matrix.dtype)
|
88
|
-
|
99
|
+
eigenvalues = NMatrix.new([n, 1], dtype: matrix.dtype)
|
100
|
+
# For real dtypes this holds only the real part of the eigenvalues.
|
101
|
+
imag_eigenvalues = matrix.complex_dtype? ? nil : NMatrix.new([n, 1], \
|
102
|
+
dtype: matrix.dtype) # For complex dtypes, this is unused.
|
89
103
|
left_output = jobvl ? matrix.clone_structure : nil
|
90
104
|
right_output = jobvr ? matrix.clone_structure : nil
|
91
105
|
|
@@ -121,19 +135,25 @@ class NMatrix
|
|
121
135
|
|
122
136
|
if !complex_indices.empty?
|
123
137
|
# For real dtypes, put the real and imaginary parts together
|
124
|
-
eigenvalues = eigenvalues + imag_eigenvalues*
|
125
|
-
|
126
|
-
|
138
|
+
eigenvalues = eigenvalues + imag_eigenvalues * \
|
139
|
+
Complex(0.0,1.0)
|
140
|
+
left_output = left_output.cast(dtype: \
|
141
|
+
NMatrix.upcast(:complex64, matrix.dtype)) if left_output
|
142
|
+
right_output = right_output.cast(dtype: NMatrix.upcast(:complex64, \
|
143
|
+
matrix.dtype)) if right_output
|
127
144
|
end
|
128
145
|
|
129
146
|
complex_indices.each_slice(2) do |i, _|
|
130
147
|
if right_output
|
131
|
-
right_output[0...n,i] = right_output[0...n,i] +
|
132
|
-
|
148
|
+
right_output[0...n,i] = right_output[0...n,i] + \
|
149
|
+
right_output[0...n,i+1] * Complex(0.0,1.0)
|
150
|
+
right_output[0...n,i+1] = \
|
151
|
+
right_output[0...n,i].complex_conjugate
|
133
152
|
end
|
134
153
|
|
135
154
|
if left_output
|
136
|
-
left_output[0...n,i] = left_output[0...n,i] +
|
155
|
+
left_output[0...n,i] = left_output[0...n,i] + \
|
156
|
+
left_output[0...n,i+1] * Complex(0.0,1.0)
|
137
157
|
left_output[0...n,i+1] = left_output[0...n,i].complex_conjugate
|
138
158
|
end
|
139
159
|
end
|
@@ -157,15 +177,18 @@ class NMatrix
|
|
157
177
|
# This is a pure LAPACK function so it expects column-major functions.
|
158
178
|
# So we need to transpose the input as well as the output.
|
159
179
|
matrix = matrix.transpose
|
160
|
-
NMatrix::LAPACK::lapack_gesvd(:a, :a, m, n, matrix,
|
180
|
+
NMatrix::LAPACK::lapack_gesvd(:a, :a, m, n, matrix, \
|
181
|
+
m, result[1], result[0], m, result[2], n, workspace_size)
|
161
182
|
result[0] = result[0].transpose
|
162
183
|
result[2] = result[2].transpose
|
163
184
|
result
|
164
185
|
end
|
165
186
|
|
166
187
|
def gesdd(matrix, workspace_size=nil)
|
167
|
-
min_workspace_size = matrix.shape.min *
|
168
|
-
|
188
|
+
min_workspace_size = matrix.shape.min * \
|
189
|
+
(6 + 4 * matrix.shape.min) + matrix.shape.max
|
190
|
+
workspace_size = min_workspace_size if \
|
191
|
+
workspace_size.nil? || workspace_size < min_workspace_size
|
169
192
|
|
170
193
|
result = alloc_svd_result(matrix)
|
171
194
|
|
@@ -175,7 +198,8 @@ class NMatrix
|
|
175
198
|
# This is a pure LAPACK function so it expects column-major functions.
|
176
199
|
# So we need to transpose the input as well as the output.
|
177
200
|
matrix = matrix.transpose
|
178
|
-
NMatrix::LAPACK::lapack_gesdd(:a, m, n, matrix, m, result[1],
|
201
|
+
NMatrix::LAPACK::lapack_gesdd(:a, m, n, matrix, m, result[1], \
|
202
|
+
result[0], m, result[2], n, workspace_size)
|
179
203
|
result[0] = result[0].transpose
|
180
204
|
result[2] = result[2].transpose
|
181
205
|
result
|
@@ -184,9 +208,14 @@ class NMatrix
|
|
184
208
|
end
|
185
209
|
|
186
210
|
def invert!
|
187
|
-
raise(StorageTypeError, "invert only works on dense matrices currently")
|
188
|
-
|
189
|
-
|
211
|
+
raise(StorageTypeError, "invert only works on dense matrices currently") \
|
212
|
+
unless self.dense?
|
213
|
+
|
214
|
+
raise(ShapeError, "Cannot invert non-square matrix") \
|
215
|
+
unless shape[0] == shape[1]
|
216
|
+
|
217
|
+
raise(DataTypeError, "Cannot invert an integer matrix in-place") \
|
218
|
+
if self.integer_dtype?
|
190
219
|
|
191
220
|
# Even though we are using the ATLAS plugin, we still might be missing
|
192
221
|
# CLAPACK (and thus clapack_getri) if we are on OS X.
|
@@ -205,8 +234,10 @@ class NMatrix
|
|
205
234
|
end
|
206
235
|
|
207
236
|
def potrf!(which)
|
208
|
-
raise(StorageTypeError, "ATLAS functions only work on dense matrices")
|
209
|
-
|
237
|
+
raise(StorageTypeError, "ATLAS functions only work on dense matrices") \
|
238
|
+
unless self.dense?
|
239
|
+
raise(ShapeError, "Cholesky decomposition only valid for square matrices") \
|
240
|
+
unless self.dim == 2 && self.shape[0] == self.shape[1]
|
210
241
|
|
211
242
|
NMatrix::LAPACK::clapack_potrf(:row, which, self.shape[0], self, self.shape[1])
|
212
243
|
end
|
data/spec/00_nmatrix_spec.rb
CHANGED
@@ -424,6 +424,13 @@ describe 'NMatrix' do
|
|
424
424
|
expect(n.reshape!([8,2]).eql?(n)).to eq(true) # because n itself changes
|
425
425
|
end
|
426
426
|
|
427
|
+
it "should do the reshape operation in place, changing dimension" do
|
428
|
+
n = NMatrix.seq(4)
|
429
|
+
a = n.reshape!([4,2,2])
|
430
|
+
expect(n).to eq(NMatrix.seq([4,2,2]))
|
431
|
+
expect(a).to eq(NMatrix.seq([4,2,2]))
|
432
|
+
end
|
433
|
+
|
427
434
|
it "reshape and reshape! must produce same result" do
|
428
435
|
n = NMatrix.seq(4)+1
|
429
436
|
a = NMatrix.seq(4)+1
|
@@ -432,7 +439,7 @@ describe 'NMatrix' do
|
|
432
439
|
|
433
440
|
it "should prevent a resize in place" do
|
434
441
|
n = NMatrix.seq(4)+1
|
435
|
-
expect { n.reshape([5,2]) }.to raise_error(ArgumentError)
|
442
|
+
expect { n.reshape!([5,2]) }.to raise_error(ArgumentError)
|
436
443
|
end
|
437
444
|
end
|
438
445
|
|
@@ -534,6 +541,26 @@ describe 'NMatrix' do
|
|
534
541
|
n = NMatrix.new([1,3,1], [1,2,3])
|
535
542
|
expect(n.dconcat(n)).to eq(NMatrix.new([1,3,2], [1,1,2,2,3,3]))
|
536
543
|
end
|
544
|
+
|
545
|
+
it "should work on matrices with different size along concat dim" do
|
546
|
+
n = N[[1, 2, 3],
|
547
|
+
[4, 5, 6]]
|
548
|
+
m = N[[7],
|
549
|
+
[8]]
|
550
|
+
|
551
|
+
expect(n.hconcat(m)).to eq N[[1, 2, 3, 7], [4, 5, 6, 8]]
|
552
|
+
expect(m.hconcat(n)).to eq N[[7, 1, 2, 3], [8, 4, 5, 6]]
|
553
|
+
end
|
554
|
+
|
555
|
+
it "should work on matrices with different size along concat dim" do
|
556
|
+
n = N[[1, 2, 3],
|
557
|
+
[4, 5, 6]]
|
558
|
+
|
559
|
+
m = N[[7, 8, 9]]
|
560
|
+
|
561
|
+
expect(n.vconcat(m)).to eq N[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
562
|
+
expect(m.vconcat(n)).to eq N[[7, 8, 9], [1, 2, 3], [4, 5, 6]]
|
563
|
+
end
|
537
564
|
end
|
538
565
|
|
539
566
|
context "#[]" do
|
@@ -631,6 +658,23 @@ describe 'NMatrix' do
|
|
631
658
|
end
|
632
659
|
end
|
633
660
|
|
661
|
+
context "#last" do
|
662
|
+
it "returns the last element of a 1-dimensional NMatrix" do
|
663
|
+
n = NMatrix.new([1,4], [1,2,3,4])
|
664
|
+
expect(n.last).to eq(4)
|
665
|
+
end
|
666
|
+
|
667
|
+
it "returns the last element of a 2-dimensional NMatrix" do
|
668
|
+
n = NMatrix.new([2,2], [4,8,12,16])
|
669
|
+
expect(n.last).to eq(16)
|
670
|
+
end
|
671
|
+
|
672
|
+
it "returns the last element of a 3-dimensional NMatrix" do
|
673
|
+
n = NMatrix.new([2,2,2], [1,2,3,4,5,6,7,8])
|
674
|
+
expect(n.last).to eq(8)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
634
678
|
context "#diagonal" do
|
635
679
|
ALL_DTYPES.each do |dtype|
|
636
680
|
before do
|
@@ -682,6 +726,11 @@ describe 'NMatrix' do
|
|
682
726
|
expect(@sample_matrix.repeat(2, 0)).to eq(NMatrix.new([4, 2], [1, 2, 3, 4, 1, 2, 3, 4]))
|
683
727
|
expect(@sample_matrix.repeat(2, 1)).to eq(NMatrix.new([2, 4], [1, 2, 1, 2, 3, 4, 3, 4]))
|
684
728
|
end
|
729
|
+
|
730
|
+
it "preserves dtype" do
|
731
|
+
expect(@sample_matrix.repeat(2, 0).dtype).to eq(@sample_matrix.dtype)
|
732
|
+
expect(@sample_matrix.repeat(2, 1).dtype).to eq(@sample_matrix.dtype)
|
733
|
+
end
|
685
734
|
end
|
686
735
|
|
687
736
|
context "#meshgrid" do
|
data/spec/02_slice_spec.rb
CHANGED
@@ -127,9 +127,9 @@ describe "Slice operation" do
|
|
127
127
|
it "should have #is_ref? method" do
|
128
128
|
a = stype_matrix[0..1, 0..1]
|
129
129
|
b = stype_matrix.slice(0..1, 0..1)
|
130
|
-
expect(stype_matrix.is_ref?).to
|
131
|
-
expect(a.is_ref?).to
|
132
|
-
expect(b.is_ref?).to
|
130
|
+
expect(stype_matrix.is_ref?).to be false
|
131
|
+
expect(a.is_ref?).to be true
|
132
|
+
expect(b.is_ref?).to be false
|
133
133
|
end
|
134
134
|
|
135
135
|
it "reference should compare with non-reference" do
|
@@ -141,7 +141,7 @@ describe "Slice operation" do
|
|
141
141
|
context "with copying" do
|
142
142
|
it 'should return an NMatrix' do
|
143
143
|
n = stype_matrix.slice(0..1,0..1)
|
144
|
-
expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to
|
144
|
+
expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to be true
|
145
145
|
end
|
146
146
|
|
147
147
|
it 'should return a copy of 2x2 matrix to self elements' do
|
@@ -183,19 +183,19 @@ describe "Slice operation" do
|
|
183
183
|
|
184
184
|
[:dense, :list, :yale].each do |cast_type|
|
185
185
|
it "should cast copied slice from #{stype.upcase} to #{cast_type.upcase}" do
|
186
|
-
expect(nm_eql(stype_matrix.slice(1..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(1..2,1..2))).to
|
187
|
-
expect(nm_eql(stype_matrix.slice(0..1, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..1,1..2))).to
|
188
|
-
expect(nm_eql(stype_matrix.slice(1..2, 0..1).cast(cast_type, :int32), stype_matrix.slice(1..2,0..1))).to
|
189
|
-
expect(nm_eql(stype_matrix.slice(0..1, 0..1).cast(cast_type, :int32), stype_matrix.slice(0..1,0..1))).to
|
186
|
+
expect(nm_eql(stype_matrix.slice(1..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(1..2,1..2))).to be true
|
187
|
+
expect(nm_eql(stype_matrix.slice(0..1, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..1,1..2))).to be true
|
188
|
+
expect(nm_eql(stype_matrix.slice(1..2, 0..1).cast(cast_type, :int32), stype_matrix.slice(1..2,0..1))).to be true
|
189
|
+
expect(nm_eql(stype_matrix.slice(0..1, 0..1).cast(cast_type, :int32), stype_matrix.slice(0..1,0..1))).to be true
|
190
190
|
|
191
191
|
# Non square
|
192
|
-
expect(nm_eql(stype_matrix.slice(0..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..2,1..2))).to
|
192
|
+
expect(nm_eql(stype_matrix.slice(0..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..2,1..2))).to be true
|
193
193
|
#require 'pry'
|
194
194
|
#binding.pry if cast_type == :yale
|
195
|
-
expect(nm_eql(stype_matrix.slice(1..2, 0..2).cast(cast_type, :int32), stype_matrix.slice(1..2,0..2))).to
|
195
|
+
expect(nm_eql(stype_matrix.slice(1..2, 0..2).cast(cast_type, :int32), stype_matrix.slice(1..2,0..2))).to be true
|
196
196
|
|
197
197
|
# Full
|
198
|
-
expect(nm_eql(stype_matrix.slice(0..2, 0..2).cast(cast_type, :int32), stype_matrix)).to
|
198
|
+
expect(nm_eql(stype_matrix.slice(0..2, 0..2).cast(cast_type, :int32), stype_matrix)).to be true
|
199
199
|
end
|
200
200
|
end
|
201
201
|
end
|
@@ -214,7 +214,7 @@ describe "Slice operation" do
|
|
214
214
|
context "by reference" do
|
215
215
|
it 'should return an NMatrix' do
|
216
216
|
n = stype_matrix[0..1,0..1]
|
217
|
-
expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to
|
217
|
+
expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to be true
|
218
218
|
end
|
219
219
|
|
220
220
|
it 'should return a 2x2 matrix with refs to self elements' do
|
@@ -246,7 +246,7 @@ describe "Slice operation" do
|
|
246
246
|
|
247
247
|
it 'should slice again' do
|
248
248
|
n = stype_matrix[1..2, 1..2]
|
249
|
-
expect(nm_eql(n[1,0..1], NVector.new(2, [7,8], dtype: :int32).transpose)).to
|
249
|
+
expect(nm_eql(n[1,0..1], NVector.new(2, [7,8], dtype: :int32).transpose)).to be true
|
250
250
|
end
|
251
251
|
|
252
252
|
it 'should be correct slice for range 0..2 and 0...3' do
|
@@ -320,7 +320,7 @@ describe "Slice operation" do
|
|
320
320
|
end
|
321
321
|
|
322
322
|
it "compares slices to scalars" do
|
323
|
-
(stype_matrix[1, 0..2] > 2).each { |e| expect(e != 0).to
|
323
|
+
(stype_matrix[1, 0..2] > 2).each { |e| expect(e != 0).to be true }
|
324
324
|
end
|
325
325
|
|
326
326
|
it "iterates only over elements in the slice" do
|
@@ -367,20 +367,20 @@ describe "Slice operation" do
|
|
367
367
|
|
368
368
|
[:dense, :list, :yale].each do |cast_type|
|
369
369
|
it "should cast a square reference-slice from #{stype.upcase} to #{cast_type.upcase}" do
|
370
|
-
expect(nm_eql(stype_matrix[1..2, 1..2].cast(cast_type), stype_matrix[1..2,1..2])).to
|
371
|
-
expect(nm_eql(stype_matrix[0..1, 1..2].cast(cast_type), stype_matrix[0..1,1..2])).to
|
372
|
-
expect(nm_eql(stype_matrix[1..2, 0..1].cast(cast_type), stype_matrix[1..2,0..1])).to
|
373
|
-
expect(nm_eql(stype_matrix[0..1, 0..1].cast(cast_type), stype_matrix[0..1,0..1])).to
|
370
|
+
expect(nm_eql(stype_matrix[1..2, 1..2].cast(cast_type), stype_matrix[1..2,1..2])).to be true
|
371
|
+
expect(nm_eql(stype_matrix[0..1, 1..2].cast(cast_type), stype_matrix[0..1,1..2])).to be true
|
372
|
+
expect(nm_eql(stype_matrix[1..2, 0..1].cast(cast_type), stype_matrix[1..2,0..1])).to be true
|
373
|
+
expect(nm_eql(stype_matrix[0..1, 0..1].cast(cast_type), stype_matrix[0..1,0..1])).to be true
|
374
374
|
end
|
375
375
|
|
376
376
|
it "should cast a rectangular reference-slice from #{stype.upcase} to #{cast_type.upcase}" do
|
377
377
|
# Non square
|
378
|
-
expect(nm_eql(stype_matrix[0..2, 1..2].cast(cast_type), stype_matrix[0..2,1..2])).to
|
379
|
-
expect(nm_eql(stype_matrix[1..2, 0..2].cast(cast_type), stype_matrix[1..2,0..2])).to
|
378
|
+
expect(nm_eql(stype_matrix[0..2, 1..2].cast(cast_type), stype_matrix[0..2,1..2])).to be true # FIXME: memory problem.
|
379
|
+
expect(nm_eql(stype_matrix[1..2, 0..2].cast(cast_type), stype_matrix[1..2,0..2])).to be true # this one is fine
|
380
380
|
end
|
381
381
|
|
382
382
|
it "should cast a square full-matrix reference-slice from #{stype.upcase} to #{cast_type.upcase}" do
|
383
|
-
expect(nm_eql(stype_matrix[0..2, 0..2].cast(cast_type), stype_matrix)).to
|
383
|
+
expect(nm_eql(stype_matrix[0..2, 0..2].cast(cast_type), stype_matrix)).to be true
|
384
384
|
end
|
385
385
|
end
|
386
386
|
end
|
data/spec/blas_spec.rb
CHANGED
@@ -69,6 +69,18 @@ describe NMatrix::BLAS do
|
|
69
69
|
expect(b[0]).to eq(-15.0/2)
|
70
70
|
expect(b[1]).to eq(5)
|
71
71
|
expect(b[2]).to eq(-13)
|
72
|
+
|
73
|
+
NMatrix::BLAS::cblas_trsm(:row, :left, :lower, :transpose, :nounit, 3, 1, 1.0, a, 3, b, 1)
|
74
|
+
|
75
|
+
expect(b[0]).to eq(307.0/8)
|
76
|
+
expect(b[1]).to eq(57.0/2)
|
77
|
+
expect(b[2]).to eq(26.0)
|
78
|
+
|
79
|
+
NMatrix::BLAS::cblas_trsm(:row, :left, :upper, :transpose, :unit, 3, 1, 1.0, a, 3, b, 1)
|
80
|
+
|
81
|
+
expect(b[0]).to eq(307.0/8)
|
82
|
+
expect(b[1]).to eq(763.0/16)
|
83
|
+
expect(b[2]).to eq(4269.0/64)
|
72
84
|
end
|
73
85
|
|
74
86
|
# trmm multiplies two matrices, where one of the two is required to be
|
@@ -174,9 +186,17 @@ describe NMatrix::BLAS do
|
|
174
186
|
|
175
187
|
it "exposes nrm2" do
|
176
188
|
pending("broken for :object") if dtype == :object
|
177
|
-
pending("Temporarily disable because the internal implementation of nrm2 is broken -WL 2015-05-17") if dtype == :complex64 || dtype == :complex128
|
178
189
|
|
179
|
-
|
190
|
+
if dtype =~ /complex/
|
191
|
+
x = NMatrix.new([3,1], [Complex(1,2),Complex(3,4),Complex(0,6)], dtype: dtype)
|
192
|
+
y = NMatrix.new([3,1], [Complex(0,0),Complex(0,0),Complex(0,0)], dtype: dtype)
|
193
|
+
nrm2 = 8.12403840463596
|
194
|
+
else
|
195
|
+
x = NMatrix.new([4,1], [2,-4,3,5], dtype: dtype)
|
196
|
+
y = NMatrix.new([3,1], [0,0,0], dtype: dtype)
|
197
|
+
nrm2 = 5.385164807134504
|
198
|
+
end
|
199
|
+
|
180
200
|
err = case dtype
|
181
201
|
when :float32, :complex64
|
182
202
|
1e-6
|
@@ -185,7 +205,9 @@ describe NMatrix::BLAS do
|
|
185
205
|
else
|
186
206
|
1e-14
|
187
207
|
end
|
188
|
-
|
208
|
+
|
209
|
+
expect(NMatrix::BLAS.nrm2(x, 1, 3)).to be_within(err).of(nrm2)
|
210
|
+
expect(NMatrix::BLAS.nrm2(y, 1, 3)).to be_within(err).of(0)
|
189
211
|
end
|
190
212
|
|
191
213
|
end
|