nmatrix 0.0.9 → 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/History.txt +95 -1
  4. data/LICENSE.txt +2 -2
  5. data/README.rdoc +24 -26
  6. data/Rakefile +32 -16
  7. data/ext/nmatrix/data/complex.h +2 -2
  8. data/ext/nmatrix/data/data.cpp +27 -51
  9. data/ext/nmatrix/data/data.h +92 -4
  10. data/ext/nmatrix/data/meta.h +2 -2
  11. data/ext/nmatrix/data/rational.h +2 -2
  12. data/ext/nmatrix/data/ruby_object.h +2 -2
  13. data/ext/nmatrix/extconf.rb +87 -86
  14. data/ext/nmatrix/math.cpp +45 -40
  15. data/ext/nmatrix/math/asum.h +3 -3
  16. data/ext/nmatrix/math/geev.h +2 -2
  17. data/ext/nmatrix/math/gemm.h +6 -2
  18. data/ext/nmatrix/math/gemv.h +6 -2
  19. data/ext/nmatrix/math/ger.h +2 -2
  20. data/ext/nmatrix/math/gesdd.h +2 -2
  21. data/ext/nmatrix/math/gesvd.h +2 -2
  22. data/ext/nmatrix/math/getf2.h +2 -2
  23. data/ext/nmatrix/math/getrf.h +2 -2
  24. data/ext/nmatrix/math/getri.h +2 -2
  25. data/ext/nmatrix/math/getrs.h +7 -3
  26. data/ext/nmatrix/math/idamax.h +2 -2
  27. data/ext/nmatrix/math/inc.h +12 -6
  28. data/ext/nmatrix/math/laswp.h +2 -2
  29. data/ext/nmatrix/math/long_dtype.h +2 -2
  30. data/ext/nmatrix/math/math.h +16 -10
  31. data/ext/nmatrix/math/nrm2.h +3 -3
  32. data/ext/nmatrix/math/potrs.h +7 -3
  33. data/ext/nmatrix/math/rot.h +2 -2
  34. data/ext/nmatrix/math/rotg.h +2 -2
  35. data/ext/nmatrix/math/scal.h +2 -2
  36. data/ext/nmatrix/math/swap.h +2 -2
  37. data/ext/nmatrix/math/trsm.h +7 -3
  38. data/ext/nmatrix/nm_memory.h +60 -0
  39. data/ext/nmatrix/nmatrix.cpp +13 -47
  40. data/ext/nmatrix/nmatrix.h +37 -12
  41. data/ext/nmatrix/ruby_constants.cpp +4 -2
  42. data/ext/nmatrix/ruby_constants.h +4 -2
  43. data/ext/nmatrix/ruby_nmatrix.c +937 -170
  44. data/ext/nmatrix/storage/common.cpp +2 -2
  45. data/ext/nmatrix/storage/common.h +2 -2
  46. data/ext/nmatrix/storage/{dense.cpp → dense/dense.cpp} +253 -100
  47. data/ext/nmatrix/storage/{dense.h → dense/dense.h} +6 -5
  48. data/ext/nmatrix/storage/{list.cpp → list/list.cpp} +517 -98
  49. data/ext/nmatrix/storage/{list.h → list/list.h} +13 -6
  50. data/ext/nmatrix/storage/storage.cpp +48 -19
  51. data/ext/nmatrix/storage/storage.h +4 -4
  52. data/ext/nmatrix/storage/yale/class.h +112 -43
  53. data/ext/nmatrix/storage/yale/iterators/base.h +2 -2
  54. data/ext/nmatrix/storage/yale/iterators/iterator.h +2 -2
  55. data/ext/nmatrix/storage/yale/iterators/row.h +2 -2
  56. data/ext/nmatrix/storage/yale/iterators/row_stored.h +2 -2
  57. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +4 -3
  58. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +2 -2
  59. data/ext/nmatrix/storage/yale/math/transpose.h +2 -2
  60. data/ext/nmatrix/storage/yale/yale.cpp +343 -52
  61. data/ext/nmatrix/storage/yale/yale.h +7 -3
  62. data/ext/nmatrix/types.h +2 -2
  63. data/ext/nmatrix/util/io.cpp +5 -5
  64. data/ext/nmatrix/util/io.h +2 -2
  65. data/ext/nmatrix/util/sl_list.cpp +40 -27
  66. data/ext/nmatrix/util/sl_list.h +3 -3
  67. data/ext/nmatrix/util/util.h +2 -2
  68. data/lib/nmatrix.rb +2 -2
  69. data/lib/nmatrix/blas.rb +2 -2
  70. data/lib/nmatrix/enumerate.rb +17 -6
  71. data/lib/nmatrix/io/market.rb +2 -3
  72. data/lib/nmatrix/io/mat5_reader.rb +2 -2
  73. data/lib/nmatrix/io/mat_reader.rb +2 -2
  74. data/lib/nmatrix/lapack.rb +46 -46
  75. data/lib/nmatrix/math.rb +213 -20
  76. data/lib/nmatrix/monkeys.rb +24 -2
  77. data/lib/nmatrix/nmatrix.rb +394 -9
  78. data/lib/nmatrix/nvector.rb +2 -64
  79. data/lib/nmatrix/rspec.rb +2 -2
  80. data/lib/nmatrix/shortcuts.rb +14 -61
  81. data/lib/nmatrix/version.rb +11 -3
  82. data/lib/nmatrix/yale_functions.rb +4 -4
  83. data/nmatrix.gemspec +2 -7
  84. data/scripts/mac-brew-gcc.sh +11 -8
  85. data/scripts/mac-mavericks-brew-gcc.sh +22 -0
  86. data/spec/00_nmatrix_spec.rb +116 -7
  87. data/spec/01_enum_spec.rb +17 -3
  88. data/spec/02_slice_spec.rb +11 -3
  89. data/spec/blas_spec.rb +5 -2
  90. data/spec/elementwise_spec.rb +5 -2
  91. data/spec/io_spec.rb +27 -17
  92. data/spec/lapack_spec.rb +157 -9
  93. data/spec/math_spec.rb +95 -4
  94. data/spec/nmatrix_yale_spec.rb +21 -26
  95. data/spec/rspec_monkeys.rb +27 -0
  96. data/spec/rspec_spec.rb +2 -2
  97. data/spec/shortcuts_spec.rb +5 -10
  98. data/spec/slice_set_spec.rb +6 -2
  99. data/spec/spec_helper.rb +3 -2
  100. data/spec/stat_spec.rb +174 -158
  101. metadata +15 -15
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # == Copyright Information
11
11
  #
