nmatrix-fftw 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.
@@ -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
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
- 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
data/spec/math_spec.rb CHANGED
@@ -285,6 +285,152 @@ describe "math" do
285
285
  end
286
286
  end
287
287
 
288
+ NON_INTEGER_DTYPES.each do |dtype|
289
+ next if dtype == :object
290
+ context dtype do
291
+
292
+ it "calculates QR decomposition using factorize_qr for a square matrix" do
293
+
294
+ a = NMatrix.new(3, [12.0, -51.0, 4.0,
295
+ 6.0, 167.0, -68.0,
296
+ -4.0, 24.0, -41.0] , dtype: dtype)
297
+
298
+ q_solution = NMatrix.new([3,3], Q_SOLUTION_ARRAY_2, dtype: dtype)
299
+
300
+ r_solution = NMatrix.new([3,3], [-14.0, -21.0, 14,
301
+ 0.0, -175, 70,
302
+ 0.0, 0.0, -35] , dtype: dtype)
303
+
304
+ err = case dtype
305
+ when :float32, :complex64
306
+ 1e-4
307
+ when :float64, :complex128
308
+ 1e-13
309
+ end
310
+
311
+ begin
312
+ q,r = a.factorize_qr
313
+
314
+ expect(q).to be_within(err).of(q_solution)
315
+ expect(r).to be_within(err).of(r_solution)
316
+
317
+ rescue NotImplementedError
318
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
319
+ end
320
+ end
321
+
322
+ it "calculates QR decomposition using factorize_qr for a tall and narrow rectangular matrix" do
323
+
324
+ a = NMatrix.new([4,2], [34.0, 21.0,
325
+ 23.0, 53.0,
326
+ 26.0, 346.0,
327
+ 23.0, 121.0] , dtype: dtype)
328
+
329
+ q_solution = NMatrix.new([4,4], Q_SOLUTION_ARRAY_1, dtype: dtype)
330
+
331
+ r_solution = NMatrix.new([4,2], [-53.75872022286244, -255.06559574252242,
332
+ 0.0, 269.34836526051555,
333
+ 0.0, 0.0,
334
+ 0.0, 0.0] , dtype: dtype)
335
+
336
+ err = case dtype
337
+ when :float32, :complex64
338
+ 1e-4
339
+ when :float64, :complex128
340
+ 1e-13
341
+ end
342
+
343
+ begin
344
+ q,r = a.factorize_qr
345
+
346
+ expect(q).to be_within(err).of(q_solution)
347
+ expect(r).to be_within(err).of(r_solution)
348
+
349
+ rescue NotImplementedError
350
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
351
+ end
352
+ end
353
+
354
+ it "calculates QR decomposition using factorize_qr for a short and wide rectangular matrix" do
355
+
356
+ a = NMatrix.new([3,4], [123,31,57,81,92,14,17,36,42,34,11,28], dtype: dtype)
357
+
358
+ q_solution = NMatrix.new([3,3], Q_SOLUTION_ARRAY_3, dtype: dtype)
359
+
360
+ r_solution = NMatrix.new([3,4], R_SOLUTION_ARRAY, dtype: dtype)
361
+
362
+ err = case dtype
363
+ when :float32, :complex64
364
+ 1e-4
365
+ when :float64, :complex128
366
+ 1e-13
367
+ end
368
+
369
+ begin
370
+ q,r = a.factorize_qr
371
+
372
+ expect(q).to be_within(err).of(q_solution)
373
+ expect(r).to be_within(err).of(r_solution)
374
+
375
+ rescue NotImplementedError
376
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
377
+ end
378
+ end
379
+
380
+ it "calculates QR decomposition such that A - QR ~ 0" do
381
+
382
+ a = NMatrix.new([3,3], [ 9.0, 0.0, 26.0,
383
+ 12.0, 0.0, -7.0,
384
+ 0.0, 4.0, 0.0] , dtype: dtype)
385
+
386
+ err = case dtype
387
+ when :float32, :complex64
388
+ 1e-4
389
+ when :float64, :complex128
390
+ 1e-13
391
+ end
392
+
393
+ begin
394
+ q,r = a.factorize_qr
395
+ a_expected = q.dot(r)
396
+
397
+ expect(a_expected).to be_within(err).of(a)
398
+
399
+ rescue NotImplementedError
400
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
401
+ end
402
+ end
403
+
404
+
405
+ it "calculates the orthogonal matrix Q in QR decomposition" do
406
+
407
+ a = N.new([2,2], [34.0, 21, 23, 53] , dtype: dtype)
408
+
409
+ err = case dtype
410
+ when :float32, :complex64
411
+ 1e-4
412
+ when :float64, :complex128
413
+ 1e-13
414
+ end
415
+
416
+ begin
417
+ q,r = a.factorize_qr
418
+
419
+ #Q is orthogonal if Q x Q.transpose = I
420
+ product = q.dot(q.transpose)
421
+
422
+ expect(product[0,0]).to be_within(err).of(1)
423
+ expect(product[1,0]).to be_within(err).of(0)
424
+ expect(product[0,1]).to be_within(err).of(0)
425
+ expect(product[1,1]).to be_within(err).of(1)
426
+
427
+ rescue NotImplementedError
428
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
429
+ end
430
+ end
431
+ end
432
+ end
433
+
288
434
  ALL_DTYPES.each do |dtype|
