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.
Files changed (63) hide show
  1. data/.gitignore +3 -0
  2. data/CONTRIBUTING.md +66 -0
  3. data/Gemfile +1 -1
  4. data/History.txt +68 -10
  5. data/LICENSE.txt +2 -2
  6. data/Manifest.txt +2 -0
  7. data/README.rdoc +90 -69
  8. data/Rakefile +18 -9
  9. data/ext/nmatrix/data/complex.h +7 -7
  10. data/ext/nmatrix/data/data.cpp +2 -7
  11. data/ext/nmatrix/data/data.h +7 -4
  12. data/ext/nmatrix/data/rational.h +2 -2
  13. data/ext/nmatrix/data/ruby_object.h +3 -10
  14. data/ext/nmatrix/extconf.rb +79 -54
  15. data/ext/nmatrix/new_extconf.rb +11 -12
  16. data/ext/nmatrix/nmatrix.cpp +94 -125
  17. data/ext/nmatrix/nmatrix.h +38 -17
  18. data/ext/nmatrix/ruby_constants.cpp +2 -15
  19. data/ext/nmatrix/ruby_constants.h +2 -14
  20. data/ext/nmatrix/storage/common.cpp +2 -2
  21. data/ext/nmatrix/storage/common.h +2 -2
  22. data/ext/nmatrix/storage/dense.cpp +206 -31
  23. data/ext/nmatrix/storage/dense.h +5 -2
  24. data/ext/nmatrix/storage/list.cpp +52 -4
  25. data/ext/nmatrix/storage/list.h +3 -2
  26. data/ext/nmatrix/storage/storage.cpp +6 -6
  27. data/ext/nmatrix/storage/storage.h +2 -2
  28. data/ext/nmatrix/storage/yale.cpp +202 -49
  29. data/ext/nmatrix/storage/yale.h +5 -4
  30. data/ext/nmatrix/ttable_helper.rb +108 -108
  31. data/ext/nmatrix/types.h +2 -15
  32. data/ext/nmatrix/util/io.cpp +2 -2
  33. data/ext/nmatrix/util/io.h +2 -2
  34. data/ext/nmatrix/util/lapack.h +2 -2
  35. data/ext/nmatrix/util/math.cpp +14 -14
  36. data/ext/nmatrix/util/math.h +2 -2
  37. data/ext/nmatrix/util/sl_list.cpp +2 -2
  38. data/ext/nmatrix/util/sl_list.h +2 -2
  39. data/ext/nmatrix/util/util.h +2 -2
  40. data/lib/nmatrix.rb +13 -35
  41. data/lib/nmatrix/blas.rb +182 -56
  42. data/lib/nmatrix/io/market.rb +38 -14
  43. data/lib/nmatrix/io/mat5_reader.rb +393 -278
  44. data/lib/nmatrix/io/mat_reader.rb +121 -107
  45. data/lib/nmatrix/lapack.rb +59 -14
  46. data/lib/nmatrix/monkeys.rb +32 -30
  47. data/lib/nmatrix/nmatrix.rb +204 -100
  48. data/lib/nmatrix/nvector.rb +166 -57
  49. data/lib/nmatrix/shortcuts.rb +364 -231
  50. data/lib/nmatrix/version.rb +8 -4
  51. data/nmatrix.gemspec +5 -3
  52. data/scripts/mac-brew-gcc.sh +1 -1
  53. data/spec/blas_spec.rb +80 -2
  54. data/spec/math_spec.rb +78 -32
  55. data/spec/nmatrix_list_spec.rb +55 -55
  56. data/spec/nmatrix_spec.rb +60 -117
  57. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  58. data/spec/nmatrix_yale_spec.rb +214 -198
  59. data/spec/nvector_spec.rb +58 -2
  60. data/spec/shortcuts_spec.rb +156 -32
  61. data/spec/slice_spec.rb +229 -178
  62. data/spec/spec_helper.rb +2 -2
  63. metadata +71 -21
@@ -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 - 2012, Ruby Science Foundation
12
- # NMatrix is Copyright (c) 2012, Ruby Science Foundation
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
- # Read and write extensions for NMatrix. These are only loaded when needed.
40
- module IO
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
- # TODO: Make this actually pretty.
59
- def pretty_print(q = nil)
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
- self[i, j]
69
- rescue ArgumentError
70
- nil
71
- end
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
- end
87
- alias :pp :pretty_print
81
+ end
82
+ alias :pp :pretty_print
88
83
 