12
- # SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
13
- # NMatrix is Copyright (c) 2012, Ruby Science Foundation
12
+ # SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ # NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
14
  #
15
15
  # Please see LICENSE.txt for additional copyright notices.
16
16
  #
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # == Copyright Information
11
11
  #
12
- # SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
13
- # NMatrix is Copyright (c) 2013, Ruby Science Foundation
12
+ # SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ # NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
14
  #
15
15
  # Please see LICENSE.txt for additional copyright notices.
16
16
  #
@@ -64,16 +64,16 @@ class NMatrix
64
64
  # - +nrhs+ ->
65
65
  # - +a+ ->
66
66
  # - +lda+ ->
67
- # - +ipiv+ ->
68
67
  # - +b+ ->
69
68
  # - +ldb+ ->
69
+ # - +ipiv+ -> A pivot array (if nil, one will be generated with +clapack_getrf+)
70
70
  # * *Returns* :
71
71
  # -
72
72
  # * *Raises* :
73
73
  # - ++ ->
74
74
  #
75
- def clapack_gesv(order, n, nrhs, a, lda, ipiv, b, ldb)
76
- clapack_getrf(order, n, n, a, lda, ipiv)
75
+ def clapack_gesv(order, n, nrhs, a, lda, b, ldb, ipiv=nil)
76
+ ipiv ||= clapack_getrf(order, n, n, a, lda)
77
77
  clapack_getrs(order, :no_transpose, n, nrhs, a, lda, ipiv, b, ldb)
