nmatrix 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/ext/nmatrix/data/complex.h +20 -55
- data/ext/nmatrix/data/data.cpp +11 -44
- data/ext/nmatrix/data/data.h +174 -311
- data/ext/nmatrix/data/meta.h +1 -7
- data/ext/nmatrix/data/ruby_object.h +3 -85
- data/ext/nmatrix/extconf.rb +2 -73
- data/ext/nmatrix/math.cpp +170 -813
- data/ext/nmatrix/math/asum.h +2 -25
- data/ext/nmatrix/math/{inc.h → cblas_enums.h} +11 -22
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +2 -32
- data/ext/nmatrix/math/gemv.h +1 -35
- data/ext/nmatrix/math/getrf.h +21 -6
- data/ext/nmatrix/math/getrs.h +0 -8
- data/ext/nmatrix/math/imax.h +0 -22
- data/ext/nmatrix/math/long_dtype.h +0 -3
- data/ext/nmatrix/math/math.h +11 -337
- data/ext/nmatrix/math/nrm2.h +2 -23
- data/ext/nmatrix/math/rot.h +1 -25
- data/ext/nmatrix/math/rotg.h +4 -13
- data/ext/nmatrix/math/scal.h +0 -22
- data/ext/nmatrix/math/trsm.h +0 -55
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nmatrix.cpp +0 -14
- data/ext/nmatrix/nmatrix.h +92 -84
- data/ext/nmatrix/ruby_constants.cpp +0 -2
- data/ext/nmatrix/ruby_constants.h +0 -2
- data/ext/nmatrix/ruby_nmatrix.c +86 -45
- data/ext/nmatrix/storage/dense/dense.cpp +1 -7
- data/ext/nmatrix/storage/storage.h +0 -1
- data/ext/nmatrix/ttable_helper.rb +0 -6
- data/ext/nmatrix/util/io.cpp +1 -1
- data/lib/nmatrix.rb +1 -19
- data/lib/nmatrix/blas.rb +33 -11
- data/lib/nmatrix/io/market.rb +3 -3
- data/lib/nmatrix/lapack_core.rb +181 -0
- data/lib/nmatrix/lapack_plugin.rb +44 -0
- data/lib/nmatrix/math.rb +382 -131
- data/lib/nmatrix/monkeys.rb +2 -3
- data/lib/nmatrix/nmatrix.rb +166 -13
- data/lib/nmatrix/shortcuts.rb +72 -7
- data/lib/nmatrix/version.rb +2 -2
- data/spec/00_nmatrix_spec.rb +154 -5
- data/spec/02_slice_spec.rb +2 -6
- data/spec/03_nmatrix_monkeys_spec.rb +7 -1
- data/spec/blas_spec.rb +60 -33
- data/spec/homogeneous_spec.rb +10 -10
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/math_spec.rb +436 -52
- data/spec/shortcuts_spec.rb +28 -4
- data/spec/spec_helper.rb +14 -2
- data/spec/utm5940.mtx +83844 -0
- metadata +49 -76
- data/.gitignore +0 -27
- data/.rspec +0 -2
- data/.travis.yml +0 -15
- data/CONTRIBUTING.md +0 -82
- data/Gemfile +0 -2
- data/History.txt +0 -677
- data/LICENSE.txt +0 -23
- data/Manifest.txt +0 -92
- data/README.rdoc +0 -150
- data/Rakefile +0 -216
- data/ext/nmatrix/data/rational.h +0 -440
- data/ext/nmatrix/math/geev.h +0 -82
- data/ext/nmatrix/math/ger.h +0 -96
- data/ext/nmatrix/math/gesdd.h +0 -80
- data/ext/nmatrix/math/gesvd.h +0 -78
- data/ext/nmatrix/math/getf2.h +0 -86
- data/ext/nmatrix/math/getri.h +0 -108
- data/ext/nmatrix/math/potrs.h +0 -129
- data/ext/nmatrix/math/swap.h +0 -52
- data/lib/nmatrix/lapack.rb +0 -240
- data/nmatrix.gemspec +0 -55
- data/scripts/mac-brew-gcc.sh +0 -50
- data/scripts/mac-mavericks-brew-gcc.sh +0 -22
- data/spec/lapack_spec.rb +0 -459
data/lib/nmatrix/monkeys.rb
CHANGED
@@ -44,13 +44,12 @@ class Array
|
|
44
44
|
# instead of :float64) -- optional.
|
45
45
|
# <tt>stype</tt> :: Optional storage type (defaults to :dense)
|
46
46
|
def to_nm(shape = nil, dtype = nil, stype = :dense)
|
47
|
-
elements = self
|
47
|
+
elements = self.dup
|
48
48
|
|
49
49
|
guess_dtype = ->(type) {
|
50
50
|
case type
|
51
51
|
when Fixnum then :int64
|
52
52
|
when Float then :float64
|
53
|
-
when Rational then :rational128
|
54
53
|
when Complex then :complex128
|
55
54
|
end
|
56
55
|
}
|
@@ -75,7 +74,7 @@ class Array
|
|
75
74
|
}
|
76
75
|
|
77
76
|
unless shape
|
78
|
-
shape = guess_shape.call(
|
77
|
+
shape = guess_shape.call(elements)
|
79
78
|
elements.flatten!(shape.size - 1)
|
80
79
|
if elements.flatten != elements
|
81
80
|
dtype = :object
|
data/lib/nmatrix/nmatrix.rb
CHANGED
@@ -23,18 +23,33 @@
|
|
23
23
|
#
|
24
24
|
# == nmatrix.rb
|
25
25
|
#
|
26
|
-
# This file
|
26
|
+
# This file loads the C extension for NMatrix and all the ruby
|
27
|
+
# files and contains those core functionalities which can be
|
27
28
|
# implemented efficiently (or much more easily) in Ruby (e.g.,
|
28
29
|
# inspect, pretty_print, element-wise operations).
|
29
30
|
#++
|
30
31
|
|
31
|
-
|
32
|
+
# For some reason nmatrix.so ends up in a different place during gem build.
|
33
|
+
if File.exist?("lib/nmatrix/nmatrix.so") #|| File.exist?("lib/nmatrix/nmatrix.bundle")
|
34
|
+
# Development
|
35
|
+
require "nmatrix/nmatrix.so"
|
36
|
+
else
|
37
|
+
# Gem
|
38
|
+
require "nmatrix.so"
|
39
|
+
end
|
40
|
+
|
41
|
+
require_relative './io/mat_reader'
|
42
|
+
require_relative './io/mat5_reader'
|
43
|
+
require_relative './io/market'
|
44
|
+
require_relative './io/point_cloud'
|
45
|
+
|
46
|
+
require_relative './lapack_core.rb'
|
32
47
|
require_relative './yale_functions.rb'
|
33
48
|
require_relative './monkeys'
|
34
49
|
|
35
50
|
# NMatrix is a matrix class that supports both multidimensional arrays
|
36
51
|
# (`:dense` stype) and sparse storage (`:list` or `:yale` stypes) and 13 data
|
37
|
-
# types, including complex
|
52
|
+
# types, including complex numbers, various integer and
|
38
53
|
# floating-point sizes and ruby objects.
|
39
54
|
class NMatrix
|
40
55
|
# Read and write extensions for NMatrix.
|
@@ -90,6 +105,59 @@ class NMatrix
|
|
90
105
|
shape = [shape,shape] unless shape.is_a?(Array)
|
91
106
|
(0...shape.size).inject(1) { |x,i| x * shape[i] }
|
92
107
|
end
|
108
|
+
|
109
|
+
# Make N-D coordinate arrays for vectorized evaluations of
|
110
|
+
# N-D scalar/vector fields over N-D grids, given N
|
111
|
+
# coordinate arrays arrs. N > 1.
|
112
|
+
#
|
113
|
+
# call-seq:
|
114
|
+
# meshgrid(arrs) -> Array of NMatrix
|
115
|
+
# meshgrid(arrs, options) -> Array of NMatrix
|
116
|
+
#
|
117
|
+
# * *Arguments* :
|
118
|
+
# - +vectors+ -> Array of N coordinate arrays (Array or NMatrix), if any have more than one dimension they will be flatten
|
119
|
+
# - +options+ -> Hash with options (:sparse Boolean, false by default; :indexing Symbol, may be :ij or :xy, :xy by default)
|
120
|
+
# * *Returns* :
|
121
|
+
# - Array of N N-D NMatrixes
|
122
|
+
# * *Examples* :
|
123
|
+
# x, y = NMatrix::meshgrid([[1, [2, 3]], [4, 5]])
|
124
|
+
# x.to_a #<= [[1, 2, 3], [1, 2, 3]]
|
125
|
+
# y.to_a #<= [[4, 4, 4], [5, 5, 5]]
|
126
|
+
#
|
127
|
+
# * *Using* *options* :
|
128
|
+
#
|
129
|
+
# x, y = NMatrix::meshgrid([[[1, 2], 3], [4, 5]], sparse: true)
|
130
|
+
# x.to_a #<= [[1, 2, 3]]
|
131
|
+
# y.to_a #<= [[4], [5]]
|
132
|
+
#
|
133
|
+
# x, y = NMatrix::meshgrid([[1, 2, 3], [[4], 5]], indexing: :ij)
|
134
|
+
# x.to_a #<= [[1, 1], [2, 2], [3, 3]]
|
135
|
+
# y.to_a #<= [[4, 5], [4, 5], [4, 5]]
|
136
|
+
def meshgrid(vectors, options = {})
|
137
|
+
raise(ArgumentError, 'Expected at least 2 arrays.') if vectors.size < 2
|
138
|
+
options[:indexing] ||= :xy
|
139
|
+
raise(ArgumentError, 'Indexing must be :xy of :ij') unless [:ij, :xy].include? options[:indexing]
|
140
|
+
mats = vectors.map { |arr| arr.respond_to?(:flatten) ? arr.flatten : arr.to_flat_array }
|
141
|
+
mats[0], mats[1] = mats[1], mats[0] if options[:indexing] == :xy
|
142
|
+
new_dim = mats.size
|
143
|
+
lengths = mats.map(&:size)
|
144
|
+
result = mats.map.with_index do |matrix, axis|
|
145
|
+
if options[:sparse]
|
146
|
+
new_shape = Array.new(new_dim, 1)
|
147
|
+
new_shape[axis] = lengths[axis]
|
148
|
+
new_elements = matrix
|
149
|
+
else
|
150
|
+
before_axis = lengths[0...axis].reduce(:*)
|
151
|
+
after_axis = lengths[(axis+1)..-1].reduce(:*)
|
152
|
+
new_shape = lengths
|
153
|
+
new_elements = after_axis ? matrix.map{ |el| [el] * after_axis }.flatten : matrix
|
154
|
+
new_elements *= before_axis if before_axis
|
155
|
+
end
|
156
|
+
NMatrix.new(new_shape, new_elements)
|
157
|
+
end
|
158
|
+
result[0], result[1] = result[1], result[0] if options[:indexing] == :xy
|
159
|
+
result
|
160
|
+
end
|
93
161
|
end
|
94
162
|
|
95
163
|
# TODO: Make this actually pretty.
|
@@ -153,7 +221,7 @@ class NMatrix
|
|
153
221
|
# one. You can actually call this function with no arguments, in which case it functions like #clone.
|
154
222
|
#
|
155
223
|
# If your dtype is :object and you are converting from :dense to a sparse type, it is recommended that you
|
156
|
-
# provide a :default, as 0 may behave differently from its Float
|
224
|
+
# provide a :default, as 0 may behave differently from its Float or Complex equivalent. If no option
|
157
225
|
# is given, Fixnum 0 will be used.
|
158
226
|
def cast(*params)
|
159
227
|
if (params.size > 0 && params[0].is_a?(Hash))
|
@@ -200,6 +268,35 @@ class NMatrix
|
|
200
268
|
shape[1]
|
201
269
|
end
|
202
270
|
|
271
|
+
# Return the main diagonal or antidiagonal a matrix. Only works with 2D matrices.
|
272
|
+
#
|
273
|
+
# == Arguments
|
274
|
+
#
|
275
|
+
# * +main_diagonal+ - Defaults to true. If passed 'false', then will return the
|
276
|
+
# antidiagonal of the matrix.
|
277
|
+
#
|
278
|
+
# == References
|
279
|
+
#
|
280
|
+
# * http://en.wikipedia.org/wiki/Main_diagonal
|
281
|
+
def diagonal main_diagonal=true
|
282
|
+
diag_size = [cols, rows].min
|
283
|
+
diag = NMatrix.new [diag_size], dtype: dtype
|
284
|
+
|
285
|
+
if main_diagonal
|
286
|
+
0.upto(diag_size-1) do |i|
|
287
|
+
diag[i] = self[i,i]
|
288
|
+
end
|
289
|
+
else
|
290
|
+
row = 0
|
291
|
+
(diag_size-1).downto(0) do |col|
|
292
|
+
diag[row] = self[row,col]
|
293
|
+
row += 1
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
diag
|
298
|
+
end
|
299
|
+
|
203
300
|
#
|
204
301
|
# call-seq:
|
205
302
|
# to_hash -> Hash
|
@@ -249,6 +346,15 @@ class NMatrix
|
|
249
346
|
[:byte, :int8, :int16, :int32, :int64].include?(self.dtype)
|
250
347
|
end
|
251
348
|
|
349
|
+
# call-seq:
|
350
|
+
# float_dtype?() -> Boolean
|
351
|
+
#
|
352
|
+
# Checks if dtype is a floating point type
|
353
|
+
#
|
354
|
+
def float_dtype?
|
355
|
+
[:float32, :float64].include?(dtype)
|
356
|
+
end
|
357
|
+
|
252
358
|
##
|
253
359
|
# call-seq:
|
254
360
|
# complex_dtype?() -> Boolean
|
@@ -261,12 +367,12 @@ class NMatrix
|
|
261
367
|
|
262
368
|
##
|
263
369
|
# call-seq:
|
264
|
-
#
|
265
|
-
#
|
266
|
-
#
|
267
|
-
#
|
268
|
-
def
|
269
|
-
|
370
|
+
#
|
371
|
+
# object_dtype?() -> Boolean
|
372
|
+
#
|
373
|
+
# Checks if dtype is a ruby object
|
374
|
+
def object_dtype?
|
375
|
+
dtype == :object
|
270
376
|
end
|
271
377
|
|
272
378
|
|
@@ -832,13 +938,13 @@ class NMatrix
|
|
832
938
|
end
|
833
939
|
|
834
940
|
|
835
|
-
def respond_to?(method) #:nodoc:
|
941
|
+
def respond_to?(method, include_all = false) #:nodoc:
|
836
942
|
if [:shuffle, :shuffle!, :each_with_index, :sorted_indices, :binned_sorted_indices, :nrm2, :asum].include?(method.intern) # vector-only methods
|
837
943
|
return vector?
|
838
944
|
elsif [:each_layer, :layer].include?(method.intern) # 3-or-more dimensions only
|
839
945
|
return dim > 2
|
840
946
|
else
|
841
|
-
super
|
947
|
+
super
|
842
948
|
end
|
843
949
|
end
|
844
950
|
|
@@ -854,6 +960,22 @@ class NMatrix
|
|
854
960
|
return self.map_stored.inject(sym)
|
855
961
|
end
|
856
962
|
|
963
|
+
# Returns the index of the first occurence of the specified value. Returns
|
964
|
+
# an array containing the position of the value, nil in case the value is not found.
|
965
|
+
#
|
966
|
+
def index(value)
|
967
|
+
index = nil
|
968
|
+
|
969
|
+
self.each_with_indices do |yields|
|
970
|
+
if yields.first == value
|
971
|
+
yields.shift
|
972
|
+
index = yields
|
973
|
+
break
|
974
|
+
end
|
975
|
+
end
|
976
|
+
|
977
|
+
index
|
978
|
+
end
|
857
979
|
|
858
980
|
#
|
859
981
|
# call-seq:
|
@@ -870,6 +992,33 @@ class NMatrix
|
|
870
992
|
NMatrix.new(self.shape, opts)
|
871
993
|
end
|
872
994
|
|
995
|
+
#
|
996
|
+
# call-seq:
|
997
|
+
# repeat(count, axis) -> NMatrix
|
998
|
+
#
|
999
|
+
# * *Arguments* :
|
1000
|
+
# - +count+ -> how many times NMatrix should be repeated
|
1001
|
+
# - +axis+ -> index of axis along which NMatrix should be repeated
|
1002
|
+
# * *Returns* :
|
1003
|
+
# - NMatrix created by repeating the existing one along an axis
|
1004
|
+
# * *Examples* :
|
1005
|
+
# m = NMatrix.new([2, 2], [1, 2, 3, 4])
|
1006
|
+
# m.repeat(2, 0).to_a #<= [[1, 2], [3, 4], [1, 2], [3, 4]]
|
1007
|
+
# m.repeat(2, 1).to_a #<= [[1, 2, 1, 2], [3, 4, 3, 4]]
|
1008
|
+
def repeat(count, axis)
|
1009
|
+
raise(ArgumentError, 'Matrix should be repeated at least 2 times.') if count < 2
|
1010
|
+
new_shape = shape
|
1011
|
+
new_shape[axis] *= count
|
1012
|
+
new_matrix = NMatrix.new(new_shape)
|
1013
|
+
slice = new_shape.map { |axis_size| 0...axis_size }
|
1014
|
+
start = 0
|
1015
|
+
count.times do
|
1016
|
+
slice[axis] = start...(start += shape[axis])
|
1017
|
+
new_matrix[*slice] = self
|
1018
|
+
end
|
1019
|
+
new_matrix
|
1020
|
+
end
|
1021
|
+
|
873
1022
|
# This is how you write an individual element-wise operation function:
|
874
1023
|
#def __list_elementwise_add__ rhs
|
875
1024
|
# self.__list_map_merged_stored__(rhs){ |l,r| l+r }.cast(self.stype, NMatrix.upcast(self.dtype, rhs.dtype))
|
@@ -928,7 +1077,8 @@ protected
|
|
928
1077
|
end
|
929
1078
|
|
930
1079
|
|
931
|
-
#
|
1080
|
+
# This function assumes that the shapes of the two matrices have already
|
1081
|
+
# been tested and are the same.
|
932
1082
|
#
|
933
1083
|
# Called from inside NMatrix: nm_eqeq
|
934
1084
|
#
|
@@ -973,3 +1123,6 @@ end
|
|
973
1123
|
require_relative './shortcuts.rb'
|
974
1124
|
require_relative './math.rb'
|
975
1125
|
require_relative './enumerate.rb'
|
1126
|
+
|
1127
|
+
require_relative './version.rb'
|
1128
|
+
require_relative './blas.rb'
|
data/lib/nmatrix/shortcuts.rb
CHANGED
@@ -59,7 +59,6 @@ class NMatrix
|
|
59
59
|
#
|
60
60
|
# The default value for +dtype+ is guessed from the first parameter. For example:
|
61
61
|
# NMatrix[1.0, 2.0].dtype # => :float64
|
62
|
-
# NMatrix[1r, 2r].dtype # => :rational64
|
63
62
|
#
|
64
63
|
# But this is just a *guess*. If the other values can't be converted to
|
65
64
|
# this dtype, a +TypeError+ will be raised.
|
@@ -275,6 +274,76 @@ class NMatrix
|
|
275
274
|
alias :diag :diagonal
|
276
275
|
alias :diagonals :diagonal
|
277
276
|
|
277
|
+
# Generate a block-diagonal NMatrix from the supplied 2D square matrices.
|
278
|
+
#
|
279
|
+
# * *Arguments*
|
280
|
+
# - +*params+ -> An array that collects all arguments passed to the method. The method
|
281
|
+
# can receive any number of arguments. Optionally, the last entry of +params+ is
|
282
|
+
# a hash of options from NMatrix#initialize. All other entries of +params+ are
|
283
|
+
# the blocks of the desired block-diagonal matrix. Each such matrix block can be
|
284
|
+
# supplied as a square 2D NMatrix object, or alternatively as an array of arrays
|
285
|
+
# (with dimensions corresponding to a square matrix), or alternatively as a number.
|
286
|
+
# * *Returns*
|
287
|
+
# - NMatrix of block-diagonal form filled with specified matrices
|
288
|
+
# as the blocks along the diagonal.
|
289
|
+
#
|
290
|
+
# * *Example*
|
291
|
+
#
|
292
|
+
# a = NMatrix.new([2,2], [1,2,3,4])
|
293
|
+
# b = NMatrix.new([1,1], [123], dtype: :float64)
|
294
|
+
# c = Array.new(2) { [[10,10], [10,10]] }
|
295
|
+
# d = Array[[1,2,3], [4,5,6], [7,8,9]]
|
296
|
+
# m = NMatrix.block_diagonal(a, b, *c, d, 10.0, 11, dtype: :int64, stype: :yale)
|
297
|
+
# =>
|
298
|
+
# [
|
299
|
+
# [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
300
|
+
# [3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
301
|
+
# [0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
302
|
+
# [0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0]
|
303
|
+
# [0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0]
|
304
|
+
# [0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0]
|
305
|
+
# [0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0]
|
306
|
+
# [0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0]
|
307
|
+
# [0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0]
|
308
|
+
# [0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0]
|
309
|
+
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0]
|
310
|
+
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11]
|
311
|
+
# ]
|
312
|
+
#
|
313
|
+
def block_diagonal(*params)
|
314
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
315
|
+
|
316
|
+
params.each_index do |i|
|
317
|
+
params[i] = params[i].to_nm if params[i].is_a?(Array) # Convert Array to NMatrix
|
318
|
+
params[i] = NMatrix.new([1,1], [params[i]]) if params[i].is_a?(Numeric) # Convert number to NMatrix
|
319
|
+
end
|
320
|
+
|
321
|
+
block_sizes = [] #holds the size of each matrix block
|
322
|
+
params.each do |b|
|
323
|
+
unless b.is_a?(NMatrix)
|
324
|
+
raise(ArgumentError, "Only NMatrix or appropriate Array objects or single numbers allowed")
|
325
|
+
end
|
326
|
+
raise(ArgumentError, "Only 2D matrices or 2D arrays allowed") unless b.shape.size == 2
|
327
|
+
raise(ArgumentError, "Only square-shaped blocks allowed") unless b.shape[0] == b.shape[1]
|
328
|
+
block_sizes << b.shape[0]
|
329
|
+
end
|
330
|
+
|
331
|
+
block_diag_mat = NMatrix.zeros(block_sizes.sum, options)
|
332
|
+
(0...params.length).each do |n|
|
333
|
+
# First determine the size and position of the n'th block in the block-diagonal matrix
|
334
|
+
block_size = block_sizes[n]
|
335
|
+
block_pos = block_sizes[0...n].sum
|
336
|
+
# populate the n'th block in the block-diagonal matrix
|
337
|
+
(0...block_size).each do |i|
|
338
|
+
(0...block_size).each do |j|
|
339
|
+
block_diag_mat[block_pos+i,block_pos+j] = params[n][i,j]
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
return block_diag_mat
|
345
|
+
end
|
346
|
+
alias :block_diag :block_diagonal
|
278
347
|
|
279
348
|
#
|
280
349
|
# call-seq:
|
@@ -284,8 +353,7 @@ class NMatrix
|
|
284
353
|
# by +Random::rand+. The parameter is the dimension of the matrix.
|
285
354
|
#
|
286
355
|
# If you use an integer dtype, make sure to specify :scale as a parameter, or you'll
|
287
|
-
# only get a matrix of 0s.
|
288
|
-
# a rational matrix.
|
356
|
+
# only get a matrix of 0s.
|
289
357
|
#
|
290
358
|
# * *Arguments* :
|
291
359
|
# - +shape+ -> Array (or integer for square matrix) specifying the dimensions.
|
@@ -302,8 +370,6 @@ class NMatrix
|
|
302
370
|
def random(shape, opts={})
|
303
371
|
scale = opts.delete(:scale) || 1.0
|
304
372
|
|
305
|
-
raise(NotImplementedError, "does not support rational random number generation") if opts[:dtype].to_s =~ /^rational/
|
306
|
-
|
307
373
|
rng = Random.new
|
308
374
|
|
309
375
|
random_values = []
|
@@ -330,7 +396,6 @@ class NMatrix
|
|
330
396
|
# dindgen(shape) -> NMatrix of :float64
|
331
397
|
# cindgen(shape) -> NMatrix of :complex64
|
332
398
|
# zindgen(shape) -> NMatrix of :complex128
|
333
|
-
# rindgen(shape) -> NMatrix of :rational128
|
334
399
|
# rbindgen(shape) -> NMatrix of :object
|
335
400
|
#
|
336
401
|
# Creates a matrix filled with a sequence of integers starting at zero.
|
@@ -361,7 +426,7 @@ class NMatrix
|
|
361
426
|
|
362
427
|
{:bindgen => :byte, :indgen => :int64, :findgen => :float32, :dindgen => :float64,
|
363
428
|
:cindgen => :complex64, :zindgen => :complex128,
|
364
|
-
:
|
429
|
+
:rbindgen => :object}.each_pair do |meth, dtype|
|
365
430
|
define_method(meth) { |shape| NMatrix.seq(shape, :dtype => dtype) }
|
366
431
|
end
|
367
432
|
end
|
data/lib/nmatrix/version.rb
CHANGED
@@ -28,9 +28,9 @@ class NMatrix
|
|
28
28
|
# IO can still understand NMatrix::VERSION.
|
29
29
|
module VERSION #:nodoc:
|
30
30
|
MAJOR = 0
|
31
|
-
MINOR =
|
31
|
+
MINOR = 2
|
32
32
|
TINY = 0
|
33
|
-
#
|
33
|
+
#PRE = "a"
|
34
34
|
|
35
35
|
STRING = [MAJOR, MINOR, TINY].compact.join(".")
|
36
36
|
#STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
data/spec/00_nmatrix_spec.rb
CHANGED
@@ -478,13 +478,36 @@ describe 'NMatrix' do
|
|
478
478
|
context "#==" do
|
479
479
|
[:dense, :list, :yale].each do |left|
|
480
480
|
[:dense, :list, :yale].each do |right|
|
481
|
-
next if left == right
|
482
481
|
context ("#{left}?#{right}") do
|
483
|
-
it "
|
484
|
-
n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0
|
485
|
-
m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0
|
486
|
-
|
482
|
+
it "tests equality of two equal matrices" do
|
483
|
+
n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: left)
|
484
|
+
m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right)
|
485
|
+
|
486
|
+
expect(n==m).to eq(true)
|
487
|
+
end
|
488
|
+
|
489
|
+
it "tests equality of two unequal matrices" do
|
490
|
+
n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,1], stype: left)
|
491
|
+
m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right)
|
492
|
+
|
493
|
+
expect(n==m).to eq(false)
|
494
|
+
end
|
495
|
+
|
496
|
+
it "tests equality of matrices with different shapes" do
|
497
|
+
n = NMatrix.new([2,2], [1,2, 3,4], stype: left)
|
498
|
+
m = NMatrix.new([2,3], [1,2, 3,4, 5,6], stype: right)
|
499
|
+
x = NMatrix.new([1,4], [1,2, 3,4], stype: right)
|
500
|
+
|
501
|
+
expect{n==m}.to raise_error(ShapeError)
|
502
|
+
expect{n==x}.to raise_error(ShapeError)
|
487
503
|
end
|
504
|
+
|
505
|
+
it "tests equality of matrices with different dimension" do
|
506
|
+
n = NMatrix.new([2,1], [1,2], stype: left)
|
507
|
+
m = NMatrix.new([2], [1,2], stype: right)
|
508
|
+
|
509
|
+
expect{n==m}.to raise_error(ShapeError)
|
510
|
+
end if left != :yale && right != :yale # yale must have dimension 2
|
488
511
|
end
|
489
512
|
end
|
490
513
|
end
|
@@ -578,4 +601,130 @@ describe 'NMatrix' do
|
|
578
601
|
end
|
579
602
|
end
|
580
603
|
|
604
|
+
context "#index" do
|
605
|
+
it "returns index of first occurence of an element for a vector" do
|
606
|
+
n = NMatrix.new([5], [0,22,22,11,11])
|
607
|
+
|
608
|
+
expect(n.index(22)).to eq([1])
|
609
|
+
end
|
610
|
+
|
611
|
+
it "returns index of first occurence of an element for 2-D matrix" do
|
612
|
+
n = NMatrix.new([3,3], [23,11,23,
|
613
|
+
44, 2, 0,
|
614
|
+
33, 0, 32])
|
615
|
+
|
616
|
+
expect(n.index(0)).to eq([1,2])
|
617
|
+
end
|
618
|
+
|
619
|
+
it "returns index of first occerence of an element for N-D matrix" do
|
620
|
+
n = NMatrix.new([3,3,3], [23,11,23, 44, 2, 0, 33, 0, 32,
|
621
|
+
23,11,23, 44, 2, 0, 33, 0, 32,
|
622
|
+
23,11,23, 44, 2, 0, 33, 0, 32])
|
623
|
+
|
624
|
+
expect(n.index(44)).to eq([0,1,0])
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
context "#diagonal" do
|
629
|
+
ALL_DTYPES.each do |dtype|
|
630
|
+
before do
|
631
|
+
@square_matrix = NMatrix.new([3,3], [
|
632
|
+
23,11,23,
|
633
|
+
44, 2, 0,
|
634
|
+
33, 0, 32
|
635
|
+
], dtype: dtype
|
636
|
+
)
|
637
|
+
|
638
|
+
@rect_matrix = NMatrix.new([4,3], [
|
639
|
+
23,11,23,
|
640
|
+
44, 2, 0,
|
641
|
+
33, 0,32,
|
642
|
+
11,22,33
|
643
|
+
], dtype: dtype
|
644
|
+
)
|
645
|
+
end
|
646
|
+
|
647
|
+
it "returns main diagonal for square matrix" do
|
648
|
+
expect(@square_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32])
|
649
|
+
end
|
650
|
+
|
651
|
+
it "returns main diagonal for rectangular matrix" do
|
652
|
+
expect(@rect_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32])
|
653
|
+
end
|
654
|
+
|
655
|
+
it "returns anti-diagonal for square matrix" do
|
656
|
+
expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33])
|
657
|
+
end
|
658
|
+
|
659
|
+
it "returns anti-diagonal for rectangular matrix" do
|
660
|
+
expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33])
|
661
|
+
end
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
context "#repeat" do
|
666
|
+
before do
|
667
|
+
@sample_matrix = NMatrix.new([2, 2], [1, 2, 3, 4])
|
668
|
+
end
|
669
|
+
|
670
|
+
it "checks count argument" do
|
671
|
+
expect{@sample_matrix.repeat(1, 0)}.to raise_error(ArgumentError)
|
672
|
+
expect{@sample_matrix.repeat(-2, 0)}.to raise_error(ArgumentError)
|
673
|
+
end
|
674
|
+
|
675
|
+
it "returns repeated matrix" do
|
676
|
+
expect(@sample_matrix.repeat(2, 0)).to eq(NMatrix.new([4, 2], [1, 2, 3, 4, 1, 2, 3, 4]))
|
677
|
+
expect(@sample_matrix.repeat(2, 1)).to eq(NMatrix.new([2, 4], [1, 2, 1, 2, 3, 4, 3, 4]))
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
context "#meshgrid" do
|
682
|
+
before do
|
683
|
+
@x, @y, @z = [1, 2, 3], NMatrix.new([2, 1], [4, 5]), [6, 7]
|
684
|
+
@two_dim = NMatrix.new([2, 2], [1, 2, 3, 4])
|
685
|
+
@two_dim_array = [[4], [5]]
|
686
|
+
@expected_result = [NMatrix.new([2, 3], [1, 2, 3, 1, 2, 3]), NMatrix.new([2, 3], [4, 4, 4, 5, 5, 5])]
|
687
|
+
@expected_for_ij = [NMatrix.new([3, 2], [1, 1, 2, 2, 3, 3]), NMatrix.new([3, 2], [4, 5, 4, 5, 4, 5])]
|
688
|
+
@expected_for_sparse = [NMatrix.new([1, 3], [1, 2, 3]), NMatrix.new([2, 1], [4, 5])]
|
689
|
+
@expected_for_sparse_ij = [NMatrix.new([3, 1], [1, 2, 3]), NMatrix.new([1, 2], [4, 5])]
|
690
|
+
@expected_3dim = [NMatrix.new([1, 3, 1], [1, 2, 3]).repeat(2, 0).repeat(2, 2),
|
691
|
+
NMatrix.new([2, 1, 1], [4, 5]).repeat(3, 1).repeat(2, 2),
|
692
|
+
NMatrix.new([1, 1, 2], [6, 7]).repeat(2, 0).repeat(3, 1)]
|
693
|
+
@expected_3dim_sparse_ij = [NMatrix.new([3, 1, 1], [1, 2, 3]),
|
694
|
+
NMatrix.new([1, 2, 1], [4, 5]),
|
695
|
+
NMatrix.new([1, 1, 2], [6, 7])]
|
696
|
+
end
|
697
|
+
|
698
|
+
it "checks arrays count" do
|
699
|
+
expect{NMatrix.meshgrid([@x])}.to raise_error(ArgumentError)
|
700
|
+
expect{NMatrix.meshgrid([])}.to raise_error(ArgumentError)
|
701
|
+
end
|
702
|
+
|
703
|
+
it "flattens input arrays before use" do
|
704
|
+
expect(NMatrix.meshgrid([@two_dim, @two_dim_array])).to eq(NMatrix.meshgrid([@two_dim.to_flat_array, @two_dim_array.flatten]))
|
705
|
+
end
|
706
|
+
|
707
|
+
it "returns new NMatrixes" do
|
708
|
+
expect(NMatrix.meshgrid([@x, @y])).to eq(@expected_result)
|
709
|
+
end
|
710
|
+
|
711
|
+
it "has option :sparse" do
|
712
|
+
expect(NMatrix.meshgrid([@x, @y], sparse: true)).to eq(@expected_for_sparse)
|
713
|
+
end
|
714
|
+
|
715
|
+
it "has option :indexing" do
|
716
|
+
expect(NMatrix.meshgrid([@x, @y], indexing: :ij)).to eq(@expected_for_ij)
|
717
|
+
expect(NMatrix.meshgrid([@x, @y], indexing: :xy)).to eq(@expected_result)
|
718
|
+
expect{NMatrix.meshgrid([@x, @y], indexing: :not_ij_not_xy)}.to raise_error(ArgumentError)
|
719
|
+
end
|
720
|
+
|
721
|
+
it "works well with both options set" do
|
722
|
+
expect(NMatrix.meshgrid([@x, @y], sparse: true, indexing: :ij)).to eq(@expected_for_sparse_ij)
|
723
|
+
end
|
724
|
+
|
725
|
+
it "is able to take more than two arrays as arguments and works well with options" do
|
726
|
+
expect(NMatrix.meshgrid([@x, @y, @z])).to eq(@expected_3dim)
|
727
|
+
expect(NMatrix.meshgrid([@x, @y, @z], sparse: true, indexing: :ij)).to eq(@expected_3dim_sparse_ij)
|
728
|
+
end
|
729
|
+
end
|
581
730
|
end
|