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.
@@ -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