78
78
  end
79
79
 
@@ -120,47 +120,6 @@ class NMatrix
120
120
  clapack_potrs(order, uplo, n, nrhs, a, lda, b, ldb)
121
121
  end
122
122
 
123
- #
124
- # call-seq:
125
- # gesvd(matrix, type)
126
- #
127
- #
128
- # * *Arguments* :
129
- # - +matrix+ -> matrix for which to compute the singular values ##TODO make this a self
130
- # - +type+ -> :all_values, :both, :left, :right, :left_matrix, :right_matrix, :overwrite_right, :overwrite_left, :none , or signifying what combination of singular values and matrices are desired in your output.
131
- # * *Returns* :
132
- # - Array with the result values in an array
133
- # * *Raises* :
134
- # - +ArgumentError+ -> Expected dense NMatrix as first argument.
135
- #
136
- def gesvd(matrix, type = :both)
137
- raise ArgumentError, 'Expected dense NMatrix as first argument.' unless matrix.is_a?(NMatrix) and matrix.stype == :dense
138
- #define jobu, jobvt
139
- jobu, jobvt = :none, :none
140
- case type
141
- when :both
142
- jobu, jobvt = :all, :all
143
- when :arrays
144
- jobu, jobvt = :return, :return
145
- when :left
146
- jobu = :return
147
- when :right
148
- jobvt = :return
149
- end
150
-
151
- # Build up the u and vt matrices
152
- m, n = matrix.shape
153
- dtype = matrix.dtype
154
- s_matrix = NMatrix.new([1,matrix.shape.min], dtype: dtype)
155
- u_matrix = NMatrix.new([m,m], dtype: dtype)
156
- v_matrix = NMatrix.new([n,n], dtype: dtype)
157
- # test this
158
- s = gesvd(type, matrix, s_matrix, u_matrix, v_matrix)
159
-
160
- # what should this return?
161
- [s_matrix, u_matrix, v_matrix]
162
- end # #svd
163
-
164
123
  # laswp(matrix, ipiv) -> NMatrix
165
124
  #
166
125
  # Permute the columns of a matrix (in-place) according to the Array +ipiv+.
@@ -173,6 +132,47 @@ class NMatrix
173
132
  clapack_laswp(matrix.shape[0], matrix, matrix.shape[1], 0, ipiv.size-1, ipiv, 1)
174
133
  end
175
134
 
135
+ def alloc_svd_result(matrix)
136
+ [
137
+ NMatrix.new(matrix.shape[0], dtype: matrix.dtype),
138
+ NMatrix.new([matrix.shape[0],1], dtype: matrix.dtype),
139
+ NMatrix.new(matrix.shape[1], dtype: matrix.dtype)
140
+ ]
141
+ end
142
+
143
+ #
144
+ # call-seq:
145
+ # gesvd -> [u, sigma, v_transpose]
146
+ # gesvd -> [u, sigma, v_conjugate_transpose] # complex
147
+ #
148
+ # Compute the singular value decomposition of a matrix using LAPACK's GESVD function.
149
+ #
150
+ # Optionally accepts a +workspace_size+ parameter, which will be honored only if it is larger than what LAPACK
151
+ # requires.
152
+ #
153
+ def gesvd(matrix, workspace_size=1)
154
+ result = alloc_svd_result(matrix)
155
+ NMatrix::LAPACK::lapack_gesvd(:a, :a, matrix.shape[0], matrix.shape[1], matrix, matrix.shape[0], result[1], result[0], matrix.shape[0], result[2], matrix.shape[1], workspace_size)
156
+ result
157
+ end
158
+
159
+ #
160
+ # call-seq:
161
+ # gesdd -> [u, sigma, v_transpose]
162
+ # gesdd -> [u, sigma, v_conjugate_transpose] # complex
163
+ #
164
+ # Compute the singular value decomposition of a matrix using LAPACK's GESDD function. This uses a divide-and-conquer
165
+ # strategy. See also #gesvd.
166
+ #
167
+ # Optionally accepts a +workspace_size+ parameter, which will be honored only if it is larger than what LAPACK
168
+ # requires.
169
+ #
170
+ def gesdd(matrix, workspace_size=100000)
171
+ result = alloc_svd_result(matrix)
172
+ NMatrix::LAPACK::lapack_gesdd(:a, matrix.shape[0], matrix.shape[1], matrix, matrix.shape[0], result[1], result[0], matrix.shape[0], result[2], matrix.shape[1], workspace_size)
173
+ result
174
+ end
175
+
176
176
  end
