nmatrix 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|