nmatrix 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +5 -0
- data/History.txt +97 -0
- data/Manifest.txt +34 -7
- data/README.rdoc +13 -13
- data/Rakefile +36 -26
- data/ext/nmatrix/data/data.cpp +15 -2
- data/ext/nmatrix/data/data.h +4 -0
- data/ext/nmatrix/data/ruby_object.h +5 -14
- data/ext/nmatrix/extconf.rb +3 -2
- data/ext/nmatrix/{util/math.cpp → math.cpp} +296 -6
- data/ext/nmatrix/math/asum.h +143 -0
- data/ext/nmatrix/math/geev.h +82 -0
- data/ext/nmatrix/math/gemm.h +267 -0
- data/ext/nmatrix/math/gemv.h +208 -0
- data/ext/nmatrix/math/ger.h +96 -0
- data/ext/nmatrix/math/gesdd.h +80 -0
- data/ext/nmatrix/math/gesvd.h +78 -0
- data/ext/nmatrix/math/getf2.h +86 -0
- data/ext/nmatrix/math/getrf.h +240 -0
- data/ext/nmatrix/math/getri.h +107 -0
- data/ext/nmatrix/math/getrs.h +125 -0
- data/ext/nmatrix/math/idamax.h +86 -0
- data/ext/nmatrix/{util → math}/lapack.h +60 -356
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +52 -0
- data/ext/nmatrix/math/math.h +1154 -0
- data/ext/nmatrix/math/nrm2.h +181 -0
- data/ext/nmatrix/math/potrs.h +125 -0
- data/ext/nmatrix/math/rot.h +141 -0
- data/ext/nmatrix/math/rotg.h +115 -0
- data/ext/nmatrix/math/scal.h +73 -0
- data/ext/nmatrix/math/swap.h +73 -0
- data/ext/nmatrix/math/trsm.h +383 -0
- data/ext/nmatrix/nmatrix.cpp +176 -152
- data/ext/nmatrix/nmatrix.h +1 -2
- data/ext/nmatrix/ruby_constants.cpp +9 -4
- data/ext/nmatrix/ruby_constants.h +1 -0
- data/ext/nmatrix/storage/dense.cpp +57 -41
- data/ext/nmatrix/storage/list.cpp +52 -50
- data/ext/nmatrix/storage/storage.cpp +59 -43
- data/ext/nmatrix/storage/yale.cpp +352 -333
- data/ext/nmatrix/storage/yale.h +4 -0
- data/lib/nmatrix.rb +2 -2
- data/lib/nmatrix/blas.rb +4 -4
- data/lib/nmatrix/enumerate.rb +241 -0
- data/lib/nmatrix/lapack.rb +54 -1
- data/lib/nmatrix/math.rb +462 -0
- data/lib/nmatrix/nmatrix.rb +210 -486
- data/lib/nmatrix/nvector.rb +0 -62
- data/lib/nmatrix/rspec.rb +75 -0
- data/lib/nmatrix/shortcuts.rb +136 -108
- data/lib/nmatrix/version.rb +1 -1
- data/spec/blas_spec.rb +20 -12
- data/spec/elementwise_spec.rb +22 -13
- data/spec/io_spec.rb +1 -0
- data/spec/lapack_spec.rb +197 -0
- data/spec/nmatrix_spec.rb +39 -38
- data/spec/nvector_spec.rb +3 -9
- data/spec/rspec_monkeys.rb +29 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +14 -16
- data/spec/slice_spec.rb +242 -186
- data/spec/spec_helper.rb +19 -0
- metadata +33 -5
- data/ext/nmatrix/util/math.h +0 -2612
data/lib/nmatrix/nvector.rb
CHANGED
@@ -185,68 +185,6 @@ class NVector < NMatrix
|
|
185
185
|
end
|
186
186
|
alias :norm2 :nrm2
|
187
187
|
|
188
|
-
#
|
189
|
-
# call-seq:
|
190
|
-
# to_a -> Array
|
191
|
-
#
|
192
|
-
# Converts the NVector to a regular Ruby Array.
|
193
|
-
def to_a
|
194
|
-
if self.stype == :dense
|
195
|
-
ary = Array.new(size)
|
196
|
-
self.each.with_index { |v,idx| ary[idx] = v }
|
197
|
-
else
|
198
|
-
begin
|
199
|
-
ary = Array.new(size, self[0] - self[0]) # Fill the Array with 0s of the appropriate class
|
200
|
-
rescue NoMethodError # handle Ruby Object arrays that might have nils instead of 0s
|
201
|
-
ary = Array.new(size)
|
202
|
-
end
|
203
|
-
self.each_stored_with_index { |v,idx| ary[idx] = v }
|
204
|
-
end
|
205
|
-
ary
|
206
|
-
end
|
207
|
-
|
208
|
-
#
|
209
|
-
# call-seq:
|
210
|
-
# each_stored_with_index -> Enumerator
|
211
|
-
#
|
212
|
-
# Allow iteration across an NVector's stored values. See also NMatrix#each_stored_with_indices
|
213
|
-
#
|
214
|
-
def each_stored_with_index(&block)
|
215
|
-
return enum_for(:each_stored_with_index) unless block_given?
|
216
|
-
self.each_stored_with_indices do |v, i, j|
|
217
|
-
shape[0] == 1 ? yield(v,j) : yield(v,i)
|
218
|
-
end
|
219
|
-
self
|
220
|
-
end
|
221
|
-
|
222
|
-
#
|
223
|
-
# call-seq:
|
224
|
-
# shuffle! -> ...
|
225
|
-
# shuffle!(random: rng) -> ...
|
226
|
-
#
|
227
|
-
# Re-arranges the contents of an NVector.
|
228
|
-
#
|
229
|
-
# TODO: Write more efficient version for Yale, list.
|
230
|
-
def shuffle!(*args)
|
231
|
-
ary = self.to_a
|
232
|
-
ary.shuffle!(*args)
|
233
|
-
ary.each.with_index { |v,idx| self[idx] = v }
|
234
|
-
self
|
235
|
-
end
|
236
|
-
|
237
|
-
|
238
|
-
#
|
239
|
-
# call-seq:
|
240
|
-
# shuffle -> ...
|
241
|
-
# shuffle(rng) -> ...
|
242
|
-
#
|
243
|
-
# Re-arranges the contents of an NVector.
|
244
|
-
#
|
245
|
-
# TODO: Write more efficient version for Yale, list.
|
246
|
-
def shuffle(*args)
|
247
|
-
t = self.clone
|
248
|
-
t.shuffle!(*args)
|
249
|
-
end
|
250
188
|
|
251
189
|
#
|
252
190
|
# call-seq:
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# = NMatrix
|
2
|
+
#
|
3
|
+
# A linear algebra library for scientific computation in Ruby.
|
4
|
+
# NMatrix is part of SciRuby.
|
5
|
+
#
|
6
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
7
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
8
|
+
#
|
9
|
+
# == Copyright Information
|
10
|
+
#
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
|
12
|
+
# NMatrix is Copyright (c) 2012, Ruby Science Foundation
|
13
|
+
#
|
14
|
+
# Please see LICENSE.txt for additional copyright notices.
|
15
|
+
#
|
16
|
+
# == Contributing
|
17
|
+
#
|
18
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
19
|
+
# our Contributor Agreement:
|
20
|
+
#
|
21
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
22
|
+
#
|
23
|
+
# == rspec.rb
|
24
|
+
#
|
25
|
+
# Monkey patches for RSpec improving its ability to work well with
|
26
|
+
# NMatrix (particularly #be_within).
|
27
|
+
#
|
28
|
+
|
29
|
+
require 'rspec'
|
30
|
+
|
31
|
+
# Amend RSpec to allow #be_within for matrices.
|
32
|
+
module RSpec::Matchers::BuiltIn #:nodoc:
|
33
|
+
class BeWithin
|
34
|
+
|
35
|
+
def of(expected)
|
36
|
+
@expected = expected
|
37
|
+
@unit = ''
|
38
|
+
if expected.is_a?(NMatrix)
|
39
|
+
@tolerance = if @delta.is_a?(NMatrix)
|
40
|
+
@delta.abs
|
41
|
+
elsif @delta.is_a?(Array)
|
42
|
+
NMatrix.new(:dense, expected.shape, @delta, :object).abs.cast(:dtype => expected.abs_dtype)
|
43
|
+
else
|
44
|
+
(NMatrix.ones_like(expected) * @delta).abs
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@tolerance = @delta
|
48
|
+
end
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def percent_of(expected)
|
54
|
+
@expected = expected
|
55
|
+
@unit = '%'
|
56
|
+
@tolerance = @expected.abs * @delta / 100.0 # <- only change is to reverse abs and @delta
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def matches?(actual)
|
61
|
+
@actual = actual
|
62
|
+
raise needs_expected unless defined? @expected
|
63
|
+
raise needs_subtractable unless @actual.respond_to? :-
|
64
|
+
res = (@actual - @expected).abs <= @tolerance
|
65
|
+
|
66
|
+
#if res.is_a?(NMatrix)
|
67
|
+
# require 'pry'
|
68
|
+
# binding.pry
|
69
|
+
#end
|
70
|
+
|
71
|
+
res.is_a?(NMatrix) ? !res.any? { |x| !x } : res
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
data/lib/nmatrix/shortcuts.rb
CHANGED
@@ -34,7 +34,76 @@
|
|
34
34
|
|
35
35
|
class NMatrix
|
36
36
|
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# call-seq:
|
41
|
+
# dense? -> true or false
|
42
|
+
# list? -> true or false
|
43
|
+
# yale? -> true or false
|
44
|
+
#
|
45
|
+
# Shortcut functions for quickly determining a matrix's stype.
|
46
|
+
#
|
47
|
+
def dense?; return stype == :dense; end
|
48
|
+
def yale?; return stype == :yale; end
|
49
|
+
def list?; return stype == :list; end
|
50
|
+
|
51
|
+
|
37
52
|
class << self
|
53
|
+
#
|
54
|
+
# call-seq:
|
55
|
+
# NMatrix[array-of-arrays, dtype = nil]
|
56
|
+
#
|
57
|
+
# You can use the old +N+ constant in this way:
|
58
|
+
# N = NMatrix
|
59
|
+
# N[1, 2, 3]
|
60
|
+
# NMatrix needs to have a succinct way to create a matrix by specifying the
|
61
|
+
# components directly. This is very useful for using it as an advanced
|
62
|
+
# calculator, it is useful for learning how to use, for testing language
|
63
|
+
# features and for developing algorithms.
|
64
|
+
#
|
65
|
+
# The NMatrix::[] method provides a way to create a matrix in a way that is compact and
|
66
|
+
# natural. The components are specified using Ruby array syntax. Optionally,
|
67
|
+
# one can specify a dtype as the last parameter (default is :float64).
|
68
|
+
#
|
69
|
+
# Examples:
|
70
|
+
#
|
71
|
+
# a = NMatrix[ 1,2,3,4 ] => 1.0 2.0 3.0 4.0
|
72
|
+
#
|
73
|
+
# a = NMatrix[ 1,2,3,4, :int32 ] => 1 2 3 4
|
74
|
+
#
|
75
|
+
# a = NMatrix[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
|
76
|
+
# 3.0 4.0 5.0
|
77
|
+
#
|
78
|
+
# SYNTAX COMPARISON:
|
79
|
+
#
|
80
|
+
# MATLAB: a = [ [1 2 3] ; [4 5 6] ] or [ 1 2 3 ; 4 5 6 ]
|
81
|
+
# IDL: a = [ [1,2,3] , [4,5,6] ]
|
82
|
+
# NumPy: a = array( [1,2,3], [4,5,6] )
|
83
|
+
#
|
84
|
+
# SciRuby: a = NMatrix[ [1,2,3], [4,5,6] ]
|
85
|
+
# Ruby array: a = [ [1,2,3], [4,5,6] ]
|
86
|
+
#
|
87
|
+
def [](*params)
|
88
|
+
dtype = params.last.is_a?(Symbol) ? params.pop : nil
|
89
|
+
|
90
|
+
# First find the dimensions of the array.
|
91
|
+
i = 0
|
92
|
+
shape = []
|
93
|
+
row = params
|
94
|
+
while row.is_a?(Array)
|
95
|
+
shape[i] = row.length
|
96
|
+
row = row[0]
|
97
|
+
i += 1
|
98
|
+
end
|
99
|
+
|
100
|
+
# A row vector should be stored as 1xN, not N
|
101
|
+
#shape.unshift(1) if shape.size == 1
|
102
|
+
|
103
|
+
# Then flatten the array.
|
104
|
+
NMatrix.new(shape, params.flatten, dtype)
|
105
|
+
end
|
106
|
+
|
38
107
|
#
|
39
108
|
# call-seq:
|
40
109
|
# zeros(size) -> NMatrix
|
@@ -97,6 +166,34 @@ class NMatrix
|
|
97
166
|
NMatrix.new(dim, 1, dtype)
|
98
167
|
end
|
99
168
|
|
169
|
+
##
|
170
|
+
# call-seq:
|
171
|
+
# ones_like(nm) -> NMatrix
|
172
|
+
#
|
173
|
+
# Creates a new matrix of ones with the same dtype and shape as the
|
174
|
+
# provided matrix.
|
175
|
+
#
|
176
|
+
# @param [NMatrix] nm the nmatrix whose dtype and shape will be used
|
177
|
+
# @return [NMatrix] a new nmatrix filled with ones.
|
178
|
+
#
|
179
|
+
def ones_like(nm)
|
180
|
+
NMatrix.ones(nm.shape, nm.dtype)
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# call-seq:
|
185
|
+
# zeros_like(nm) -> NMatrix
|
186
|
+
#
|
187
|
+
# Creates a new matrix of zeros with the same stype, dtype, and shape
|
188
|
+
# as the provided matrix.
|
189
|
+
#
|
190
|
+
# @param [NMatrix] nm the nmatrix whose stype, dtype, and shape will be used
|
191
|
+
# @return [NMatrix] a new nmatrix filled with zeros.
|
192
|
+
#
|
193
|
+
def zeros_like(nm)
|
194
|
+
NMatrix.zeros(nm.stype, nm.shape, nm.dtype)
|
195
|
+
end
|
196
|
+
|
100
197
|
#
|
101
198
|
# call-seq:
|
102
199
|
# eye(size) -> NMatrix
|
@@ -140,7 +237,6 @@ class NMatrix
|
|
140
237
|
m
|
141
238
|
end
|
142
239
|
alias :identity :eye
|
143
|
-
|
144
240
|
#
|
145
241
|
# call-seq:
|
146
242
|
# diagonals(array) -> NMatrix
|
@@ -324,75 +420,50 @@ as dimension."
|
|
324
420
|
end
|
325
421
|
|
326
422
|
end
|
423
|
+
end
|
327
424
|
|
328
|
-
|
329
|
-
# call-seq:
|
330
|
-
# column(column_number) -> NMatrix
|
331
|
-
# column(column_number, get_by) -> NMatrix
|
332
|
-
#
|
333
|
-
# Returns the column specified. Uses slicing by copy as default.
|
334
|
-
#
|
335
|
-
# * *Arguments* :
|
336
|
-
# - +column_number+ -> Integer.
|
337
|
-
# - +get_by+ -> Type of slicing to use, +:copy+ or +:reference+.
|
338
|
-
# * *Returns* :
|
339
|
-
# - A NMatrix representing the requested column as a column vector.
|
340
|
-
#
|
341
|
-
# Examples:
|
342
|
-
#
|
343
|
-
# m = NMatrix.new(2, [1, 4, 9, 14], :int32) # => 1 4
|
344
|
-
# 9 14
|
345
|
-
#
|
346
|
-
# m.column(1) # => 4
|
347
|
-
# 14
|
348
|
-
#
|
349
|
-
def column(column_number, get_by = :copy)
|
350
|
-
unless [:copy, :reference].include?(get_by)
|
351
|
-
raise ArgumentError, "column() 2nd parameter must be :copy or :reference"
|
352
|
-
end
|
353
|
-
|
354
|
-
if get_by == :copy
|
355
|
-
self.slice(0 ... self.shape[0], column_number)
|
356
|
-
else # by reference
|
357
|
-
self[0 ... self.shape[0], column_number]
|
358
|
-
end
|
359
|
-
end
|
425
|
+
module NVector
|
360
426
|
|
361
|
-
|
427
|
+
class << self
|
428
|
+
#
|
429
|
+
# call-seq:
|
430
|
+
# new(shape) -> NVector
|
431
|
+
# new(stype, shape) -> NVector
|
432
|
+
# new(shape, init) -> NVector
|
433
|
+
# new(:dense, shape, init) -> NVector
|
434
|
+
# new(:list, shape, init) -> NVector
|
435
|
+
# new(shape, init, dtype) -> NVector
|
436
|
+
# new(stype, shape, init, dtype) -> NVector
|
437
|
+
# new(stype, shape, dtype) -> NVector
|
438
|
+
#
|
439
|
+
# Creates a new NVector. See also NMatrix#initialize for a more detailed explanation of
|
440
|
+
# the arguments.
|
441
|
+
#
|
442
|
+
# * *Arguments* :
|
443
|
+
# - +stype+ -> (optional) Storage type of the vector (:list, :dense, :yale). Defaults to :dense.
|
444
|
+
# - +shape+ -> Shape of the vector. Accepts [n,1], [1,n], or n, where n is a Fixnum.
|
445
|
+
# - +init+ -> (optional) Yale: capacity; List: default value (0); Dense: initial value or values (uninitialized by default).
|
446
|
+
# - +dtype+ -> (optional if +init+ provided) Data type stored in the vector. For :dense and :list, can be inferred from +init+.
|
447
|
+
# * *Returns* :
|
448
|
+
# -
|
449
|
+
#
|
450
|
+
def new(*args)
|
451
|
+
stype = args[0].is_a?(Symbol) ? args.shift : :dense
|
452
|
+
shape = args[0].is_a?(Array) ? args.shift : [1,args.shift]
|
362
453
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
# row(row_number, get_by) -> NMatrix
|
367
|
-
#
|
368
|
-
# * *Arguments* :
|
369
|
-
# - +row_number+ -> Integer.
|
370
|
-
# - +get_by+ -> Type of slicing to use, +:copy+ or +:reference+.
|
371
|
-
# * *Returns* :
|
372
|
-
# - A NMatrix representing the requested row .
|
373
|
-
#
|
374
|
-
def row(row_number, get_by = :copy)
|
375
|
-
unless [:copy, :reference].include?(get_by)
|
376
|
-
raise ArgumentError, "row() 2nd parameter must be :copy or :reference"
|
377
|
-
end
|
454
|
+
if shape.size != 2 || !shape.include?(1) || shape == [1,1]
|
455
|
+
raise(ArgumentError, "shape must be a Fixnum or an Array of positive Fixnums where exactly one value is 1")
|
456
|
+
end
|
378
457
|
|
379
|
-
|
380
|
-
self.slice(row_number, 0 ... self.shape[1])
|
381
|
-
else # by reference
|
382
|
-
self[row_number, 0 ... self.shape[1]]
|
458
|
+
NMatrix.new(stype, shape, *args)
|
383
459
|
end
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
class NVector < NMatrix
|
388
460
|
|
389
|
-
class << self
|
390
461
|
#
|
391
462
|
# call-seq:
|
392
463
|
# zeros(size) -> NMatrix
|
393
464
|
# zeros(size, dtype) -> NMatrix
|
394
465
|
#
|
395
|
-
# Creates a new
|
466
|
+
# Creates a new vector of zeros with the dimensions supplied as
|
396
467
|
# parameters.
|
397
468
|
#
|
398
469
|
# * *Arguments* :
|
@@ -492,14 +563,10 @@ class NVector < NMatrix
|
|
492
563
|
# 1.0
|
493
564
|
# 2.0
|
494
565
|
#
|
495
|
-
def seq(
|
496
|
-
|
497
|
-
raise ArgumentError, "NVector::seq() only accepts integers as size."
|
498
|
-
end
|
566
|
+
def seq(size, dtype = :int64)
|
567
|
+
values = (0 ... size).to_a
|
499
568
|
|
500
|
-
|
501
|
-
|
502
|
-
NVector.new(n, values, dtype)
|
569
|
+
NVector.new(size, values, dtype)
|
503
570
|
end
|
504
571
|
|
505
572
|
#
|
@@ -645,15 +712,8 @@ class NVector < NMatrix
|
|
645
712
|
end
|
646
713
|
end
|
647
714
|
|
648
|
-
|
649
|
-
#
|
650
|
-
# calculator, it is useful for learning how to use, for testing language
|
651
|
-
# features and for developing algorithms.
|
652
|
-
#
|
653
|
-
# The N class provides a way to create a matrix in a way that is compact and
|
654
|
-
# natural. The components are specified using Ruby array syntax. Optionally,
|
655
|
-
# one can specify a dtype as the last parameter (default is :float64).
|
656
|
-
#
|
715
|
+
|
716
|
+
# Use this constant as you would use NMatrix[].
|
657
717
|
# Examples:
|
658
718
|
#
|
659
719
|
# a = N[ 1,2,3,4 ] => 1.0 2.0 3.0 4.0
|
@@ -663,36 +723,4 @@ end
|
|
663
723
|
# a = N[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
|
664
724
|
# 3.0 4.0 5.0
|
665
725
|
#
|
666
|
-
|
667
|
-
#
|
668
|
-
# MATLAB: a = [ [1 2 3] ; [4 5 6] ] or [ 1 2 3 ; 4 5 6 ]
|
669
|
-
# IDL: a = [ [1,2,3] , [4,5,6] ]
|
670
|
-
# NumPy: a = array( [1,2,3], [4,5,6] )
|
671
|
-
#
|
672
|
-
# SciRuby: a = N[ [1,2,3], [4,5,6] ]
|
673
|
-
# Ruby array: a = [ [1,2,3], [4,5,6] ]
|
674
|
-
#
|
675
|
-
class N
|
676
|
-
class << self
|
677
|
-
#
|
678
|
-
# call-seq:
|
679
|
-
# N[array-of-arrays, dtype = nil]
|
680
|
-
#
|
681
|
-
def [](*params)
|
682
|
-
dtype = params.last.is_a?(Symbol) ? params.pop : nil
|
683
|
-
|
684
|
-
# First find the dimensions of the array.
|
685
|
-
i = 0
|
686
|
-
dim = []
|
687
|
-
foo = params
|
688
|
-
while foo.is_a?(Array)
|
689
|
-
dim[i] = foo.length
|
690
|
-
foo = foo[0]
|
691
|
-
i += 1
|
692
|
-
end
|
693
|
-
|
694
|
-
# Then flatten the array.
|
695
|
-
NMatrix.new(dim, params.flatten, dtype)
|
696
|
-
end
|
697
|
-
end
|
698
|
-
end
|
726
|
+
N = NMatrix
|
data/lib/nmatrix/version.rb
CHANGED