177
177
  end
178
178
  end
data/lib/nmatrix/math.rb CHANGED
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # == Copyright Information
11
11
  #
12
- # SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
13
- # NMatrix is Copyright (c) 2013, Ruby Science Foundation
12
+ # SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ # NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
14
  #
15
15
  # Please see LICENSE.txt for additional copyright notices.
16
16
  #
@@ -29,6 +29,13 @@
29
29
  #++
30
30
 
31
31
  class NMatrix
32
+
33
+ module NMMath
34
+ METHODS_ARITY_2 = [:atan2, :ldexp, :hypot]
35
+ METHODS_ARITY_1 = [:cos, :sin, :tan, :acos, :asin, :atan, :cosh, :sinh, :tanh, :acosh,
36
+ :asinh, :atanh, :exp, :log2, :log10, :sqrt, :cbrt, :erf, :erfc, :gamma]
37
+ end
38
+
32
39
  #
33
40
  # call-seq:
34
41
  # invert! -> NMatrix
@@ -75,10 +82,66 @@ class NMatrix
75
82
  # - +StorageTypeError+ -> ATLAS functions only work on dense matrices.
76
83
  #
77
84
  def getrf!
78
- raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.stype == :dense
85
+ raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense?
79
86
  NMatrix::LAPACK::clapack_getrf(:row, self.shape[0], self.shape[1], self, self.shape[1])
80
87
  end
81
88
 
89
+
90
+ #
91
+ # call-seq:
92
+ # getrf -> NMatrix
93
+ #
94
+ # In-place version of #getrf!. Returns the new matrix, which contains L and U matrices.
95
+ #
96
+ # * *Raises* :
97
+ # - +StorageTypeError+ -> ATLAS functions only work on dense matrices.
98
+ #
99
+ def getrf
100
+ a = self.clone
101
+ a.getrf!
102
+ return a
103
+ end
104
+
105
+
106
+ #
107
+ # call-seq:
108
+ # potrf!(upper_or_lower) -> NMatrix
109
+ #
110
+ # Cholesky factorization of a symmetric positive-definite matrix -- or, if complex,
111
+ # a Hermitian positive-definite matrix +A+. This uses the ATLAS function clapack_potrf,
112
+ # so the result will be written in either the upper or lower triangular portion of the
113
+ # matrix upon which it is called.
114
+ #
115
+ # * *Returns* :
116
+ # the triangular portion specified by the parameter
117
+ # * *Raises* :
118
+ # - +StorageTypeError+ -> ATLAS functions only work on dense matrices.
119
+ #
120
+ def potrf!(which)
121
+ raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense?
122
+ # FIXME: Surely there's an easy way to calculate one of these from the other. Do we really need to run twice?
123
+ NMatrix::LAPACK::clapack_potrf(:row, which, self.shape[0], self, self.shape[1])
124
+ end
125
+
126
+ def potrf_upper!
127
+ potrf! :upper
128
+ end
129
+
130
+ def potrf_lower!
131
+ potrf! :lower
132
+ end
133
+
134
+
135
+ #
136
+ # call-seq:
137
+ # factorize_cholesky -> ...
138
+ #
139
+ # Cholesky factorization of a matrix.
140
+ def factorize_cholesky
141
+ [self.clone.potrf_upper!.triu!,
142
+ self.clone.potrf_lower!.tril!]
143
+ end
144
+
82
145
  #
