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.
@@ -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,float32_t>,
372
- nm::math::atlas::cblas_nrm2<float64_t,float64_t>,
373
- nm::math::atlas::cblas_nrm2<float32_t,nm::Complex64>,
374
- nm::math::atlas::cblas_nrm2<float64_t,nm::Complex128>,
375
- nm::math::atlas::cblas_nrm2<nm::RubyObject,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,uint8_t>,
421
- nm::math::atlas::cblas_asum<int8_t,int8_t>,
422
- nm::math::atlas::cblas_asum<int16_t,int16_t>,
423
- nm::math::atlas::cblas_asum<int32_t,int32_t>,
424
- nm::math::atlas::cblas_asum<int64_t,int64_t>,
425
- nm::math::atlas::cblas_asum<float32_t,float32_t>,
426
- nm::math::atlas::cblas_asum<float64_t,float64_t>,
427
- nm::math::atlas::cblas_asum<float32_t,nm::Complex64>,
428
- nm::math::atlas::cblas_asum<float64_t,nm::Complex128>,
429
- nm::math::atlas::cblas_asum<nm::RubyObject,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);
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # == Copyright Information
11
11
  #
12
- # SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
- # NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
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' #need to have nmatrix required first or else bad things will happen
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 && a.shape[0] == a.shape[1]
61
- raise(ShapeError, "number of rows of b must equal number of cols of a") unless a.shape[1] == b.shape[0]
62
- raise(StorageTypeError, "only works with dense matrices") unless a.stype == :dense && b.stype == :dense
63
- raise(DataTypeError, "only works for non-integer, non-object dtypes") if
64
- a.integer_dtype? || a.object_dtype? || b.integer_dtype? || b.object_dtype?
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: http://math-atlas.sourceforge.net/faq.html#RowSolve
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") unless matrix.dense?
79
- raise(ShapeError, "eigenvalues can only be computed for square matrices") unless matrix.dim == 2 && matrix.shape[0] == matrix.shape[1]
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) # For real dtypes this holds only the real part of the eigenvalues.
88
- imag_eigenvalues = matrix.complex_dtype? ? nil : NMatrix.new([n, 1], dtype: matrix.dtype) # For complex dtypes, this is unused.
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*Complex(0.0,1.0)
125
- left_output = left_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if left_output
126
- right_output = right_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if right_output
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] + right_output[0...n,i+1]*Complex(0.0,1.0)
132
- right_output[0...n,i+1] = right_output[0...n,i].complex_conjugate
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] + left_output[0...n,i+1]*Complex(0.0,1.0)
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, m, result[1], result[0], m, result[2], n, workspace_size)
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 * (6 + 4 * matrix.shape.min) + matrix.shape.max
168
- workspace_size = min_workspace_size if workspace_size.nil? || workspace_size < min_workspace_size
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], result[0], m, result[2], n, workspace_size)
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") unless self.dense?
188
- raise(ShapeError, "Cannot invert non-square matrix") unless shape[0] == shape[1]
189
- raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype?
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") unless self.dense?
209
- raise(ShapeError, "Cholesky decomposition only valid for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1]
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
@@ -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
@@ -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 be_false
131
- expect(a.is_ref?).to be_true
132
- expect(b.is_ref?).to be_false
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 be_true
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 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
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 be_true
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 be_true
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 be_true
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 be_true
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 be_true
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 be_true }
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 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
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 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
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 be_true
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
@@ -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
- x = NMatrix.new([4,1], [2,-4,3,5], dtype: dtype)
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
- expect(NMatrix::BLAS.nrm2(x, 1, 3)).to be_within(err).of(5.385164807134504)
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