nmatrix 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +102 -10
- data/README.rdoc +24 -32
- data/Rakefile +1 -1
- data/ext/nmatrix/data/complex.h +9 -0
- data/ext/nmatrix/data/data.cpp +78 -4
- data/ext/nmatrix/data/data.h +86 -54
- data/ext/nmatrix/data/rational.h +2 -0
- data/ext/nmatrix/data/ruby_object.h +38 -8
- data/ext/nmatrix/extconf.rb +13 -7
- data/ext/nmatrix/nmatrix.cpp +262 -139
- data/ext/nmatrix/nmatrix.h +11 -4
- data/ext/nmatrix/storage/common.cpp +20 -13
- data/ext/nmatrix/storage/common.h +18 -12
- data/ext/nmatrix/storage/dense.cpp +122 -192
- data/ext/nmatrix/storage/dense.h +4 -2
- data/ext/nmatrix/storage/list.cpp +467 -636
- data/ext/nmatrix/storage/list.h +6 -3
- data/ext/nmatrix/storage/storage.cpp +83 -46
- data/ext/nmatrix/storage/storage.h +7 -7
- data/ext/nmatrix/storage/yale.cpp +621 -361
- data/ext/nmatrix/storage/yale.h +21 -9
- data/ext/nmatrix/ttable_helper.rb +27 -31
- data/ext/nmatrix/types.h +1 -1
- data/ext/nmatrix/util/math.cpp +9 -10
- data/ext/nmatrix/util/sl_list.cpp +1 -7
- data/ext/nmatrix/util/sl_list.h +0 -118
- data/lib/nmatrix/blas.rb +59 -18
- data/lib/nmatrix/monkeys.rb +0 -52
- data/lib/nmatrix/nmatrix.rb +136 -9
- data/lib/nmatrix/nvector.rb +33 -0
- data/lib/nmatrix/shortcuts.rb +95 -16
- data/lib/nmatrix/version.rb +1 -1
- data/lib/nmatrix/yale_functions.rb +25 -19
- data/spec/blas_spec.rb +1 -19
- data/spec/elementwise_spec.rb +132 -17
- data/spec/lapack_spec.rb +0 -3
- data/spec/nmatrix_list_spec.rb +18 -0
- data/spec/nmatrix_spec.rb +44 -18
- data/spec/nmatrix_yale_spec.rb +1 -3
- data/spec/shortcuts_spec.rb +26 -36
- data/spec/slice_spec.rb +2 -4
- metadata +2 -2
data/ext/nmatrix/storage/yale.h
CHANGED
@@ -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
|
-
|
204
|
-
|
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 =>
|
48
|
-
:int8_t =>
|
49
|
-
:int16_t =>
|
50
|
-
:int32_t =>
|
51
|
-
:int64_t =>
|
52
|
-
:float32_t =>
|
53
|
-
:float64_t =>
|
54
|
-
:Complex64 =>
|
55
|
-
:Complex128 =>
|
56
|
-
:Rational32 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128'
|
57
|
-
:Rational64 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128'
|
58
|
-
:Rational128 => nullify([:float32_t, :float64_t, :'nm::Complex64', :'nm::Complex128'
|
59
|
-
: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
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
data/ext/nmatrix/util/math.cpp
CHANGED
@@ -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
|
-
|
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
|
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
|
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
|
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
|
}
|
data/ext/nmatrix/util/sl_list.h
CHANGED
@@ -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
|
-
# - +
|
170
|
-
# - +
|
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
|
178
|
-
# - +ArgumentError+ ->
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
#
|