83
146
  # call-seq:
84
147
  # factorize_lu -> ...
@@ -97,12 +160,19 @@ class NMatrix
97
160
  t.transpose
98
161
  end
99
162
 
100
- def alloc_svd_result
101
- [
102
- NMatrix.new(self.shape[0], dtype: self.dtype),
103
- NMatrix.new([self.shape[0],1], dtype: self.dtype),
104
- NMatrix.new(self.shape[1], dtype: self.dtype)
105
- ]
163
+ #
164
+ # call-seq:
165
+ # gesvd! -> [u, sigma, v_transpose]
166
+ # gesvd! -> [u, sigma, v_conjugate_transpose] # complex
167
+ #
168
+ # Compute the singular value decomposition of a matrix using LAPACK's GESVD function.
169
+ # This is destructive, modifying the source NMatrix. See also #gesdd.
170
+ #
171
+ # Optionally accepts a +workspace_size+ parameter, which will be honored only if it is larger than what LAPACK
172
+ # requires.
173
+ #
174
+ def gesvd!(workspace_size=1)
175
+ NMatrix::LAPACK::gesvd(self, workspace_size)
106
176
  end
107
177
 
108
178
  #
@@ -116,12 +186,26 @@ class NMatrix
116
186
  # requires.
117
187
  #
118
188
  def gesvd(workspace_size=1)
119
- result = alloc_svd_result
120
- NMatrix::LAPACK::lapack_gesvd(:a, :a, self.shape[0], self.shape[1], self, self.shape[0], result[1], result[0], self.shape[0], result[2], self.shape[1], workspace_size)
121
- result
189
+ self.clone.gesvd!(workspace_size)
122
190
  end
123
191
 
124
192
 
193
+
194
+ #
195
+ # call-seq:
196
+ # gesdd! -> [u, sigma, v_transpose]
197
+ # gesdd! -> [u, sigma, v_conjugate_transpose] # complex
198
+ #
199
+ # Compute the singular value decomposition of a matrix using LAPACK's GESDD function. This uses a divide-and-conquer
200
+ # strategy. This is destructive, modifying the source NMatrix. See also #gesvd.
201
+ #
202
+ # Optionally accepts a +workspace_size+ parameter, which will be honored only if it is larger than what LAPACK
203
+ # requires.
204
+ #
205
+ def gesdd!(workspace_size=1)
206
+ NMatrix::LAPACK::gesdd(self, workspace_size)
207
+ end
208
+
125
209
  #
126
210
  # call-seq:
127
211
  # gesdd -> [u, sigma, v_transpose]
@@ -134,11 +218,8 @@ class NMatrix
134
218
  # requires.
135
219
  #
136
220
  def gesdd(workspace_size=1)
137
- result = alloc_svd_result
138
- NMatrix::LAPACK::lapack_gesvd(:a, :a, self.shape[0], self.shape[1], self, self.shape[0], result[1], result[0], self.shape[0], result[2], self.shape[1], workspace_size)
139
- result
221
+ self.clone.gesdd!(workspace_size)
140
222
  end
141
-
142
223
  #
143
224
  # call-seq:
144
225
  # laswp!(ary) -> NMatrix
@@ -279,8 +360,8 @@ class NMatrix
279
360
  reduce_dtype = :float64
280
361
  end
281
362
  inject_rank(dimen, 0.0, reduce_dtype) do |mean, sub_mat|
282
- mean + sub_mat/shape[dimen]
283
- end
363
+ mean + sub_mat
364
+ end / shape[dimen]
284
365
  end
285
366
 
286
367
  ##
@@ -372,7 +453,7 @@ class NMatrix
372
453
  # @see #inject_rank
373
454
  #
374
455
  def std(dimen=0)
