nmatrix-atlas 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|