289
435
  next if dtype == :byte #doesn't work for unsigned types
290
436
  next if dtype == :object
@@ -332,6 +478,49 @@ describe "math" do
332
478
  end
333
479
  end
334
480
 
481
+ ALL_DTYPES.each do |dtype|
482
+ next if dtype == :byte #doesn't work for unsigned types
483
+ next if dtype == :object
484
+
485
+ context dtype do
486
+ err = case dtype
487
+ when :float32, :complex64
488
+ 1e-4
489
+ else #integer matrices will return :float64
490
+ 1e-13
491
+ end
492
+
493
+ it "should correctly find adjugate a matrix in place (bang)" do
494
+ a = NMatrix.new(:dense, 2, [2, 3, 3, 5], dtype)
495
+ b = NMatrix.new(:dense, 2, [5, -3, -3, 2], dtype)
496
+
497
+ if a.integer_dtype?
498
+ expect{a.adjugate!}.to raise_error(DataTypeError)
499
+ else
500
+ #should return adjugate as well as modifying a
501
+ r = a.adjugate!
502
+ expect(a).to be_within(err).of(b)
503
+ expect(r).to be_within(err).of(b)
504
+ end
505
+ end
506
+
507
+
508
+ it "should correctly find adjugate of a matrix out-of-place" do
509
+ a = NMatrix.new(:dense, 3, [-3, 2, -5, -1, 0, -2, 3, -4, 1], dtype)
510
+
511
+ if a.integer_dtype?
512
+ b = NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], :float64)
513
+ else
514
+ b = NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], dtype)
515
+ end
516
+
517
+ expect(a.adjoint).to be_within(err).of(b)
518
+ expect(a.adjugate).to be_within(err).of(b)
519
+ end
520
+
521
+ end
522
+ end
523
+
335
524
  # TODO: Get it working with ROBJ too
336
525
  [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |left_dtype|
337
526
  [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |right_dtype|
@@ -702,7 +891,7 @@ describe "math" do
702
891
  360, 96, 51, -14,
703
892
  448,-231,-24,-87,
704
893
  -1168, 595,234, 523],
705
- dtype: answer_dtype,
894
+ dtype: answer_dtype,
706
895
  stype: stype))
707
896
  end
708
897
 
@@ -757,7 +946,6 @@ describe "math" do
757
946
 
758
947
  context "determinants" do
759
948
  ALL_DTYPES.each do |dtype|
760
- next if dtype == :object
761
949
  context dtype do
762
950
  before do