375
- variance(dimen).map! { |e| Math.sqrt(e) }
456
+ variance(dimen).sqrt
376
457
  end
377
458
 
378
459
 
@@ -409,6 +490,38 @@ class NMatrix
409
490
  end.cast(self.stype, abs_dtype)
410
491
  end
411
492
 
493
+
494
+ #
495
+ # call-seq:
496
+ # absolute_sum -> Numeric
497
+ #
498
+ # == Arguments
499
+ # - +incx+ -> the skip size (defaults to 1, no skip)
500
+ # - +n+ -> the number of elements to include
501
+ #
502
+ # Return the sum of the contents of the vector. This is the BLAS asum routine.
503
+ def asum incx=1, n=nil
504
+ return method_missing(:asum, incx, n) unless vector?
505
+ NMatrix::BLAS::asum(self, incx, self.size / incx)
506
+ end
507
+ alias :absolute_sum :asum
508
+
509
+ #
510
+ # call-seq:
511
+ # norm2 -> Numeric
512
+ #
513
+ # == Arguments
514
+ # - +incx+ -> the skip size (defaults to 1, no skip)
515
+ # - +n+ -> the number of elements to include
516
+ #
517
+ # Return the 2-norm of the vector. This is the BLAS nrm2 routine.
518
+ def nrm2 incx=1, n=nil
519
+ return method_missing(:nrm2, incx, n) unless vector?
520
+ NMatrix::BLAS::nrm2(self, incx, self.size / incx)
521
+ end
522
+ alias :norm2 :nrm2
523
+
524
+
412
525
  alias :permute_columns :laswp
413
526
  alias :permute_columns! :laswp!
414
527
 
@@ -437,6 +550,86 @@ protected
437
550
  end
438
551
  end
439
552
 
553
+ # These don't actually take an argument -- they're called reverse-polish style on the matrix.
554
+ # This group always gets casted to float64.
555
+ [:log2, :log10, :sqrt, :sin, :cos, :tan, :acos, :asin, :atan, :cosh, :sinh, :tanh, :acosh, :asinh, :atanh, :exp, :erf, :erfc, :gamma, :cbrt].each do |ewop|
556
+ define_method("__list_unary_#{ewop}__") do
557
+ self.__list_map_stored__(nil) { |l| Math.send(ewop, l) }.cast(stype, NMatrix.upcast(dtype, :float64))
558
+ end
559
+ define_method("__yale_unary_#{ewop}__") do
560
+ self.__yale_map_stored__ { |l| Math.send(ewop, l) }.cast(stype, NMatrix.upcast(dtype, :float64))
561
+ end
562
+ define_method("__dense_unary_#{ewop}__") do
563
+ self.__dense_map__ { |l| Math.send(ewop, l) }.cast(stype, NMatrix.upcast(dtype, :float64))
564
+ end
565
+ end
566
+
567
+ # log takes an optional single argument, the base. Default to natural log.
568
+ def __list_unary_log__(base)
569
+ self.__list_map_stored__(nil) { |l| Math.log(l, base) }.cast(stype, NMatrix.upcast(dtype, :float64))
570
+ end
571
+
572
+ def __yale_unary_log__(base)
573
+ self.__yale_map_stored__ { |l| Math.log(l, base) }.cast(stype, NMatrix.upcast(dtype, :float64))
574
+ end
575
+
576
+ def __dense_unary_log__(base)
577
+ self.__dense_map__ { |l| Math.log(l, base) }.cast(stype, NMatrix.upcast(dtype, :float64))
578
+ end
579
+
580
+ # These take two arguments. One might be a matrix, and one might be a scalar.
581
+ # See also monkeys.rb, which contains Math module patches to let the first
582
+ # arg be a scalar
583
+ [:atan2, :ldexp, :hypot].each do |ewop|
584
+ define_method("__list_elementwise_#{ewop}__") do |rhs,order|
585
+ if order then
586
+ self.__list_map_merged_stored__(rhs, nil) { |r,l| Math.send(ewop,l,r) }
587
+ else
588
+ self.__list_map_merged_stored__(rhs, nil) { |l,r| Math.send(ewop,l,r) }
589
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
590
+ end
591
+
592
+ define_method("__dense_elementwise_#{ewop}__") do |rhs, order|
593
+ if order then
594
+ self.__dense_map_pair__(rhs) { |r,l| Math.send(ewop,l,r) }
595
+ else
596
+ self.__dense_map_pair__(rhs) { |l,r| Math.send(ewop,l,r) }
597
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
598
+ end
599
+
600
+ define_method("__yale_elementwise_#{ewop}__") do |rhs, order|
601
+ if order then
602
+ self.__yale_map_merged_stored__(rhs, nil) { |r,l| Math.send(ewop,l,r) }
603
+ else
604
+ self.__yale_map_merged_stored__(rhs, nil) { |l,r| Math.send(ewop,l,r) }
605
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
606
+ end
607
+
608
+ define_method("__list_scalar_#{ewop}__") do |rhs,order|
609
+ if order then
610
+ self.__list_map_stored__(nil) { |l| Math.send(ewop, rhs, l) }
611
+ else
612
+ self.__list_map_stored__(nil) { |l| Math.send(ewop, l, rhs) }
613
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
614
+ end
615
+
616
+ define_method("__yale_scalar_#{ewop}__") do |rhs,order|
617
+ if order then
618
+ self.__yale_map_stored__ { |l| Math.send(ewop, rhs, l) }
619
+ else
620
+ self.__yale_map_stored__ { |l| Math.send(ewop, l, rhs) }
621
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
622
+ end
623
+
624
+ define_method("__dense_scalar_#{ewop}__") do |rhs,order|
625
+ if order
626
+ self.__dense_map__ { |l| Math.send(ewop, rhs, l) }
627
+ else
628
+ self.__dense_map__ { |l| Math.send(ewop, l, rhs) }
629
+ end.cast(stype, NMatrix.upcast(dtype, :float64))
630
+ end
631
+ end
632
+
440
633
  # Equality operators do not involve a cast. We want to get back matrices of TrueClass and FalseClass.
