nmatrix 0.0.3 → 0.0.4
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.
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +1 -1
- data/History.txt +68 -10
- data/LICENSE.txt +2 -2
- data/Manifest.txt +2 -0
- data/README.rdoc +90 -69
- data/Rakefile +18 -9
- data/ext/nmatrix/data/complex.h +7 -7
- data/ext/nmatrix/data/data.cpp +2 -7
- data/ext/nmatrix/data/data.h +7 -4
- data/ext/nmatrix/data/rational.h +2 -2
- data/ext/nmatrix/data/ruby_object.h +3 -10
- data/ext/nmatrix/extconf.rb +79 -54
- data/ext/nmatrix/new_extconf.rb +11 -12
- data/ext/nmatrix/nmatrix.cpp +94 -125
- data/ext/nmatrix/nmatrix.h +38 -17
- data/ext/nmatrix/ruby_constants.cpp +2 -15
- data/ext/nmatrix/ruby_constants.h +2 -14
- data/ext/nmatrix/storage/common.cpp +2 -2
- data/ext/nmatrix/storage/common.h +2 -2
- data/ext/nmatrix/storage/dense.cpp +206 -31
- data/ext/nmatrix/storage/dense.h +5 -2
- data/ext/nmatrix/storage/list.cpp +52 -4
- data/ext/nmatrix/storage/list.h +3 -2
- data/ext/nmatrix/storage/storage.cpp +6 -6
- data/ext/nmatrix/storage/storage.h +2 -2
- data/ext/nmatrix/storage/yale.cpp +202 -49
- data/ext/nmatrix/storage/yale.h +5 -4
- data/ext/nmatrix/ttable_helper.rb +108 -108
- data/ext/nmatrix/types.h +2 -15
- data/ext/nmatrix/util/io.cpp +2 -2
- data/ext/nmatrix/util/io.h +2 -2
- data/ext/nmatrix/util/lapack.h +2 -2
- data/ext/nmatrix/util/math.cpp +14 -14
- data/ext/nmatrix/util/math.h +2 -2
- data/ext/nmatrix/util/sl_list.cpp +2 -2
- data/ext/nmatrix/util/sl_list.h +2 -2
- data/ext/nmatrix/util/util.h +2 -2
- data/lib/nmatrix.rb +13 -35
- data/lib/nmatrix/blas.rb +182 -56
- data/lib/nmatrix/io/market.rb +38 -14
- data/lib/nmatrix/io/mat5_reader.rb +393 -278
- data/lib/nmatrix/io/mat_reader.rb +121 -107
- data/lib/nmatrix/lapack.rb +59 -14
- data/lib/nmatrix/monkeys.rb +32 -30
- data/lib/nmatrix/nmatrix.rb +204 -100
- data/lib/nmatrix/nvector.rb +166 -57
- data/lib/nmatrix/shortcuts.rb +364 -231
- data/lib/nmatrix/version.rb +8 -4
- data/nmatrix.gemspec +5 -3
- data/scripts/mac-brew-gcc.sh +1 -1
- data/spec/blas_spec.rb +80 -2
- data/spec/math_spec.rb +78 -32
- data/spec/nmatrix_list_spec.rb +55 -55
- data/spec/nmatrix_spec.rb +60 -117
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +214 -198
- data/spec/nvector_spec.rb +58 -2
- data/spec/shortcuts_spec.rb +156 -32
- data/spec/slice_spec.rb +229 -178
- data/spec/spec_helper.rb +2 -2
- metadata +71 -21
data/lib/nmatrix/nmatrix.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# = NMatrix
|
2
3
|
#
|
3
4
|
# A linear algebra library for scientific computation in Ruby.
|
@@ -8,8 +9,8 @@
|
|
8
9
|
#
|
9
10
|
# == Copyright Information
|
10
11
|
#
|
11
|
-
# SciRuby is Copyright (c) 2010 -
|
12
|
-
# NMatrix is Copyright (c)
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
# NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
13
14
|
#
|
14
15
|
# Please see LICENSE.txt for additional copyright notices.
|
15
16
|
#
|
@@ -24,20 +25,15 @@
|
|
24
25
|
#
|
25
26
|
# This file adds a few additional pieces of functionality (e.g., inspect,
|
26
27
|
# pretty_print).
|
27
|
-
|
28
|
-
############
|
29
|
-
# Requires #
|
30
|
-
############
|
28
|
+
#++
|
31
29
|
|
32
30
|
require_relative './shortcuts.rb'
|
33
|
-
|
34
|
-
#######################
|
35
|
-
# Classes and Modules #
|
36
|
-
#######################
|
31
|
+
require_relative './lapack.rb'
|
37
32
|
|
38
33
|
class NMatrix
|
39
|
-
|
40
|
-
|
34
|
+
# Read and write extensions for NMatrix. These are only loaded when needed.
|
35
|
+
#
|
36
|
+
module IO
|
41
37
|
module Matlab
|
42
38
|
class << self
|
43
39
|
def load_mat file_path
|
@@ -54,10 +50,9 @@ class NMatrix
|
|
54
50
|
autoload :Market, 'nmatrix/io/market'
|
55
51
|
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
if dim != 2 || (dim == 2 && shape[1] > 10) # FIXME: Come up with a better way of restricting the display
|
53
|
+
# TODO: Make this actually pretty.
|
54
|
+
def pretty_print(q = nil) #:nodoc:
|
55
|
+
if dim != 2 || (dim == 2 && shape[1] > 10) # FIXME: Come up with a better way of restricting the display
|
61
56
|
inspect
|
62
57
|
else
|
63
58
|
|
@@ -65,17 +60,17 @@ class NMatrix
|
|
65
60
|
ary = []
|
66
61
|
(0...shape[1]).each do |j|
|
67
62
|
o = begin
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
self[i, j]
|
64
|
+
rescue ArgumentError
|
65
|
+
nil
|
66
|
+
end
|
72
67
|
ary << (o.nil? ? 'nil' : o)
|
73
68
|
end
|
74
69
|
ary.inspect
|
75
70
|
end
|
76
71
|
|
77
72
|
if q.nil?
|
78
|
-
puts arr.join("\n")
|
73
|
+
puts "[" + arr.join("\n") + "]"
|
79
74
|
else
|
80
75
|
q.group(1, "", "\n") do
|
81
76
|
q.seplist(arr, lambda { q.text " " }, :each) { |v| q.text v.to_s }
|
@@ -83,21 +78,64 @@ class NMatrix
|
|
83
78
|
end
|
84
79
|
|
85
80
|
end
|
86
|
-
|
87
|
-
|
81
|
+
end
|
82
|
+
alias :pp :pretty_print
|
88
83
|
|
89
|
-
#
|
84
|
+
#
|
85
|
+
# call-seq:
|
86
|
+
# rows -> Integer
|
87
|
+
#
|
88
|
+
# This shortcut use #shape to return the number of rows (the first dimension)
|
89
|
+
# of the matrix.
|
90
|
+
#
|
90
91
|
def rows
|
91
92
|
shape[0]
|
92
93
|
end
|
93
|
-
|
94
|
+
|
95
|
+
#
|
96
|
+
# call-seq:
|
97
|
+
# cols -> Integer
|
98
|
+
#
|
99
|
+
# This shortcut use #shape to return the number of columns (the second
|
100
|
+
# dimension) of the matrix.
|
101
|
+
#
|
94
102
|
def cols
|
95
103
|
shape[1]
|
96
104
|
end
|
97
105
|
|
98
|
-
#
|
106
|
+
#
|
107
|
+
# call-seq:
|
108
|
+
# to_hash -> Hash
|
109
|
+
#
|
110
|
+
# Create a Ruby Hash from an NMatrix.
|
111
|
+
#
|
112
|
+
def to_hash
|
113
|
+
if stype == :yale
|
114
|
+
h = {}
|
115
|
+
each_stored_with_indices do |val,i,j|
|
116
|
+
next if val == 0 # Don't bother storing the diagonal zero values -- only non-zeros.
|
117
|
+
if h.has_key?(i)
|
118
|
+
h[i][j] = val
|
119
|
+
else
|
120
|
+
h[i] = {j => val}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
h
|
124
|
+
else # dense and list should use a C internal functions.
|
125
|
+
to_hash_c
|
126
|
+
end
|
127
|
+
end
|
128
|
+
alias :to_h :to_hash
|
129
|
+
|
130
|
+
#
|
131
|
+
# call-seq:
|
132
|
+
# invert! -> NMatrix
|
133
|
+
#
|
134
|
+
# Use LAPACK to calculate the inverse of the matrix (in-place). Only works on
|
135
|
+
# dense matrices.
|
99
136
|
#
|
100
137
|
# Note: If you don't have LAPACK, e.g., on a Mac, this may not work yet.
|
138
|
+
#
|
101
139
|
def invert!
|
102
140
|
# Get the pivot array; factor the matrix
|
103
141
|
pivot = self.getrf!
|
@@ -108,33 +146,64 @@ class NMatrix
|
|
108
146
|
self
|
109
147
|
end
|
110
148
|
|
111
|
-
#
|
149
|
+
#
|
150
|
+
# call-seq:
|
151
|
+
# invert -> NMatrix
|
152
|
+
#
|
153
|
+
# Make a copy of the matrix, then invert it (requires LAPACK).
|
154
|
+
#
|
155
|
+
# * *Returns* :
|
156
|
+
# - A dense NMatrix.
|
157
|
+
#
|
112
158
|
def invert
|
113
159
|
self.cast(:dense, self.dtype).invert!
|
114
160
|
end
|
115
|
-
|
116
161
|
alias :inverse :invert
|
117
162
|
|
118
|
-
#
|
163
|
+
#
|
164
|
+
# call-seq:
|
165
|
+
# getrf! -> NMatrix
|
166
|
+
#
|
167
|
+
# LU factorization of a general M-by-N matrix +A+ using partial pivoting with
|
168
|
+
# row interchanges. Only works in dense matrices.
|
169
|
+
#
|
170
|
+
# * *Returns* :
|
171
|
+
# - The IPIV vector. The L and U matrices are stored in A.
|
172
|
+
# * *Raises* :
|
173
|
+
# - +StorageTypeError+ -> ATLAS functions only work on dense matrices.
|
174
|
+
#
|
119
175
|
def getrf!
|
120
176
|
raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.stype == :dense
|
121
177
|
NMatrix::LAPACK::clapack_getrf(:row, self.shape[0], self.shape[1], self, self.shape[0])
|
122
178
|
end
|
123
179
|
|
124
|
-
# Calculate the determinant by way of LU decomposition. This is accomplished using
|
125
|
-
# clapack_getrf, and then by summing the diagonal elements. There is a risk of
|
126
|
-
# underflow/overflow.
|
127
180
|
#
|
128
|
-
#
|
129
|
-
#
|
181
|
+
# call-seq:
|
182
|
+
# det -> determinant
|
183
|
+
#
|
184
|
+
# Calculate the determinant by way of LU decomposition. This is accomplished
|
185
|
+
# using clapack_getrf, and then by summing the diagonal elements. There is a
|
186
|
+
# risk of underflow/overflow.
|
187
|
+
#
|
188
|
+
# There are probably also more efficient ways to calculate the determinant.
|
189
|
+
# This method requires making a copy of the matrix, since clapack_getrf
|
190
|
+
# modifies its input.
|
191
|
+
#
|
192
|
+
# For smaller matrices, you may be able to use +#det_exact+.
|
130
193
|
#
|
131
|
-
#
|
194
|
+
# This function is guaranteed to return the same type of data in the matrix
|
195
|
+
# upon which it is called.
|
196
|
+
# In other words, if you call it on a rational matrix, you'll get a rational
|
197
|
+
# number back.
|
132
198
|
#
|
133
|
-
#
|
134
|
-
#
|
199
|
+
# Integer matrices are converted to rational matrices for the purposes of
|
200
|
+
# performing the calculation, as xGETRF can't work on integer matrices.
|
201
|
+
#
|
202
|
+
# * *Returns* :
|
203
|
+
# - The determinant of the matrix. It's the same type as the matrix's dtype.
|
204
|
+
# * *Raises* :
|
205
|
+
# - +NotImplementedError+ -> Must be used in 2D matrices.
|
135
206
|
#
|
136
|
-
# Integer matrices are converted to rational matrices for the purposes of performing the calculation,
|
137
|
-
# as xGETRF can't work on integer matrices.
|
138
207
|
def det
|
139
208
|
raise(NotImplementedError, "determinant can be calculated only for 2D matrices") unless self.dim == 2
|
140
209
|
|
@@ -142,7 +211,8 @@ class NMatrix
|
|
142
211
|
new_dtype = [:byte,:int8,:int16,:int32,:int64].include?(self.dtype) ? :rational128 : self.dtype
|
143
212
|
copy = self.cast(:dense, new_dtype)
|
144
213
|
|
145
|
-
# Need to know the number of permutations. We'll add up the diagonals of
|
214
|
+
# Need to know the number of permutations. We'll add up the diagonals of
|
215
|
+
# the factorized matrix.
|
146
216
|
pivot = copy.getrf!
|
147
217
|
|
148
218
|
prod = pivot.size % 2 == 1 ? -1 : 1 # odd permutations => negative
|
@@ -154,72 +224,106 @@ class NMatrix
|
|
154
224
|
new_dtype != self.dtype ? prod.to_i : prod
|
155
225
|
end
|
156
226
|
|
227
|
+
#
|
228
|
+
# call-seq:
|
229
|
+
# complex_conjugate -> NMatrix
|
230
|
+
# complex_conjugate(new_stype) -> NMatrix
|
231
|
+
#
|
232
|
+
# Get the complex conjugate of this matrix. See also complex_conjugate! for
|
233
|
+
# an in-place operation (provided the dtype is already +:complex64+ or
|
234
|
+
# +:complex128+).
|
235
|
+
#
|
236
|
+
# Doesn't work on list matrices, but you can optionally pass in the stype you
|
237
|
+
# want to cast to if you're dealing with a list matrix.
|
238
|
+
#
|
239
|
+
# * *Arguments* :
|
240
|
+
# - +new_stype+ -> stype for the new matrix.
|
241
|
+
# * *Returns* :
|
242
|
+
# - If the original NMatrix isn't complex, the result is a +:complex128+ NMatrix. Otherwise, it's the original dtype.
|
243
|
+
#
|
244
|
+
def complex_conjugate(new_stype = self.stype)
|
245
|
+
self.cast(new_stype, NMatrix::upcast(dtype, :complex64)).complex_conjugate!
|
246
|
+
end
|
247
|
+
|
248
|
+
#
|
249
|
+
# call-seq:
|
250
|
+
# conjugate_transpose -> NMatrix
|
251
|
+
#
|
252
|
+
# Calculate the conjugate transpose of a matrix. If your dtype is already
|
253
|
+
# complex, this should only require one copy (for the transpose).
|
254
|
+
#
|
255
|
+
# * *Returns* :
|
256
|
+
# - The conjugate transpose of the matrix as a copy.
|
257
|
+
#
|
258
|
+
def conjugate_transpose
|
259
|
+
self.transpose.complex_conjugate!
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# call-seq:
|
264
|
+
# hermitian? -> Boolean
|
265
|
+
#
|
266
|
+
# A hermitian matrix is a complex square matrix that is equal to its
|
267
|
+
# conjugate transpose. (http://en.wikipedia.org/wiki/Hermitian_matrix)
|
268
|
+
#
|
269
|
+
# * *Returns* :
|
270
|
+
# - True if +self+ is a hermitian matrix, nil otherwise.
|
271
|
+
#
|
272
|
+
def hermitian?
|
273
|
+
return false if self.dim != 2 or self.shape[0] != self.shape[1]
|
274
|
+
|
275
|
+
if [:complex64, :complex128].include?(self.dtype)
|
276
|
+
# TODO: Write much faster Hermitian test in C
|
277
|
+
self.eql?(self.conjugate_transpose)
|
278
|
+
else
|
279
|
+
symmetric?
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def inspect #:nodoc:
|
284
|
+
original_inspect = super()
|
285
|
+
original_inspect = original_inspect[0...original_inspect.size-1]
|
286
|
+
original_inspect + " " + inspect_helper.join(" ") + ">"
|
287
|
+
end
|
288
|
+
|
289
|
+
def __yale_ary__to_s(sym) #:nodoc:
|
290
|
+
ary = self.send("__yale_#{sym.to_s}__".to_sym)
|
157
291
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
def inspect
|
186
|
-
original_inspect = super()
|
187
|
-
original_inspect = original_inspect[0...original_inspect.size-1]
|
188
|
-
original_inspect + inspect_helper.join(" ") + ">"
|
189
|
-
end
|
190
|
-
|
191
|
-
def __yale_ary__to_s(sym)
|
192
|
-
ary = self.send("__yale_#{sym.to_s}__".to_sym)
|
193
|
-
|
194
|
-
'[' + ary.collect { |a| a ? a : 'nil'}.join(',') + ']'
|
195
|
-
end
|
196
|
-
|
197
|
-
class << self
|
198
|
-
def load_file(file_path)
|
199
|
-
NMatrix::IO::Mat5Reader.new(File.open(file_path, 'rb')).to_ruby
|
200
|
-
end
|
201
|
-
|
202
|
-
end
|
203
|
-
|
204
|
-
protected
|
205
|
-
def inspect_helper
|
206
|
-
ary = []
|
207
|
-
ary << "shape:[#{shape.join(',')}]" << "dtype:#{dtype}" << "stype:#{stype}"
|
208
|
-
|
209
|
-
if stype == :yale
|
210
|
-
ary << "capacity:#{capacity}"
|
292
|
+
'[' + ary.collect { |a| a ? a : 'nil'}.join(',') + ']'
|
293
|
+
end
|
294
|
+
|
295
|
+
class << self
|
296
|
+
#
|
297
|
+
# call-seq:
|
298
|
+
# load_file(path) -> Mat5Reader
|
299
|
+
#
|
300
|
+
# * *Arguments* :
|
301
|
+
# - +path+ -> The path to a version 5 .mat file.
|
302
|
+
# * *Returns* :
|
303
|
+
# - A Mat5Reader object.
|
304
|
+
#
|
305
|
+
def load_file(file_path)
|
306
|
+
NMatrix::IO::Mat5Reader.new(File.open(file_path, 'rb')).to_ruby
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
protected
|
311
|
+
def inspect_helper #:nodoc:
|
312
|
+
ary = []
|
313
|
+
ary << "shape:[#{shape.join(',')}]" << "dtype:#{dtype}" << "stype:#{stype}"
|
314
|
+
|
315
|
+
if stype == :yale
|
316
|
+
ary << "capacity:#{capacity}"
|
211
317
|
|
212
318
|
# These are enabled by the DEBUG_YALE compiler flag in extconf.rb.
|
213
319
|
if respond_to?(:__yale_a__)
|
214
320
|
ary << "ija:#{__yale_ary__to_s(:ija)}" << "ia:#{__yale_ary__to_s(:ia)}" <<
|
215
|
-
|
216
|
-
|
321
|
+
"ja:#{__yale_ary__to_s(:ja)}" << "a:#{__yale_ary__to_s(:a)}" << "d:#{__yale_ary__to_s(:d)}" <<
|
322
|
+
"lu:#{__yale_ary__to_s(:lu)}" << "yale_size:#{__yale_size__}"
|
217
323
|
end
|
218
324
|
|
219
|
-
|
325
|
+
end
|
220
326
|
|
221
|
-
|
222
|
-
|
327
|
+
ary
|
328
|
+
end
|
223
329
|
end
|
224
|
-
|
225
|
-
require_relative "./lapack.rb"
|
data/lib/nmatrix/nvector.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#--
|
1
2
|
# = NMatrix
|
2
3
|
#
|
3
4
|
# A linear algebra library for scientific computation in Ruby.
|
@@ -8,8 +9,8 @@
|
|
8
9
|
#
|
9
10
|
# == Copyright Information
|
10
11
|
#
|
11
|
-
# SciRuby is Copyright (c) 2010 -
|
12
|
-
# NMatrix is Copyright (c)
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
# NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
13
14
|
#
|
14
15
|
# Please see LICENSE.txt for additional copyright notices.
|
15
16
|
#
|
@@ -23,81 +24,189 @@
|
|
23
24
|
# == nmatrix.rb
|
24
25
|
#
|
25
26
|
# This file defines the NVector class.
|
26
|
-
|
27
|
-
############
|
28
|
-
# Requires #
|
29
|
-
############
|
30
|
-
|
31
|
-
|
32
|
-
#######################
|
33
|
-
# Classes and Modules #
|
34
|
-
#######################
|
27
|
+
#++
|
35
28
|
|
36
29
|
# This is a specific type of NMatrix in which only one dimension is not 1.
|
37
30
|
# Although it is stored as a dim-2, n x 1, matrix, it acts as a dim-1 vector
|
38
31
|
# of size n. If the @orientation flag is set to :row, it is stored as 1 x n
|
39
32
|
# instead of n x 1.
|
40
33
|
class NVector < NMatrix
|
41
|
-
|
42
|
-
|
34
|
+
#
|
35
|
+
# call-seq:
|
36
|
+
# new(length) -> NVector
|
37
|
+
# new(length, values) -> NVector
|
38
|
+
# new(length, values, dtype) -> NVector
|
39
|
+
#
|
40
|
+
# Creates a new NVector.
|
41
|
+
#
|
42
|
+
# * *Arguments* :
|
43
|
+
# - +length+ -> Size of the vector.
|
44
|
+
# - +values+ -> (optional) Initial values of the vector. Default is 0.
|
45
|
+
# - +dtype+ -> (optional) Default is a guess from the +values+.
|
46
|
+
# * *Returns* :
|
47
|
+
# -
|
48
|
+
#
|
49
|
+
def initialize(length, *args)
|
50
|
+
super(:dense, [length, 1], *args)
|
43
51
|
orientation
|
44
52
|
end
|
45
53
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
54
|
+
#
|
55
|
+
# call-seq:
|
56
|
+
# orientation -> Symbol
|
57
|
+
#
|
58
|
+
# Orientation defaults to column (e.g., [3,1] is a column of length 3). It
|
59
|
+
# may also be row, e.g., for [1,5].
|
60
|
+
#
|
61
|
+
def orientation
|
62
|
+
@orientation ||= :column
|
63
|
+
end
|
51
64
|
|
52
|
-
|
53
|
-
|
65
|
+
#
|
66
|
+
# call-seq:
|
67
|
+
# transpose -> NVector
|
68
|
+
#
|
69
|
+
# Returns a transposed copy of the vector.
|
70
|
+
#
|
71
|
+
# * *Returns* :
|
72
|
+
# - NVector containing the transposed vector.
|
73
|
+
#
|
74
|
+
def transpose
|
75
|
+
t = super()
|
54
76
|
t.flip!
|
55
|
-
|
77
|
+
end
|
56
78
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
79
|
+
#
|
80
|
+
# call-seq:
|
81
|
+
# transpose! -> NVector
|
82
|
+
#
|
83
|
+
# Transpose the vector in-place.
|
84
|
+
#
|
85
|
+
# * *Returns* :
|
86
|
+
# - NVector containing the transposed vector.
|
87
|
+
#
|
88
|
+
def transpose!
|
89
|
+
super()
|
90
|
+
self.flip!
|
91
|
+
end
|
61
92
|
|
62
|
-
|
63
|
-
|
93
|
+
#
|
94
|
+
# call-seq:
|
95
|
+
# multiply(m) ->
|
96
|
+
#
|
97
|
+
# ...
|
98
|
+
#
|
99
|
+
# * *Arguments* :
|
100
|
+
# - ++ ->
|
101
|
+
# * *Returns* :
|
102
|
+
# -
|
103
|
+
#
|
104
|
+
def multiply(m)
|
105
|
+
t = super(m)
|
64
106
|
t.flip!
|
65
|
-
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# call-seq:
|
111
|
+
# multiply!(m) ->
|
112
|
+
#
|
113
|
+
# ...
|
114
|
+
#
|
115
|
+
# * *Arguments* :
|
116
|
+
# - ++ ->
|
117
|
+
# * *Returns* :
|
118
|
+
# -
|
119
|
+
#
|
120
|
+
def multiply!(m)
|
121
|
+
super().flip!
|
122
|
+
end
|
66
123
|
|
67
|
-
|
68
|
-
|
69
|
-
|
124
|
+
#
|
125
|
+
# call-seq:
|
126
|
+
# vector[index] -> element
|
127
|
+
# vector[range] -> NVector
|
128
|
+
#
|
129
|
+
# Retrieves an element or return a slice.
|
130
|
+
#
|
131
|
+
# Examples:
|
132
|
+
#
|
133
|
+
# u = NVector.new(3, [10, 20, 30])
|
134
|
+
# u[0] # => 10
|
135
|
+
# u[0] + u[1] # => 30
|
136
|
+
# u[0 .. 1].shape # => [2, 1]
|
137
|
+
#
|
138
|
+
def [](i)
|
139
|
+
case @orientation
|
140
|
+
when :column; super(i, 0)
|
141
|
+
when :row; super(0, i)
|
142
|
+
end
|
143
|
+
end
|
70
144
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
145
|
+
#
|
146
|
+
# call-seq:
|
147
|
+
# vector[index] = obj -> obj
|
148
|
+
#
|
149
|
+
# Stores +value+ at position +index+.
|
150
|
+
#
|
151
|
+
def []=(i, val)
|
152
|
+
case @orientation
|
153
|
+
when :column; super(i, 0, val)
|
154
|
+
when :row; super(0, i, val)
|
155
|
+
end
|
76
156
|
end
|
77
157
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
158
|
+
#
|
159
|
+
# call-seq:
|
160
|
+
# dim -> 1
|
161
|
+
#
|
162
|
+
# Returns the dimension of a vector, which is 1.
|
163
|
+
#
|
164
|
+
def dim; 1; end
|
165
|
+
|
166
|
+
# shorthand for the dominant shape component
|
167
|
+
def size
|
168
|
+
shape[0] > 1 ? shape[0] : shape[1]
|
169
|
+
end
|
84
170
|
|
85
|
-
|
171
|
+
# TODO: Make this actually pretty.
|
172
|
+
def pretty_print(q = nil) #:nodoc:
|
173
|
+
dim = @orientation == :row ? 1 : 0
|
86
174
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
175
|
+
arr = (0...shape[dim]).inject(Array.new){ |a, i| a << self[i] }
|
176
|
+
|
177
|
+
if q.nil?
|
178
|
+
puts "[" + arr.join("\n") + "]"
|
179
|
+
else
|
180
|
+
q.group(1, "", "\n") do
|
181
|
+
q.seplist(arr, lambda { q.text " " }, :each) { |v| q.text v.to_s }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def inspect #:nodoc:
|
187
|
+
original_inspect = super()
|
188
|
+
original_inspect = original_inspect[0...original_inspect.size-1]
|
189
|
+
original_inspect.gsub("@orientation=:#{self.orientation}", "orientation:#{self.orientation}") + ">"
|
190
|
+
end
|
93
191
|
|
94
192
|
protected
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
193
|
+
# def inspect_helper #:nodoc:
|
194
|
+
# x = (super() << "orientation:#{self.orientation}") #.gsub(" @orientation=:#{self.orientation}", "")
|
195
|
+
# binding.pry
|
196
|
+
# x
|
197
|
+
# end
|
198
|
+
|
199
|
+
#
|
200
|
+
# call-seq:
|
201
|
+
# flip_orientation! -> NVector
|
202
|
+
#
|
203
|
+
# Flip the orientation of the vector.
|
204
|
+
#
|
205
|
+
# * *Returns* :
|
206
|
+
# - NVector with orientation changed.
|
207
|
+
#
|
208
|
+
def flip_orientation!
|
209
|
+
returning(self) { @orientation = @orientation == :row ? :column : :row }
|
210
|
+
end
|
211
|
+
alias :flip! :flip_orientation!
|
103
212
|
end
|