763
951
  @a = NMatrix.new([2,2], [1,2,
@@ -779,13 +967,19 @@ describe "math" do
779
967
  end
780
968
  end
781
969
  it "computes the determinant of 2x2 matrix" do
782
- expect(@a.det).to be_within(@err).of(-2)
970
+ if dtype != :object
971
+ expect(@a.det).to be_within(@err).of(-2)
972
+ end
783
973
  end
784
974
  it "computes the determinant of 3x3 matrix" do
785
- expect(@b.det).to be_within(@err).of(-8)
975
+ if dtype != :object
976
+ expect(@b.det).to be_within(@err).of(-8)
977
+ end
786
978
  end
787
979
  it "computes the determinant of 4x4 matrix" do
788
- expect(@c.det).to be_within(@err).of(-18)
980
+ if dtype != :object
981
+ expect(@c.det).to be_within(@err).of(-18)
982
+ end
789
983
  end
790
984
  it "computes the exact determinant of 2x2 matrix" do
791
985
  if dtype == :byte
@@ -804,4 +998,38 @@ describe "math" do
804
998
  end
805
999
  end
806
1000
  end
1001
+
1002
+ context "#scale and #scale!" do
1003
+ [:dense,:list,:yale].each do |stype|
1004
+ ALL_DTYPES.each do |dtype|
1005
+ next if dtype == :object
1006
+ context "for #{dtype}" do
1007
+ before do
1008
+ @m = NMatrix.new([3, 3], [0, 1, 2,
1009
+ 3, 4, 5,
1010
+ 6, 7, 8], stype: stype, dtype: dtype)
1011
+ end
1012
+ it "scales the matrix by a given factor and return the result" do
1013
+ if integer_dtype? dtype
1014
+ expect{@m.scale 2.0}.to raise_error(DataTypeError)
1015
+ else
1016
+ expect(@m.scale 2.0).to eq(NMatrix.new([3, 3], [0, 2, 4,
1017
+ 6, 8, 10,
1018
+ 12, 14, 16], stype: stype, dtype: dtype))
1019
+ end
1020
+ end
1021
+ it "scales the matrix in place by a given factor" do
1022
+ if dtype == :int8
1023
+ expect{@m.scale! 2}.to raise_error(DataTypeError)
1024
+ else
1025
+ @m.scale! 2
1026
+ expect(@m).to eq(NMatrix.new([3, 3], [0, 2, 4,
1027
+ 6, 8, 10,
1028
+ 12, 14, 16], stype: stype, dtype: dtype))
1029
+ end
1030
+ end
1031
+ end
1032
+ end
1033
+ end
1034
+ end
807
1035
  end
@@ -50,10 +50,45 @@ describe NMatrix do
50
50
  expect(m).to eq identity3
51
51
  end
52
52
 
53
+ it "hilbert() creates an hilbert matrix" do
54
+ m = NMatrix.hilbert(8)
55
+ expect(m[4, 0]).to be_within(0.000001).of(0.2)
56
+ expect(m[4, 1]).to be_within(0.000001).of(0.16666666666666666)
57
+ expect(m[4, 2]).to be_within(0.000001).of(0.14285714285714285)
58
+ expect(m[4, 3]).to be_within(0.000001).of(0.125)
59
+
60
+ m = NMatrix.hilbert(3)
61
+ hilbert3 = NMatrix.new([3, 3], [1.0, 0.5, 0.3333333333333333,\
62
+ 0.5, 0.3333333333333333, 0.25, 0.3333333333333333, 0.25, 0.2])
63
+ expect(m).to eq hilbert3
64
+ 0.upto(2) do |i|
65
+ 0.upto(2) do |j|
66
+ expect(m[i, j]).to be_within(0.000001).of(hilbert3[i,j])
67
+ end
68
+ end
69
+ end
70
+
71
+ it "inv_hilbert() creates an inverse hilbert matrix" do
72
+ m = NMatrix.inv_hilbert(6)
73
+ inv_hilbert6 = [3360.0, -88200.0, 564480.0, -1411200.0]
74
+ expect(m[2,0]).to be_within(0.000001).of(inv_hilbert6[0])
75
+ expect(m[2,1]).to be_within(0.000001).of(inv_hilbert6[1])
76
+ expect(m[2,2]).to be_within(0.000001).of(inv_hilbert6[2])
77
+ expect(m[2,3]).to be_within(0.000001).of(inv_hilbert6[3])
78
+
79
+ m = NMatrix.inv_hilbert(3)
80
+ inv_hilbert3 = NMatrix.new([3, 3], [ 9.0, -36.0, 30.0, -36.0, 192.0, -180.0, 30.0, -180.0, 180.0] )
81
+ 0.upto(2) do |i|
82
+ 0.upto(2) do |j|
83
+ expect(m[i, j]).to be_within(0.000001).of(inv_hilbert3[i,j])
84
+ end
85
+ end
86
+ end
87
+
53
88
  it "diag() creates a matrix with pre-supplied diagonal" do
54
89
  arr = [1,2,3,4]
55
90
  m = NMatrix.diag(arr)
56
- expect(m.is_a?(NMatrix)).to be_true
91
+ expect(m.is_a?(NMatrix)).to be true
57
92
  end
58
93
 
59
94
  it "diagonals() contains the seeded values on the diagonal" do
@@ -123,6 +158,112 @@ describe NMatrix do
123
158
  expect { NMatrix.random("not an array or integer") }.to raise_error
124
159
  end
125
160
  end
161
+
162
+ context "::magic" do
163
+
164
+ ALL_DTYPES.each do |dtype|
165
+ context dtype do
166
+ it "creates a matrix with numbers from 1 to n^n(n squared)" do
167
+ a = NMatrix.magic(3, dtype: dtype)
168
+ magic3 = NMatrix.new([3,3], [4, 9, 2, 3, 5, 7, 8, 1, 6], dtype: dtype)
169
+ expect(a).to eq magic3
170
+
171
+ b = NMatrix.magic(4, dtype: dtype)
172
+ magic4 = NMatrix.new([4,4], [1, 15, 14, 4, 12, 6, 7, 9, 8, 10, 11, 5, 13, 3, 2, 16], dtype: dtype)
173
+ expect(b).to eq magic4
174
+
175
+ c = NMatrix.magic(6, dtype: dtype)
176
+ magic6 = NMatrix.new([6,6], [31, 9, 2, 22, 27, 20, 3, 32, 7, 21, 23, 25, 35, 1, 6, 26, 19, 24, 4, 36, 29, 13, 18, 11, 30, 5, 34, 12, 14, 16, 8, 28, 33, 17, 10, 15], dtype: dtype)
177
+ expect(c).to eq magic6
178
+ end
179
+ end
180
+ end
181
+
182
+ it "shape of two is not allowed" do
183
+ expect { NMatrix.magic(2) }.to raise_error(ArgumentError)
184
+ end
185
+
186
+ it "Only accepts an integer as dimension" do
187
+ expect { NMatrix.magic(3.0) }.to raise_error(ArgumentError)
188
+ end
189
+ end
190
+
191
+ context "::linspace" do
192
+ it "creates a row vector when given only one shape parameter" do
193
+ v = NMatrix.linspace(1, 10, 4)
194
+ #Expect a row vector only
195
+ expect(v.shape.length).to eq(1)
196
+
197
+ ans = [1.0,4.0,7.0,10.0]
198
+
199
+ expect(v[0]).to be_within(0.000001).of(ans[0])
200
+ expect(v[1]).to be_within(0.000001).of(ans[1])
201
+ expect(v[2]).to be_within(0.000001).of(ans[2])
202
+ expect(v[3]).to be_within(0.000001).of(ans[3])
203
+ end
204
+
205
+ it "creates a matrix of input shape with each entry linearly spaced in row major order" do
206
+ v = NMatrix.linspace(1, Math::PI, [2,2])
207
+ expect(v.dtype).to eq(:float64)
208
+
209
+ ans = [1.0, 1.7138642072677612, 2.4277284145355225, 3.1415927410125732]
210
+
211
+ expect(v[0,0]).to be_within(0.000001).of(ans[0])
212
+ expect(v[0,1]).to be_within(0.000001).of(ans[1])
213
+ expect(v[1,0]).to be_within(0.000001).of(ans[2])
214
+ expect(v[1,1]).to be_within(0.000001).of(ans[3])
215
+ end
216
+ end
217
+
218
+ context "::logspace" do
219
+ it "creates a logarithmically spaced vector" do
220
+ v = NMatrix.logspace(1, 2, 10)
221
+
222
+ expect(v.shape.length).to eq(1)
223
+
224
+ #Unit test taken from Matlab R2015b output of logspace(1,2,10)
225
+ ans = [10.0000, 12.9155, 16.6810, 21.5443, 27.8256, 35.9381, 46.4159, 59.9484, 77.4264, 100.0000]
226
+
227
+ expect(v[0].round(4)).to be_within(0.000001).of(ans[0])
228
+ expect(v[1].round(4)).to be_within(0.000001).of(ans[1])
229
+ expect(v[2].round(4)).to be_within(0.000001).of(ans[2])
230
+ expect(v[3].round(4)).to be_within(0.000001).of(ans[3])
231
+ expect(v[4].round(4)).to be_within(0.000001).of(ans[4])
232
+ expect(v[5].round(4)).to be_within(0.000001).of(ans[5])
233
+ expect(v[6].round(4)).to be_within(0.000001).of(ans[6])
234
+ expect(v[7].round(4)).to be_within(0.000001).of(ans[7])
235
+ expect(v[8].round(4)).to be_within(0.000001).of(ans[8])
236
+ expect(v[9].round(4)).to be_within(0.000001).of(ans[9])
237
+ end
238
+
239
+ it "creates a logarithmically spaced vector bounded by Math::PI if :pi is pre-supplied" do
240
+ v = NMatrix.logspace(1, :pi, 7)
241
+
242
+ #Unit test taken from Matlab R2015b output of logspace(1,pi,10)
243
+ ans = [10.0000, 8.2450, 6.7980, 5.6050, 4.6213, 3.8103, 3.1416]
244
+
245
+ expect(v[0].round(4)).to be_within(0.000001).of(ans[0])
246
+ expect(v[1].round(4)).to be_within(0.000001).of(ans[1])
247
+ expect(v[2].round(4)).to be_within(0.000001).of(ans[2])
248
+ expect(v[3].round(4)).to be_within(0.000001).of(ans[3])
249
+ expect(v[4].round(4)).to be_within(0.000001).of(ans[4])
250
+ expect(v[5].round(4)).to be_within(0.000001).of(ans[5])
251
+ expect(v[6].round(4)).to be_within(0.000001).of(ans[6])
252
+ end
253
+
254
+ it "creates a matrix of input shape with each entry logarithmically spaced in row major order" do
255
+ v = NMatrix.logspace(1, 2, [3,2])
256
+
257
+ ans = [10.0, 15.8489, 25.1189, 39.8107, 63.0957, 100.0]
258
+
259
+ expect(v[0,0].round(4)).to be_within(0.000001).of(ans[0])
260
+ expect(v[0,1].round(4)).to be_within(0.000001).of(ans[1])
261
+ expect(v[1,0].round(4)).to be_within(0.000001).of(ans[2])
262
+ expect(v[1,1].round(4)).to be_within(0.000001).of(ans[3])
263
+ expect(v[2,0].round(4)).to be_within(0.000001).of(ans[4])
264
+ expect(v[2,1].round(4)).to be_within(0.000001).of(ans[5])
265
+ end
266
+ end
126
267
 
127
268
  it "seq() creates a matrix of integers, sequentially" do
128
269
  m = NMatrix.seq(2) # 2x2 matrix.
@@ -136,7 +277,6 @@ describe NMatrix do
136
277
  end
137
278
  end
138
279
 
139
-
140
280
  it "indgen() creates a matrix of integers as well as seq()" do
141
281
  m = NMatrix.indgen(2) # 2x2 matrix.
142
282
  value = 0
@@ -189,19 +329,19 @@ describe NMatrix do
189
329
  it "column() returns a NMatrix" do
190
330
  m = NMatrix.random(3)
191
331
 
192
- expect(m.column(2).is_a?(NMatrix)).to be_true
332
+ expect(m.column(2).is_a?(NMatrix)).to be true
193
333
  end
194
334
 
195
335
  it "row() returns a NMatrix" do
196
336
  m = NMatrix.random(3)
197
337
 
198
- expect(m.row(2).is_a?(NMatrix)).to be_true
338
+ expect(m.row(2).is_a?(NMatrix)).to be true
199
339
  end
200
340
 
201
341
  it "diagonals() creates an NMatrix" do
202
342
  arr = [1,2,3,4]
203
343
  m = NMatrix.diagonals(arr)
204
- expect(m.is_a?(NMatrix)).to be_true
344
+ expect(m.is_a?(NMatrix)).to be true
205
345
  end
206
346
 
207
347
  it "diagonals() contains the seeded values on the diagonal" do