nmatrix 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +102 -10
  3. data/README.rdoc +24 -32
  4. data/Rakefile +1 -1
  5. data/ext/nmatrix/data/complex.h +9 -0
  6. data/ext/nmatrix/data/data.cpp +78 -4
  7. data/ext/nmatrix/data/data.h +86 -54
  8. data/ext/nmatrix/data/rational.h +2 -0
  9. data/ext/nmatrix/data/ruby_object.h +38 -8
  10. data/ext/nmatrix/extconf.rb +13 -7
  11. data/ext/nmatrix/nmatrix.cpp +262 -139
  12. data/ext/nmatrix/nmatrix.h +11 -4
  13. data/ext/nmatrix/storage/common.cpp +20 -13
  14. data/ext/nmatrix/storage/common.h +18 -12
  15. data/ext/nmatrix/storage/dense.cpp +122 -192
  16. data/ext/nmatrix/storage/dense.h +4 -2
  17. data/ext/nmatrix/storage/list.cpp +467 -636
  18. data/ext/nmatrix/storage/list.h +6 -3
  19. data/ext/nmatrix/storage/storage.cpp +83 -46
  20. data/ext/nmatrix/storage/storage.h +7 -7
  21. data/ext/nmatrix/storage/yale.cpp +621 -361
  22. data/ext/nmatrix/storage/yale.h +21 -9
  23. data/ext/nmatrix/ttable_helper.rb +27 -31
  24. data/ext/nmatrix/types.h +1 -1
  25. data/ext/nmatrix/util/math.cpp +9 -10
  26. data/ext/nmatrix/util/sl_list.cpp +1 -7
  27. data/ext/nmatrix/util/sl_list.h +0 -118
  28. data/lib/nmatrix/blas.rb +59 -18
  29. data/lib/nmatrix/monkeys.rb +0 -52
  30. data/lib/nmatrix/nmatrix.rb +136 -9
  31. data/lib/nmatrix/nvector.rb +33 -0
  32. data/lib/nmatrix/shortcuts.rb +95 -16
  33. data/lib/nmatrix/version.rb +1 -1
  34. data/lib/nmatrix/yale_functions.rb +25 -19
  35. data/spec/blas_spec.rb +1 -19
  36. data/spec/elementwise_spec.rb +132 -17
  37. data/spec/lapack_spec.rb +0 -3
  38. data/spec/nmatrix_list_spec.rb +18 -0
  39. data/spec/nmatrix_spec.rb +44 -18
  40. data/spec/nmatrix_yale_spec.rb +1 -3
  41. data/spec/shortcuts_spec.rb +26 -36
  42. data/spec/slice_spec.rb +2 -4
  43. metadata +2 -2