441
634
  {eqeq: :==, neq: :!=, lt: :<, gt: :>, leq: :<=, geq: :>=}.each_pair do |ewop, op|
442
635
  define_method("__list_elementwise_#{ewop}__") do |rhs|
@@ -459,4 +652,4 @@ protected
459
652
  self.__dense_map__ { |l| l.send(op,rhs) }
460
653
  end
461
654
  end
462
- end
655
+ end
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # == Copyright Information
11
11
  #
12
- # SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
13
- # NMatrix is Copyright (c) 2013, Ruby Science Foundation
12
+ # SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ # NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
14
  #
15
15
  # Please see LICENSE.txt for additional copyright notices.
16
16
  #
@@ -26,6 +26,8 @@
26
26
  # Ruby core extensions for NMatrix.
27
27
  #++
28
28
 
29
+ require 'nmatrix/math'
30
+
29
31
  #######################
30
32
  # Classes and Modules #
31
33
  #######################
@@ -60,3 +62,23 @@ class Object #:nodoc:
60
62
  value
61
63
  end
62
64
  end
65
+
66
+
67
+ module Math
68
+ class << self
69
+ NMatrix::NMMath::METHODS_ARITY_2.each do |meth|
70
+ define_method "nm_#{meth}" do |arg0, arg1|
71
+ if arg0.is_a? NMatrix then
72
+ arg0.send(meth, arg1)
73
+ elsif arg1.is_a? NMatrix then
74
+ arg1.send(meth, arg0, true)
75
+ else
76
+ self.send("old_#{meth}".to_sym, arg0, arg1)
77
+ end
78
+ end
79
+ alias_method "old_#{meth}".to_sym, meth
80
+ alias_method meth, "nm_#{meth}".to_sym
81
+ end
82
+ end
83
+ end
84
+