89
- # These shortcuts use #shape to return the number of rows and columns.
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
- # Use LAPACK to calculate the inverse of the matrix (in-place). Only works on dense matrices.
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
- # Make a copy of the matrix, then invert it (requires LAPACK). Returns a dense matrix.
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
- # Calls clapack_getrf and returns the pivot array (dense only).
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
- # There are probably also more efficient ways to calculate the determinant. This method
129
- # requires making a copy of the matrix, since clapack_getrf modifies its input.
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
- # For smaller matrices, you may be able to use det_exact.
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
- # This function is guaranteed to return the same type of data in the matrix upon which it is called.
134
- # In other words, if you call it on a rational matrix, you'll get a rational number back.
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 the factorized matrix.
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
- # Get the complex conjugate of this matrix. See also complex_conjugate! for
159
- # an in-place operation (provided the dtype is already :complex64 or
160
- # :complex128).
161
- #
162
- # Does not work on list matrices, but you can optionally pass in the type you
163
- # want to cast to if you're dealing with a list matrix.
164
- def complex_conjugate(new_stype = self.stype)
165
- self.cast(new_stype, NMatrix::upcast(dtype, :complex64)).complex_conjugate!
166
- end
167
-
168
- # Calculate the conjugate transpose of a matrix. If your dtype is already
169
- # complex, this should only require one copy (for the transpose).
170
- def conjugate_transpose
171
- self.transpose.complex_conjugate!
172
- end
173
-
174
- def hermitian?
175
- return false if self.dim != 2 or self.shape[0] != self.shape[1]
176
-
177
- if [:complex64, :complex128].include?(self.dtype)
178
- # TODO: Write much faster Hermitian test in C
179
- self.eql?(self.conjugate_transpose)
180
- else
181
- symmetric?
182
- end
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
- "ja:#{__yale_ary__to_s(:ja)}" << "a:#{__yale_ary__to_s(:a)}" << "d:#{__yale_ary__to_s(:d)}" <<
216
- "lu:#{__yale_ary__to_s(:lu)}" << "yale_size:#{__yale_size__}"
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
- end
325
+ end
220
326
 
221
- ary
222
- end
327
+ ary
328
+ end
223
329
  end
224
-
225
- require_relative "./lapack.rb"
@@ -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 - 2012, Ruby Science Foundation
12
- # NMatrix is Copyright (c) 2012, Ruby Science Foundation
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
- def initialize(length, *args)
42
- super(:dense, [length, 1], *args)
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
- # Orientation defaults to column (e.g., [3,1] is a column of length 3). It
47
- # may also be row, e.g., for [1,5].
48
- def orientation
49
- @orientation ||= :column
50
- end
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
- def transpose
53
- t = super()
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
- end
77
+ end
56
78
 
57
- def transpose!
58
- super()
59
- self.flip!
60
- end
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
- def multiply(m)
63
- t = super(m)
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
- end
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
- def multiply!(m)
68
- super().flip!
69
- end
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
- def [](i)
72
- case @orientation
73
- when :column; super(i, 0)
74
- when :row; super(0, i)
75
- end
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
- def []=(i, val)
79
- case @orientation
80
- when :column; super(i, 0, val)
81
- when :row; super(0, i, val)
82
- end
83
- end
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
- def dim; 1; end
171
+ # TODO: Make this actually pretty.
172
+ def pretty_print(q = nil) #:nodoc:
173
+ dim = @orientation == :row ? 1 : 0
86
174
 
87
- # TODO: Make this actually pretty.
88
- def pretty_print
89
- dim = @orientation == :row ? 1 : 0
90
-
91
- puts (0...shape[dim]).inject(Array.new) { |a, i| a << self[i] }.join(' ')
92
- end
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
- def inspect_helper
96
- super() << "orientation:#{self.orientation}"
97
- end
98
-
99
- def flip_orientation!
100
- returning(self) { @orientation = @orientation == :row ? :column : :row }
101
- end
102
- alias :flip! :flip_orientation!
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