@@ -90,13 +90,14 @@ extern "C" {
90
90
  YALE_STORAGE* nm_yale_storage_create_from_old_yale(nm::dtype_t dtype, size_t* shape, void* ia, void* ja, void* a, nm::dtype_t from_dtype);
91
91
  YALE_STORAGE* nm_yale_storage_create_merged(const YALE_STORAGE* merge_template, const YALE_STORAGE* other);
92
92
  void nm_yale_storage_delete(STORAGE* s);
93
- void nm_yale_storage_init(YALE_STORAGE* s);
93
+ void nm_yale_storage_init(YALE_STORAGE* s, void* default_val);
94
94
  void nm_yale_storage_mark(void*);
95
95
 
96
96
  ///////////////
97
97
  // Accessors //
98
98
  ///////////////
99
99
 
100
+ VALUE nm_yale_each_with_indices(VALUE nmatrix);
100
101
  VALUE nm_yale_each_stored_with_indices(VALUE nmatrix);
101
102
  void* nm_yale_storage_get(STORAGE* s, SLICE* slice);
102
103
  void* nm_yale_storage_ref(STORAGE* s, SLICE* slice);
@@ -106,6 +107,9 @@ extern "C" {
106
107
  //void nm_yale_storage_increment_ia_after(YALE_STORAGE* s, size_t ija_size, size_t i, size_t n);
107
108
 
108
109
  size_t nm_yale_storage_get_size(const YALE_STORAGE* storage);
110
+ VALUE nm_yale_default_value(VALUE self);
111
+ VALUE nm_yale_map_stored(VALUE self);
112
+ VALUE nm_yale_map_merged_stored(VALUE left, VALUE right, VALUE init);
109
113
 
110
114
  ///////////
111
115
  // Tests //
@@ -116,8 +120,7 @@ extern "C" {
116
120
  //////////
117
121
  // Math //
118
122
  //////////
119
-
120
- STORAGE* nm_yale_storage_ew_op(nm::ewop_t op, const STORAGE* left, const STORAGE* right, VALUE scalar);
123
+
121
124
  STORAGE* nm_yale_storage_matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resulting_shape, bool vector);
122
125
 
123
126
  /////////////
@@ -163,13 +166,15 @@ extern "C" {
163
166
  // Copying and Casting //
164
167
  /////////////////////////
165
168
 
166
- STORAGE* nm_yale_storage_cast_copy(const STORAGE* rhs, nm::dtype_t new_dtype);
169
+ STORAGE* nm_yale_storage_cast_copy(const STORAGE* rhs, nm::dtype_t new_dtype, void*);
167
170
  STORAGE* nm_yale_storage_copy_transposed(const STORAGE* rhs_base);
168
171
 
169
172
 
170
173
 
171
174
  void nm_init_yale_functions(void);
172
175
 
176
+ VALUE nm_vector_set(int argc, VALUE* argv, VALUE self);
177
+
173
178
 
174
179
  } // end of extern "C" block
175
180
 
@@ -193,19 +198,26 @@ namespace nm { namespace yale_storage {
193
198
  * the zero value).
194
199
  *
195
200
  * Note: This sets a literal 0 value. If your dtype is RUBYOBJ (a Ruby object),
196
- * it'll actually be INT2FIX(0) instead of a string of NULLs.
201
+ * it'll actually be INT2FIX(0) instead of a string of NULLs. You can actually
202
+ * set a default for Ruby objects other than zero -- you generally want it to
203
+ * be Qfalse, Qnil, or INT2FIX(0). The last is the default.
197
204
  */
198
205
  template <typename DType>
199
- inline void clear_diagonal_and_zero(YALE_STORAGE* s) {
206
+ inline void clear_diagonal_and_zero(YALE_STORAGE* s, void* init_val) {
200
207
  DType* a = reinterpret_cast<DType*>(s->a);
201
208
 
202
209
  // Clear out the diagonal + one extra entry
203
- for (size_t i = 0; i < s->shape[0]+1; ++i) // insert Ruby zeros
204
- a[i] = 0;
210
+ if (init_val) {
211
+ for (size_t i = 0; i <= s->shape[0]; ++i) // insert Ruby zeros, falses, or whatever else.
212
+ a[i] = *reinterpret_cast<DType*>(init_val);
213
+ } else {
214
+ for (size_t i = 0; i <= s->shape[0]; ++i) // insert zeros.
215
+ a[i] = 0;
216
+ }
205
217
  }
206
218
 
207
219
  template <typename DType, typename IType>
208
- void init(YALE_STORAGE* s);
220
+ void init(YALE_STORAGE* s, void* init_val);
209
221
 
210
222
  template <typename IType>
211
223
  size_t get_size(const YALE_STORAGE* storage);
@@ -2,9 +2,6 @@
2
2
 
3
3
  # A helper file for generating and maintaining template tables.
4
4
 
5
- def nullify(disabled) #:nodoc:
6
- DTYPES.map { |t| if disabled.include?(t) then :NULL else t end }
7
- end
8
5
 
9
6
  DTYPES = [
10
7
  :uint8_t,
@@ -22,6 +19,10 @@ DTYPES = [
22
19
  :'nm::RubyObject'
23
20
  ]
24
21
 
22
+ def nullify(disabled = []) #:nodoc:
23
+ DTYPES.map { |t| if disabled.include?(t) then :NULL else t end }
24
+ end
25
+
25
26
  ITYPES = [
26
27
  :uint8_t,
27
28
  :uint16_t,
@@ -34,6 +35,7 @@ EWOPS = [
34
35
  :'nm::EW_SUB',
35
36
  :'nm::EW_MUL',
36
37
  :'nm::EW_DIV',
38
+ :'nm::EW_POW',
37
39
  :'nm::EW_MOD',
38
40
  :'nm::EW_EQEQ',
39
41
  :'nm::EW_NEQ',
@@ -44,19 +46,19 @@ EWOPS = [
44
46
  ]
45
47
 
46
48
  LR_ALLOWED = {
47
- :uint8_t => nullify([:RubyObject]),
48
- :int8_t => nullify([:RubyObject]),
49
- :int16_t => nullify([:RubyObject]),
50
- :int32_t => nullify([:RubyObject]),
51
- :int64_t => nullify([:RubyObject]),
52
- :float32_t => nullify([:RubyObject]),
53
- :float64_t => nullify([:RubyObject]),
54
- :Complex64 => nullify([:RubyObject]),
55
- :Complex128 => nullify([:RubyObject]),
56
- :Rational32 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128', :'nm::RubyObject']),
57
- :Rational64 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128', :'nm::RubyObject']),
58
- :Rational128 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128', :'nm::RubyObject']),
59
- :RubyObject => nullify(DTYPES - [:RubyObject])
49
+ :uint8_t => DTYPES,
50
+ :int8_t => DTYPES,
51
+ :int16_t => DTYPES,
52
+ :int32_t => DTYPES,
53
+ :int64_t => DTYPES,
54
+ :float32_t => DTYPES,
55
+ :float64_t => DTYPES,
56
+ :'nm::Complex64' => DTYPES,
57
+ :'nm::Complex128' => DTYPES,
58
+ :'nm::Rational32' => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128']),
59
+ :'nm::Rational64' => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128']),
60
+ :'nm::Rational128' => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128']),
61
+ :'nm::RubyObject' => DTYPES
60
62
  }
61
63
 
62
64
  lines =
@@ -106,21 +108,15 @@ lines =
106
108
  '}'
107
109
 
108
110
  when 'LR'
109
- '{' +
110
- DTYPES.map do |l_dtype|
111
-
112
- '{' +
113
- LR_ALLOWED[l_dtype].map do |r_dtype|
114
- if r_dtype == :NULL
115
- 'NULL'
116
- else
117
- "fun<#{l_dtype}, #{r_dtype}>"
118
- end
119
- end.join(', ') +
120
- '}'
121
-
122
- end.join(",\n") +
123
- '}'
111
+ '{' + DTYPES.map do |l_dtype|
112
+ '{' + LR_ALLOWED[l_dtype].map do |r_dtype|
113
+ if r_dtype == :NULL
114
+ 'NULL'
115
+ else
116
+ "fun<#{l_dtype}, #{r_dtype}>"
117
+ end
118
+ end.join(', ') + '}'
119
+ end.join(",\n") + '}'
124
120
  end
125
121
 
126
122
  puts lines
data/ext/nmatrix/types.h CHANGED
@@ -32,7 +32,7 @@
32
32
  * Standard Includes
33
33
  */
34
34
 
35
- #include <stdint.h>
35
+ #include <cstdint>
36
36
 
37
37
  /*
38
38
  * Macros
@@ -416,16 +416,14 @@ static VALUE nm_cblas_rotg(VALUE self, VALUE ab) {
416
416
  nm::math::cblas_rotg<double>,
417
417
  nm::math::cblas_rotg<nm::Complex64>,
418
418
  nm::math::cblas_rotg<nm::Complex128>,
419
- nm::math::cblas_rotg<nm::Rational32>,
420
- nm::math::cblas_rotg<nm::Rational64>,
421
- nm::math::cblas_rotg<nm::Rational128>,
419
+ NULL, NULL, NULL, // no rationals
422
420
  nm::math::cblas_rotg<nm::RubyObject>
423
421
  };
424
422
 
425
423
  nm::dtype_t dtype = NM_DTYPE(ab);
426
424
 
427
425
  if (!ttable[dtype]) {
428
- rb_raise(nm_eDataTypeError, "this matrix operation undefined for integer matrices");
426
+ rb_raise(nm_eDataTypeError, "this operation undefined for integer and rational vectors");
429
427
  return Qnil;
430
428
 
431
429
  } else {
@@ -488,7 +486,7 @@ static VALUE nm_cblas_rot(VALUE self, VALUE n, VALUE x, VALUE incx, VALUE y, VAL
488
486
 
489
487
 
490
488
  if (!ttable[dtype]) {
491
- rb_raise(nm_eDataTypeError, "this matrix operation undefined for integer matrices");
489
+ rb_raise(nm_eDataTypeError, "this operation undefined for integer vectors");
492
490
  return Qfalse;
493
491
  } else {
494
492
  void *pC, *pS;
@@ -547,16 +545,17 @@ static VALUE nm_cblas_nrm2(VALUE self, VALUE n, VALUE x, VALUE incx) {
547
545
  nm::math::cblas_nrm2<float64_t,float64_t>,
548
546
  nm::math::cblas_nrm2<float32_t,nm::Complex64>,
549
547
  nm::math::cblas_nrm2<float64_t,nm::Complex128>,
550
- nm::math::cblas_nrm2<nm::Rational32,nm::Rational32>,
551
- nm::math::cblas_nrm2<nm::Rational64,nm::Rational64>,
552
- nm::math::cblas_nrm2<nm::Rational128,nm::Rational128>,
548
+ //nm::math::cblas_nrm2<nm::Rational32,nm::Rational32>,
549
+ //nm::math::cblas_nrm2<nm::Rational64,nm::Rational64>,
550
+ //nm::math::cblas_nrm2<nm::Rational128,nm::Rational128>,
551
+ NULL, NULL, NULL,
553
552
  nm::math::cblas_nrm2<nm::RubyObject,nm::RubyObject>
554
553
  };
555
554
 
556
555
  nm::dtype_t dtype = NM_DTYPE(x);
557
556
 
558
557
  if (!ttable[dtype]) {
559
- rb_raise(nm_eDataTypeError, "this vector operation undefined for integer vectors");
558
+ rb_raise(nm_eDataTypeError, "this operation undefined for integer and rational vectors");
560
559
  return Qnil;
561
560
 
562
561
  } else {
@@ -1154,7 +1153,7 @@ static VALUE nm_clapack_getri(VALUE self, VALUE order, VALUE n, VALUE a, VALUE l
1154
1153
 
1155
1154
  if (!ttable[NM_DTYPE(a)]) {
1156
1155
  rb_raise(rb_eNotImpError, "this operation not yet implemented for non-BLAS dtypes");
1157
- // FIXME: Once BLAS dtypes are implemented, replace error above with the error below.
1156
+ // FIXME: Once non-BLAS dtypes are implemented, replace error above with the error below.
1158
1157
  //rb_raise(nm_eDataTypeError, "this matrix operation undefined for integer matrices");
1159
1158
  } else {
1160
1159
  // Call either our version of getri or the LAPACK version.
@@ -58,13 +58,7 @@ namespace nm { namespace list {
58
58
  * Creates an empty linked list.
59
59
  */
60
60
  LIST* create(void) {
61
- LIST* list;
62
-
63
- //if (!(list = malloc(sizeof(LIST)))) return NULL;
64
- list = ALLOC( LIST );
65
-
66
- //fprintf(stderr, " create_list LIST: %p\n", list);
67
-
61
+ LIST* list = ALLOC( LIST );
68
62
  list->first = NULL;
69
63
  return list;
70
64
  }
@@ -110,124 +110,6 @@ inline NODE* insert_helper(LIST* list, NODE* node, size_t key, Type* ptr) {
110
110
  // Tests //
111
111
  ///////////
112
112
 
113
- /*
114
- * Do all values in a list == some value?
115
- *
116
- * Note that the template parameters should line up with the first two function parameters. This differs from most
117
- * other eqeq functions, which use left and right dtypes.
118
- */
119
- template <typename ListDType, typename ValueDType>
120
- bool eqeq_value(const LIST* l, const ValueDType* v, size_t recursions, size_t& checked) {
121
- NODE *next, *curr = l->first;
122
-
123
- while (curr) {
124
- next = curr->next;
125
-
126
- if (recursions == 0) {
127
- ++checked;
128
-
129
- if (*reinterpret_cast<ListDType*>(curr->val) != *v) return false;
130
-
131
- } else if (!eqeq_value<ListDType,ValueDType>((LIST*)curr->val, v, recursions - 1, checked)) {
132
- return false;
133
- }
134
-
135
- curr = next;
136
- }
137
-
138
- return true;
139
- }
140
-
141
-
142
- /*
143
- * Are all values in the two lists equal? If one is missing a value, but the
144
- * other isn't, does the value in the list match the default value?
145
- */
146
- template <typename LDType, typename RDType>
147
- bool eqeq(const LIST* left, const LIST* right, const LDType* left_val, const RDType* right_val, size_t recursions, size_t& checked) {
148
- NODE *lnext = NULL, *lcurr = left->first, *rnext = NULL, *rcurr = right->first;
149
-
150
- if (lcurr) lnext = lcurr->next;
151
- if (rcurr) rnext = rcurr->next;
152
-
153
- while (lcurr && rcurr) {
154
-
155
- if (lcurr->key == rcurr->key) {
156
- // MATCHING KEYS
157
-
158
- if (recursions == 0) {
159
- ++checked;
160
-
161
- if (*reinterpret_cast<LDType*>(lcurr->val) != *reinterpret_cast<RDType*>(rcurr->val)) return false;
162
-
163
- } else if (!eqeq<LDType,RDType>(reinterpret_cast<LIST*>(lcurr->val), (LIST*)rcurr->val, left_val, right_val, recursions - 1, checked)) {
164
- return false;
165
- }
166
-
167
- // increment both iterators
168
- rcurr = rnext;
169
- if (rcurr) rnext = rcurr->next;
170
- lcurr = lnext;
171
- if (lcurr) lnext = lcurr->next;
172
-
173
- } else if (lcurr->key < rcurr->key) {
174
- // NON-MATCHING KEYS
175
-
176
- if (recursions == 0) {
177
- // compare left entry to right default value
178
- ++checked;
179
-
180
- if (*reinterpret_cast<LDType*>(lcurr->val) != *right_val) return false;
181
-
182
- } else if (!eqeq_value<LDType,RDType>(reinterpret_cast<LIST*>(lcurr->val), right_val, recursions - 1, checked)) {
183
- return false;
184
- }
185
-
186
- // increment left iterator
187
- lcurr = lnext;
188
- if (lcurr) lnext = lcurr->next;
189
-
190
- } else {
191
- // if (rcurr->key < lcurr->key)
192
-
193
- if (recursions == 0) {
194
- // compare right entry to left default value
195
- ++checked;
196
-
197
- if (*reinterpret_cast<RDType*>(rcurr->val) != *left_val) return false;
198
-
199
- } else if (!eqeq_value<RDType,LDType>(reinterpret_cast<LIST*>(rcurr->val), left_val, recursions - 1, checked)) {
200
- return false;
201
- }
202
-
203
- // increment right iterator
204
- rcurr = rnext;
205
- if (rcurr) rnext = rcurr->next;
206
- }
207
-
208
- }
209
-
210
- /*
211
- * One final check, in case we get to the end of one list but not the other
212
- * one.
213
- */
214
- if (lcurr) {
215
- // nothing left in right-hand list
216
- if (*reinterpret_cast<LDType*>(lcurr->val) != *right_val) return false;
217
-
218
- } else if (rcurr) {
219
- // nothing left in left-hand list
220
- if (*reinterpret_cast<RDType*>(rcurr->val) != *left_val) return false;
221
-
222
- }
223
-
224
- /*
225
- * Nothing different between the two lists -- but make sure after this return
226
- * that you compare the default values themselves, if we haven't visited
227
- * every value in the two matrices.
228
- */
229
- return true;
230
- }
231
113
 
232
114
  /////////////
233
115
  // Utility //
data/lib/nmatrix/blas.rb CHANGED
@@ -159,43 +159,84 @@ module NMatrix::BLAS
159
159
 
160
160
  #
161
161
  # call-seq:
162
- # rot(x, y, c, s)
162
+ # rot(x, y, c, s) -> [NVector, NVector]
163
163
  #
164
164
  # Apply plane rotation.
165
165
  #
166
166
  # * *Arguments* :
167
- # - +x+ ->
168
- # - +y+ ->
169
- # - +s+ ->
170
- # - +c+ ->
171
- # - +incx+ ->
172
- # - +incy+ ->
173
- # - +n+ ->
167
+ # - +x+ -> NVector
168
+ # - +y+ -> NVector
169
+ # - +c+ -> cosine of the angle of rotation
170
+ # - +s+ -> sine of the angle of rotation
171
+ # - +incx+ -> stride of NVector +x+
172
+ # - +incy+ -> stride of NVector +y+
173
+ # - +n+ -> number of elements to consider in x and y
174
+ # - +in_place+ -> true if it's okay to modify the supplied +x+ and +y+ parameters directly; false if not. Default is false.
174
175
  # * *Returns* :
175
176
  # - Array with the results, in the format [xx, yy]
176
177
  # * *Raises* :
177
- # - +ArgumentError+ -> Expected dense NMatrices as first two arguments.
178
- # - +ArgumentError+ -> Nmatrix dtype mismatch.
178
+ # - +ArgumentError+ -> Expected dense NVectors as first two arguments.
179
+ # - +ArgumentError+ -> NMatrix dtype mismatch.
179
180
  # - +ArgumentError+ -> Need to supply n for non-standard incx, incy values.
180
181
  #
181
- def rot(x, y, c, s, incx = 1, incy = 1, n = nil)
182
- raise(ArgumentError, 'Expected dense NMatrices as first two arguments.') unless x.is_a?(NMatrix) and y.is_a?(NMatrix) and x.stype == :dense and y.stype == :dense
182
+ def rot(x, y, c, s, incx = 1, incy = 1, n = nil, in_place=false)
183
+ raise(ArgumentError, 'Expected dense NVectors as first two arguments.') unless x.is_a?(NMatrix) and y.is_a?(NMatrix) and x.stype == :dense and y.stype == :dense
183
184
  raise(ArgumentError, 'NMatrix dtype mismatch.') unless x.dtype == y.dtype
184
185
  raise(ArgumentError, 'Need to supply n for non-standard incx, incy values') if n.nil? && incx != 1 && incx != -1 && incy != 1 && incy != -1
185
186
 
186
- n ||= x.size > y.size ? y.size : x.size
187
+ n ||= [x.size/incx.abs, y.size/incy.abs].min
188
+
189
+ if in_place
190
+ ::NMatrix::BLAS.cblas_rot(n, x, incx, y, incy, c, s)
191
+ return [x,y]
192
+ else
193
+ xx = x.clone
194
+ yy = y.clone
195
+
196
+ ::NMatrix::BLAS.cblas_rot(n, xx, incx, yy, incy, c, s)
197
+
198
+ return [xx,yy]
199
+ end
200
+ end
201
+
202
+
203
+ #
204
+ # call-seq:
205
+ # rot!(x, y, c, s) -> [NVector, NVector]
206
+ #
207
+ # Apply plane rotation directly to +x+ and +y+.
208
+ #
209
+ # See rot for arguments.
210
+ def rot!(x, y, c, s, incx = 1, incy = 1, n = nil)
211
+ rot(x,y,c,s,incx,incy,n,true)
212
+ end
187
213
 
188
- xx = x.clone
189
- yy = y.clone
190
214
 
191
- ::NMatrix::BLAS.cblas_rot(n, xx, incx, yy, incy, c, s)
215
+ #
216
+ # call-seq:
217
+ # rotg(ab) -> [Numeric, Numeric]
218
+ #
219
+ # Apply givens plane rotation to the coordinates (a,b), returning the cosine and sine of the angle theta.
220
+ #
221
+ # Since the givens rotation includes a square root, integers and rationals are disallowed.
222
+ #
223
+ # * *Arguments* :
224
+ # - +ab+ -> NVector with two elements
225
+ # * *Returns* :
226
+ # - Array with the results, in the format [cos(theta), sin(theta)]
227
+ # * *Raises* :
228
+ # - +ArgumentError+ -> Expected dense NVector of size 2
229
+ #
230
+ def rotg(ab)
231
+ raise(ArgumentError, "Expected dense NVector of size 2") unless ab.is_a?(NVector) && ab.size == 2
192
232
 
193
- return [xx,yy]
233
+ ::NMatrix::BLAS.cblas_rotg(ab)
194
234
  end
195
235
 
236
+
196
237
  #
197
238
  # call-seq:
198
- # asum(x, incx, n)
239
+ # asum(x, incx, n) -> Numeric
199
240
  #
200
241
  # Calculate the sum of absolute values of the entries of a vector +x+ of size +n+
201
242
  #