nmatrix 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/History.txt +31 -3
- data/Manifest.txt +5 -0
- data/README.rdoc +29 -27
- data/ext/nmatrix/binary_format.txt +53 -0
- data/ext/nmatrix/data/data.cpp +18 -18
- data/ext/nmatrix/data/data.h +38 -7
- data/ext/nmatrix/data/rational.h +13 -0
- data/ext/nmatrix/data/ruby_object.h +10 -0
- data/ext/nmatrix/extconf.rb +2 -0
- data/ext/nmatrix/nmatrix.cpp +655 -103
- data/ext/nmatrix/nmatrix.h +26 -14
- data/ext/nmatrix/ruby_constants.cpp +4 -0
- data/ext/nmatrix/ruby_constants.h +2 -0
- data/ext/nmatrix/storage/dense.cpp +99 -41
- data/ext/nmatrix/storage/dense.h +3 -3
- data/ext/nmatrix/storage/list.cpp +36 -14
- data/ext/nmatrix/storage/list.h +4 -4
- data/ext/nmatrix/storage/storage.cpp +19 -19
- data/ext/nmatrix/storage/storage.h +11 -11
- data/ext/nmatrix/storage/yale.cpp +17 -20
- data/ext/nmatrix/storage/yale.h +13 -11
- data/ext/nmatrix/util/io.cpp +25 -23
- data/ext/nmatrix/util/io.h +5 -5
- data/ext/nmatrix/util/math.cpp +634 -17
- data/ext/nmatrix/util/math.h +958 -9
- data/ext/nmatrix/util/sl_list.cpp +7 -7
- data/ext/nmatrix/util/sl_list.h +2 -2
- data/lib/nmatrix.rb +9 -0
- data/lib/nmatrix/blas.rb +4 -4
- data/lib/nmatrix/io/market.rb +227 -0
- data/lib/nmatrix/io/mat_reader.rb +7 -7
- data/lib/nmatrix/lapack.rb +80 -0
- data/lib/nmatrix/nmatrix.rb +78 -52
- data/lib/nmatrix/shortcuts.rb +486 -0
- data/lib/nmatrix/version.rb +1 -1
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/blas_spec.rb +59 -9
- data/spec/elementwise_spec.rb +25 -12
- data/spec/io_spec.rb +69 -1
- data/spec/lapack_spec.rb +53 -4
- data/spec/math_spec.rb +9 -0
- data/spec/nmatrix_list_spec.rb +95 -0
- data/spec/nmatrix_spec.rb +10 -53
- data/spec/nmatrix_yale_spec.rb +17 -15
- data/spec/shortcuts_spec.rb +154 -0
- metadata +22 -15
data/ext/nmatrix/extconf.rb
CHANGED
@@ -122,10 +122,12 @@ dir_config("atlas")
|
|
122
122
|
# (substituting in the path of your cblas.h and clapack.h for the path I used). -- JW 8/27/12
|
123
123
|
|
124
124
|
find_library("lapack", "clapack_dgetrf", "/usr/local/lib", "/usr/local/atlas/lib")
|
125
|
+
find_header("clapack.h", "/usr/local/atlas/include")
|
125
126
|
have_header("clapack.h")
|
126
127
|
|
127
128
|
find_library("cblas", "cblas_dgemm", "/usr/local/lib", "/usr/local/atlas/lib")
|
128
129
|
find_library("atlas", "ATL_dgemmNN", "/usr/local/lib", "/usr/local/atlas/lib", "/usr/lib")
|
130
|
+
find_header("cblas.h", "/usr/local/atlas/include")
|
129
131
|
have_header("cblas.h")
|
130
132
|
|
131
133
|
# Order matters here: ATLAS has to go after LAPACK: http://mail.scipy.org/pipermail/scipy-user/2007-January/010717.html
|
data/ext/nmatrix/nmatrix.cpp
CHANGED
@@ -39,6 +39,7 @@ extern "C" {
|
|
39
39
|
|
40
40
|
#include <ruby.h>
|
41
41
|
#include <algorithm> // std::min
|
42
|
+
#include <fstream>
|
42
43
|
|
43
44
|
/*
|
44
45
|
* Project Includes
|
@@ -77,6 +78,269 @@ extern "C" {
|
|
77
78
|
*/
|
78
79
|
|
79
80
|
|
81
|
+
namespace nm {
|
82
|
+
|
83
|
+
/*
|
84
|
+
* Read the shape from a matrix storage file, and ignore any padding.
|
85
|
+
*
|
86
|
+
* shape should already be allocated before calling this.
|
87
|
+
*/
|
88
|
+
template <typename IType>
|
89
|
+
void read_padded_shape(std::ifstream& f, size_t dim, size_t* shape) {
|
90
|
+
size_t bytes_read = 0;
|
91
|
+
|
92
|
+
// Read shape
|
93
|
+
for (size_t i = 0; i < dim; ++i) {
|
94
|
+
IType s;
|
95
|
+
f.read(reinterpret_cast<char*>(&s), sizeof(IType));
|
96
|
+
shape[i] = s;
|
97
|
+
|
98
|
+
bytes_read += sizeof(IType);
|
99
|
+
}
|
100
|
+
|
101
|
+
// Ignore padding
|
102
|
+
f.ignore(bytes_read % 8);
|
103
|
+
}
|
104
|
+
|
105
|
+
template <typename IType>
|
106
|
+
void write_padded_shape(std::ofstream& f, size_t dim, size_t* shape) {
|
107
|
+
size_t bytes_written = 0;
|
108
|
+
|
109
|
+
// Write shape
|
110
|
+
for (size_t i = 0; i < dim; ++i) {
|
111
|
+
IType s = shape[i];
|
112
|
+
f.write(reinterpret_cast<const char*>(&s), sizeof(IType));
|
113
|
+
|
114
|
+
bytes_written += sizeof(IType);
|
115
|
+
}
|
116
|
+
|
117
|
+
// Pad with zeros
|
118
|
+
while (bytes_written % 8) {
|
119
|
+
IType zero = 0;
|
120
|
+
f.write(reinterpret_cast<const char*>(&zero), sizeof(IType));
|
121
|
+
|
122
|
+
bytes_written += sizeof(IType);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
/*
|
127
|
+
* This function is pulled out separately so it can be called for hermitian matrix writing, which also uses it.
|
128
|
+
*/
|
129
|
+
template <typename DType>
|
130
|
+
size_t write_padded_dense_elements_upper(std::ofstream& f, DENSE_STORAGE* storage, symm_t symm) {
|
131
|
+
// Write upper triangular portion. Assume 2D square matrix.
|
132
|
+
DType* elements = reinterpret_cast<DType*>(storage->elements);
|
133
|
+
size_t length = storage->shape[0];
|
134
|
+
|
135
|
+
size_t bytes_written = 0;
|
136
|
+
|
137
|
+
for (size_t i = 0; i < length; ++i) { // which row are we on?
|
138
|
+
|
139
|
+
f.write( reinterpret_cast<const char*>( &(elements[ i*(length + 1) ]) ),
|
140
|
+
(length - i) * sizeof(DType) );
|
141
|
+
|
142
|
+
bytes_written += (length - i) * sizeof(DType);
|
143
|
+
}
|
144
|
+
return bytes_written;
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
/*
|
149
|
+
* We need to specialize for Hermitian matrices. The next six functions accomplish that specialization, basically
|
150
|
+
* by ensuring that non-complex matrices cannot read or write hermitians (which would cause big problems).
|
151
|
+
*/
|
152
|
+
template <typename DType>
|
153
|
+
size_t write_padded_dense_elements_herm(std::ofstream& f, DENSE_STORAGE* storage, symm_t symm) {
|
154
|
+
rb_raise(rb_eArgError, "cannot write a non-complex matrix as hermitian");
|
155
|
+
}
|
156
|
+
|
157
|
+
template <>
|
158
|
+
size_t write_padded_dense_elements_herm<Complex64>(std::ofstream& f, DENSE_STORAGE* storage, symm_t symm) {
|
159
|
+
return write_padded_dense_elements_upper<Complex64>(f, storage, symm);
|
160
|
+
}
|
161
|
+
|
162
|
+
template <>
|
163
|
+
size_t write_padded_dense_elements_herm<Complex128>(std::ofstream& f, DENSE_STORAGE* storage, symm_t symm) {
|
164
|
+
return write_padded_dense_elements_upper<Complex128>(f, storage, symm);
|
165
|
+
}
|
166
|
+
|
167
|
+
template <typename DType>
|
168
|
+
void read_padded_dense_elements_herm(DType* elements, size_t length) {
|
169
|
+
rb_raise(rb_eArgError, "cannot read a non-complex matrix as hermitian");
|
170
|
+
}
|
171
|
+
|
172
|
+
template <>
|
173
|
+
void read_padded_dense_elements_herm(Complex64* elements, size_t length) {
|
174
|
+
for (size_t i = 0; i < length; ++i) {
|
175
|
+
for (size_t j = i+1; j < length; ++j) {
|
176
|
+
elements[j * length + i] = elements[i * length + j].conjugate();
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
template <>
|
182
|
+
void read_padded_dense_elements_herm(Complex128* elements, size_t length) {
|
183
|
+
for (size_t i = 0; i < length; ++i) {
|
184
|
+
for (size_t j = i+1; j < length; ++j) {
|
185
|
+
elements[j * length + i] = elements[i * length + j].conjugate();
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
/*
|
192
|
+
* Read the elements of a dense storage matrix from a binary file, padded to 64-bits.
|
193
|
+
*
|
194
|
+
* storage should already be allocated. No initialization necessary.
|
195
|
+
*/
|
196
|
+
template <typename DType>
|
197
|
+
void read_padded_dense_elements(std::ifstream& f, DENSE_STORAGE* storage, nm::symm_t symm) {
|
198
|
+
size_t bytes_read = 0;
|
199
|
+
|
200
|
+
if (symm == nm::NONSYMM) {
|
201
|
+
// Easy. Simply read the whole elements array.
|
202
|
+
size_t length = nm_storage_count_max_elements(reinterpret_cast<STORAGE*>(storage));
|
203
|
+
f.read(reinterpret_cast<char*>(storage->elements), length * sizeof(DType) );
|
204
|
+
|
205
|
+
bytes_read += length * sizeof(DType);
|
206
|
+
} else if (symm == LOWER) {
|
207
|
+
|
208
|
+
// Read lower triangular portion and initialize remainder to 0
|
209
|
+
DType* elements = reinterpret_cast<DType*>(storage->elements);
|
210
|
+
size_t length = storage->shape[0];
|
211
|
+
|
212
|
+
for (size_t i = 0; i < length; ++i) { // which row?
|
213
|
+
|
214
|
+
f.read( reinterpret_cast<char*>(&(elements[i * length])), (i + 1) * sizeof(DType) );
|
215
|
+
|
216
|
+
// need to zero-fill the rest of the row.
|
217
|
+
for (size_t j = i+1; j < length; ++j)
|
218
|
+
elements[i * length + j] = 0;
|
219
|
+
|
220
|
+
bytes_read += (i + 1) * sizeof(DType);
|
221
|
+
}
|
222
|
+
} else {
|
223
|
+
|
224
|
+
DType* elements = reinterpret_cast<DType*>(storage->elements);
|
225
|
+
size_t length = storage->shape[0];
|
226
|
+
|
227
|
+
for (size_t i = 0; i < length; ++i) { // which row?
|
228
|
+
f.read( reinterpret_cast<char*>(&(elements[i * (length + 1)])), (length - i) * sizeof(DType) );
|
229
|
+
|
230
|
+
bytes_read += (length - i) * sizeof(DType);
|
231
|
+
}
|
232
|
+
|
233
|
+
if (symm == SYMM) {
|
234
|
+
for (size_t i = 0; i < length; ++i) {
|
235
|
+
for (size_t j = i+1; j < length; ++j) {
|
236
|
+
elements[j * length + i] = elements[i * length + j];
|
237
|
+
}
|
238
|
+
}
|
239
|
+
} else if (symm == SKEW) {
|
240
|
+
for (size_t i = 0; i < length; ++i) {
|
241
|
+
for (size_t j = i+1; j < length; ++j) {
|
242
|
+
elements[j * length + i] = -elements[i * length + j];
|
243
|
+
}
|
244
|
+
}
|
245
|
+
} else if (symm == HERM) {
|
246
|
+
read_padded_dense_elements_herm<DType>(elements, length);
|
247
|
+
|
248
|
+
} else if (symm == UPPER) { // zero-fill the rest of the rows
|
249
|
+
for (size_t i = 0; i < length; ++i) {
|
250
|
+
for(size_t j = i+1; j < length; ++j) {
|
251
|
+
elements[j * length + i] = 0;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
}
|
257
|
+
|
258
|
+
// Ignore any padding.
|
259
|
+
if (bytes_read % 8) f.ignore(bytes_read % 8);
|
260
|
+
}
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
template <typename DType, typename IType>
|
265
|
+
void write_padded_yale_elements(std::ofstream& f, YALE_STORAGE* storage, size_t length, nm::symm_t symm) {
|
266
|
+
if (symm != nm::NONSYMM) rb_raise(rb_eNotImpError, "Yale matrices can only be read/written in full form");
|
267
|
+
|
268
|
+
// Keep track of bytes written for each of A and IJA so we know how much padding to use.
|
269
|
+
size_t bytes_written = length * sizeof(DType);
|
270
|
+
|
271
|
+
// Write A array
|
272
|
+
f.write(reinterpret_cast<const char*>(storage->a), bytes_written);
|
273
|
+
|
274
|
+
// Padding
|
275
|
+
int64_t zero = 0;
|
276
|
+
f.write(reinterpret_cast<const char*>(&zero), bytes_written % 8);
|
277
|
+
|
278
|
+
bytes_written = length * sizeof(IType);
|
279
|
+
f.write(reinterpret_cast<const char*>(storage->ija), bytes_written);
|
280
|
+
|
281
|
+
// More padding
|
282
|
+
f.write(reinterpret_cast<const char*>(&zero), bytes_written % 8);
|
283
|
+
}
|
284
|
+
|
285
|
+
|
286
|
+
template <typename DType, typename IType>
|
287
|
+
void read_padded_yale_elements(std::ifstream& f, YALE_STORAGE* storage, size_t length, nm::symm_t symm) {
|
288
|
+
if (symm != NONSYMM) rb_raise(rb_eNotImpError, "Yale matrices can only be read/written in full form");
|
289
|
+
|
290
|
+
size_t bytes_read = length * sizeof(DType);
|
291
|
+
f.read(reinterpret_cast<char*>(storage->a), bytes_read);
|
292
|
+
|
293
|
+
int64_t padding = 0;
|
294
|
+
f.read(reinterpret_cast<char*>(&padding), bytes_read % 8);
|
295
|
+
|
296
|
+
bytes_read = length * sizeof(IType);
|
297
|
+
f.read(reinterpret_cast<char*>(storage->ija), bytes_read);
|
298
|
+
|
299
|
+
f.read(reinterpret_cast<char*>(&padding), bytes_read % 8);
|
300
|
+
}
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
/*
|
305
|
+
* Write the elements of a dense storage matrix to a binary file, padded to 64-bits.
|
306
|
+
*/
|
307
|
+
template <typename DType>
|
308
|
+
void write_padded_dense_elements(std::ofstream& f, DENSE_STORAGE* storage, nm::symm_t symm) {
|
309
|
+
size_t bytes_written = 0;
|
310
|
+
|
311
|
+
if (symm == nm::NONSYMM) {
|
312
|
+
// Simply write the whole elements array.
|
313
|
+
size_t length = nm_storage_count_max_elements(storage);
|
314
|
+
f.write(reinterpret_cast<const char*>(storage->elements), length * sizeof(DType));
|
315
|
+
|
316
|
+
bytes_written += length * sizeof(DType);
|
317
|
+
|
318
|
+
} else if (symm == nm::LOWER) {
|
319
|
+
|
320
|
+
// Write lower triangular portion. Assume 2D square matrix.
|
321
|
+
DType* elements = reinterpret_cast<DType*>(storage->elements);
|
322
|
+
size_t length = storage->shape[0];
|
323
|
+
for (size_t i = 0; i < length; ++i) { // which row?
|
324
|
+
|
325
|
+
f.write( reinterpret_cast<const char*>( &(elements[i * length]) ),
|
326
|
+
(i + 1) * sizeof(DType) );
|
327
|
+
|
328
|
+
bytes_written += (i + 1) * sizeof(DType);
|
329
|
+
}
|
330
|
+
} else if (symm == nm::HERM) {
|
331
|
+
bytes_written += write_padded_dense_elements_herm<DType>(f, storage, symm);
|
332
|
+
} else { // HERM, UPPER, SYMM, SKEW
|
333
|
+
bytes_written += write_padded_dense_elements_upper<DType>(f, storage, symm);
|
334
|
+
}
|
335
|
+
|
336
|
+
// Padding
|
337
|
+
int64_t zero = 0;
|
338
|
+
f.write(reinterpret_cast<const char*>(&zero), bytes_written % 8);
|
339
|
+
}
|
340
|
+
|
341
|
+
} // end of namespace nm
|
342
|
+
|
343
|
+
|
80
344
|
extern "C" {
|
81
345
|
|
82
346
|
/*
|
@@ -87,6 +351,8 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm);
|
|
87
351
|
static VALUE nm_init_copy(VALUE copy, VALUE original);
|
88
352
|
static VALUE nm_init_transposed(VALUE self);
|
89
353
|
static VALUE nm_init_cast_copy(VALUE self, VALUE new_stype_symbol, VALUE new_dtype_symbol);
|
354
|
+
static VALUE nm_read(int argc, VALUE* argv, VALUE self);
|
355
|
+
static VALUE nm_write(int argc, VALUE* argv, VALUE self);
|
90
356
|
static VALUE nm_to_hash(VALUE self);
|
91
357
|
static VALUE nm_init_yale_from_old_yale(VALUE shape, VALUE dtype, VALUE ia, VALUE ja, VALUE a, VALUE from_dtype, VALUE nm);
|
92
358
|
static VALUE nm_alloc(VALUE klass);
|
@@ -149,11 +415,10 @@ static VALUE nm_factorize_lu(VALUE self);
|
|
149
415
|
static VALUE nm_det_exact(VALUE self);
|
150
416
|
static VALUE nm_complex_conjugate_bang(VALUE self);
|
151
417
|
|
152
|
-
static dtype_t
|
153
|
-
static
|
154
|
-
static void* interpret_initial_value(VALUE arg, dtype_t dtype);
|
418
|
+
static nm::dtype_t interpret_dtype(int argc, VALUE* argv, nm::stype_t stype);
|
419
|
+
static void* interpret_initial_value(VALUE arg, nm::dtype_t dtype);
|
155
420
|
static size_t* interpret_shape(VALUE arg, size_t* dim);
|
156
|
-
static stype_t interpret_stype(VALUE arg);
|
421
|
+
static nm::stype_t interpret_stype(VALUE arg);
|
157
422
|
|
158
423
|
/* Singleton methods */
|
159
424
|
static VALUE nm_itype_by_shape(VALUE self, VALUE shape_arg);
|
@@ -197,13 +462,16 @@ void Init_nmatrix() {
|
|
197
462
|
|
198
463
|
rb_define_singleton_method(cNMatrix, "upcast", (METHOD)nm_upcast, 2);
|
199
464
|
rb_define_singleton_method(cNMatrix, "itype_by_shape", (METHOD)nm_itype_by_shape, 1);
|
200
|
-
|
465
|
+
|
201
466
|
//////////////////////
|
202
467
|
// Instance Methods //
|
203
468
|
//////////////////////
|
204
469
|
|
205
470
|
rb_define_method(cNMatrix, "initialize", (METHOD)nm_init, -1);
|
206
471
|
rb_define_method(cNMatrix, "initialize_copy", (METHOD)nm_init_copy, 1);
|
472
|
+
rb_define_singleton_method(cNMatrix, "read", (METHOD)nm_read, -1);
|
473
|
+
|
474
|
+
rb_define_method(cNMatrix, "write", (METHOD)nm_write, -1);
|
207
475
|
|
208
476
|
// Technically, the following function is a copy constructor.
|
209
477
|
rb_define_method(cNMatrix, "transpose", (METHOD)nm_init_transposed, 0);
|
@@ -317,15 +585,15 @@ static VALUE nm_capacity(VALUE self) {
|
|
317
585
|
VALUE cap;
|
318
586
|
|
319
587
|
switch(NM_STYPE(self)) {
|
320
|
-
case YALE_STORE:
|
588
|
+
case nm::YALE_STORE:
|
321
589
|
cap = UINT2NUM(((YALE_STORAGE*)(NM_STORAGE(self)))->capacity);
|
322
590
|
break;
|
323
591
|
|
324
|
-
case DENSE_STORE:
|
592
|
+
case nm::DENSE_STORE:
|
325
593
|
cap = UINT2NUM(nm_storage_count_max_elements( NM_STORAGE_DENSE(self) ));
|
326
594
|
break;
|
327
595
|
|
328
|
-
case LIST_STORE:
|
596
|
+
case nm::LIST_STORE:
|
329
597
|
cap = UINT2NUM(nm_list_storage_count_elements( NM_STORAGE_LIST(self) ));
|
330
598
|
break;
|
331
599
|
|
@@ -375,7 +643,7 @@ static VALUE nm_dtype(VALUE self) {
|
|
375
643
|
* Get the index data type (dtype) of a matrix. Defined only for yale; others return nil.
|
376
644
|
*/
|
377
645
|
static VALUE nm_itype(VALUE self) {
|
378
|
-
if (NM_STYPE(self) == YALE_STORE) {
|
646
|
+
if (NM_STYPE(self) == nm::YALE_STORE) {
|
379
647
|
ID itype = rb_intern(ITYPE_NAMES[NM_ITYPE(self)]);
|
380
648
|
return ID2SYM(itype);
|
381
649
|
}
|
@@ -391,8 +659,8 @@ static VALUE nm_itype_by_shape(VALUE self, VALUE shape_arg) {
|
|
391
659
|
size_t dim;
|
392
660
|
size_t* shape = interpret_shape(shape_arg, &dim);
|
393
661
|
|
394
|
-
itype_t itype = nm_yale_storage_itype_by_shape(shape);
|
395
|
-
ID itype_id
|
662
|
+
nm::itype_t itype = nm_yale_storage_itype_by_shape(shape);
|
663
|
+
ID itype_id = rb_intern(ITYPE_NAMES[itype]);
|
396
664
|
|
397
665
|
return ID2SYM(itype_id);
|
398
666
|
}
|
@@ -405,8 +673,8 @@ static VALUE nm_itype_by_shape(VALUE self, VALUE shape_arg) {
|
|
405
673
|
*/
|
406
674
|
static VALUE nm_upcast(VALUE self, VALUE t1, VALUE t2) {
|
407
675
|
|
408
|
-
dtype_t d1 = nm_dtype_from_rbsymbol(t1),
|
409
|
-
|
676
|
+
nm::dtype_t d1 = nm_dtype_from_rbsymbol(t1),
|
677
|
+
d2 = nm_dtype_from_rbsymbol(t2);
|
410
678
|
|
411
679
|
return ID2SYM(rb_intern( DTYPE_NAMES[ Upcast[d1][d2] ] ));
|
412
680
|
}
|
@@ -453,7 +721,7 @@ static VALUE nm_dense_each_indirect(VALUE nm) {
|
|
453
721
|
static VALUE nm_dense_each(VALUE nmatrix) {
|
454
722
|
volatile VALUE nm = nmatrix; // Not sure this actually does anything.
|
455
723
|
|
456
|
-
if (NM_DTYPE(nm) == RUBYOBJ) {
|
724
|
+
if (NM_DTYPE(nm) == nm::RUBYOBJ) {
|
457
725
|
|
458
726
|
// matrix of Ruby objects -- yield those objects directly
|
459
727
|
return nm_dense_each_direct(nm);
|
@@ -476,7 +744,7 @@ static VALUE nm_each(VALUE nmatrix) {
|
|
476
744
|
volatile VALUE nm = nmatrix; // not sure why we do this, but it gets done in ruby's array.c.
|
477
745
|
|
478
746
|
switch(NM_STYPE(nm)) {
|
479
|
-
case DENSE_STORE:
|
747
|
+
case nm::DENSE_STORE:
|
480
748
|
return nm_dense_each(nm);
|
481
749
|
default:
|
482
750
|
rb_raise(rb_eNotImpError, "only dense matrix's each method works right now");
|
@@ -508,13 +776,13 @@ static VALUE nm_eqeq(VALUE left, VALUE right) {
|
|
508
776
|
bool result = false;
|
509
777
|
|
510
778
|
switch(l->stype) {
|
511
|
-
case DENSE_STORE:
|
779
|
+
case nm::DENSE_STORE:
|
512
780
|
result = nm_dense_storage_eqeq(l->storage, r->storage);
|
513
781
|
break;
|
514
|
-
case LIST_STORE:
|
782
|
+
case nm::LIST_STORE:
|
515
783
|
result = nm_list_storage_eqeq(l->storage, r->storage);
|
516
784
|
break;
|
517
|
-
case YALE_STORE:
|
785
|
+
case nm::YALE_STORE:
|
518
786
|
result = nm_yale_storage_eqeq(l->storage, r->storage);
|
519
787
|
break;
|
520
788
|
}
|
@@ -558,12 +826,12 @@ static VALUE nm_complex_conjugate_bang(VALUE self) {
|
|
558
826
|
|
559
827
|
UnwrapNMatrix(self, m);
|
560
828
|
|
561
|
-
if (m->stype == DENSE_STORE) {
|
829
|
+
if (m->stype == nm::DENSE_STORE) {
|
562
830
|
|
563
831
|
size = nm_storage_count_max_elements(NM_STORAGE(self));
|
564
832
|
elem = NM_STORAGE_DENSE(self)->elements;
|
565
833
|
|
566
|
-
} else if (m->stype == YALE_STORE) {
|
834
|
+
} else if (m->stype == nm::YALE_STORE) {
|
567
835
|
|
568
836
|
size = nm_yale_storage_get_size(NM_STORAGE_YALE(self));
|
569
837
|
elem = NM_STORAGE_YALE(self)->a;
|
@@ -573,13 +841,13 @@ static VALUE nm_complex_conjugate_bang(VALUE self) {
|
|
573
841
|
}
|
574
842
|
|
575
843
|
// Walk through and negate the imaginary component
|
576
|
-
if (NM_DTYPE(self) == COMPLEX64) {
|
844
|
+
if (NM_DTYPE(self) == nm::COMPLEX64) {
|
577
845
|
|
578
846
|
for (p = 0; p < size; ++p) {
|
579
847
|
reinterpret_cast<nm::Complex64*>(elem)[p].i = -reinterpret_cast<nm::Complex64*>(elem)[p].i;
|
580
848
|
}
|
581
849
|
|
582
|
-
} else if (NM_DTYPE(self) == COMPLEX128) {
|
850
|
+
} else if (NM_DTYPE(self) == nm::COMPLEX128) {
|
583
851
|
|
584
852
|
for (p = 0; p < size; ++p) {
|
585
853
|
reinterpret_cast<nm::Complex128*>(elem)[p].i = -reinterpret_cast<nm::Complex128*>(elem)[p].i;
|
@@ -597,7 +865,7 @@ static VALUE nm_complex_conjugate_bang(VALUE self) {
|
|
597
865
|
* Helper function for creating a matrix. You have to create the storage and pass it in, but you don't
|
598
866
|
* need to worry about deleting it.
|
599
867
|
*/
|
600
|
-
NMATRIX* nm_create(stype_t stype, STORAGE* storage) {
|
868
|
+
NMATRIX* nm_create(nm::stype_t stype, STORAGE* storage) {
|
601
869
|
NMATRIX* mat = ALLOC(NMATRIX);
|
602
870
|
|
603
871
|
mat->stype = stype;
|
@@ -646,11 +914,11 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
646
914
|
}
|
647
915
|
|
648
916
|
/* First, determine stype (dense by default) */
|
649
|
-
stype_t stype;
|
917
|
+
nm::stype_t stype;
|
650
918
|
size_t offset = 0;
|
651
919
|
|
652
920
|
if (!SYMBOL_P(argv[0]) && TYPE(argv[0]) != T_STRING) {
|
653
|
-
stype = DENSE_STORE;
|
921
|
+
stype = nm::DENSE_STORE;
|
654
922
|
|
655
923
|
} else {
|
656
924
|
// 0: String or Symbol
|
@@ -660,7 +928,7 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
660
928
|
|
661
929
|
// If there are 7 arguments and Yale, refer to a different init function with fewer sanity checks.
|
662
930
|
if (argc == 7) {
|
663
|
-
if (stype == YALE_STORE) {
|
931
|
+
if (stype == nm::YALE_STORE) {
|
664
932
|
return nm_init_yale_from_old_yale(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], nm);
|
665
933
|
|
666
934
|
} else {
|
@@ -673,14 +941,14 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
673
941
|
size_t* shape = interpret_shape(argv[offset], &dim);
|
674
942
|
|
675
943
|
// 2-3: dtype
|
676
|
-
dtype_t dtype = interpret_dtype(argc-1-offset, argv+offset+1, stype);
|
944
|
+
nm::dtype_t dtype = interpret_dtype(argc-1-offset, argv+offset+1, stype);
|
677
945
|
|
678
946
|
size_t init_cap = 0, init_val_len = 0;
|
679
947
|
void* init_val = NULL;
|
680
948
|
if (NM_RUBYVAL_IS_NUMERIC(argv[1+offset]) || TYPE(argv[1+offset]) == T_ARRAY) {
|
681
949
|
// Initial value provided (could also be initial capacity, if yale).
|
682
950
|
|
683
|
-
if (stype == YALE_STORE) {
|
951
|
+
if (stype == nm::YALE_STORE) {
|
684
952
|
init_cap = FIX2UINT(argv[1+offset]);
|
685
953
|
|
686
954
|
} else {
|
@@ -694,12 +962,12 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
694
962
|
} else {
|
695
963
|
// DType is RUBYOBJ.
|
696
964
|
|
697
|
-
if (stype == DENSE_STORE) {
|
965
|
+
if (stype == nm::DENSE_STORE) {
|
698
966
|
/*
|
699
967
|
* No need to initialize dense with any kind of default value unless it's
|
700
968
|
* an RUBYOBJ matrix.
|
701
969
|
*/
|
702
|
-
if (dtype == RUBYOBJ) {
|
970
|
+
if (dtype == nm::RUBYOBJ) {
|
703
971
|
// Pretend [nil] was passed for RUBYOBJ.
|
704
972
|
init_val = ALLOC(VALUE);
|
705
973
|
*(VALUE*)init_val = Qnil;
|
@@ -709,7 +977,7 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
709
977
|
} else {
|
710
978
|
init_val = NULL;
|
711
979
|
}
|
712
|
-
} else if (stype == LIST_STORE) {
|
980
|
+
} else if (stype == nm::LIST_STORE) {
|
713
981
|
init_val = ALLOC_N(char, DTYPE_SIZES[dtype]);
|
714
982
|
std::memset(init_val, 0, DTYPE_SIZES[dtype]);
|
715
983
|
}
|
@@ -722,15 +990,15 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
722
990
|
nmatrix->stype = stype;
|
723
991
|
|
724
992
|
switch (stype) {
|
725
|
-
case DENSE_STORE:
|
993
|
+
case nm::DENSE_STORE:
|
726
994
|
nmatrix->storage = (STORAGE*)nm_dense_storage_create(dtype, shape, dim, init_val, init_val_len);
|
727
995
|
break;
|
728
996
|
|
729
|
-
case LIST_STORE:
|
997
|
+
case nm::LIST_STORE:
|
730
998
|
nmatrix->storage = (STORAGE*)nm_list_storage_create(dtype, shape, dim, init_val);
|
731
999
|
break;
|
732
1000
|
|
733
|
-
case YALE_STORE:
|
1001
|
+
case nm::YALE_STORE:
|
734
1002
|
nmatrix->storage = (STORAGE*)nm_yale_storage_create(dtype, shape, dim, init_cap);
|
735
1003
|
nm_yale_storage_init((YALE_STORAGE*)(nmatrix->storage));
|
736
1004
|
break;
|
@@ -746,7 +1014,7 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
746
1014
|
* Currently only works for list storage.
|
747
1015
|
*/
|
748
1016
|
static VALUE nm_to_hash(VALUE self) {
|
749
|
-
if (NM_STYPE(self) != LIST_STORE) {
|
1017
|
+
if (NM_STYPE(self) != nm::LIST_STORE) {
|
750
1018
|
rb_raise(rb_eNotImpError, "please cast to :list first");
|
751
1019
|
}
|
752
1020
|
|
@@ -758,8 +1026,8 @@ static VALUE nm_to_hash(VALUE self) {
|
|
758
1026
|
* Copy constructor for changing dtypes and stypes.
|
759
1027
|
*/
|
760
1028
|
static VALUE nm_init_cast_copy(VALUE self, VALUE new_stype_symbol, VALUE new_dtype_symbol) {
|
761
|
-
dtype_t new_dtype = nm_dtype_from_rbsymbol(new_dtype_symbol);
|
762
|
-
stype_t new_stype = nm_stype_from_rbsymbol(new_stype_symbol);
|
1029
|
+
nm::dtype_t new_dtype = nm_dtype_from_rbsymbol(new_dtype_symbol);
|
1030
|
+
nm::stype_t new_stype = nm_stype_from_rbsymbol(new_stype_symbol);
|
763
1031
|
|
764
1032
|
CheckNMatrixType(self);
|
765
1033
|
|
@@ -822,6 +1090,278 @@ static VALUE nm_init_copy(VALUE copy, VALUE original) {
|
|
822
1090
|
}
|
823
1091
|
|
824
1092
|
|
1093
|
+
/*
|
1094
|
+
* Get major, minor, and release components of NMatrix::VERSION. Store in function parameters.
|
1095
|
+
*/
|
1096
|
+
static void get_version_info(uint16_t& major, uint16_t& minor, uint16_t& release) {
|
1097
|
+
// Get VERSION and split it on periods. Result is an Array.
|
1098
|
+
VALUE version = rb_funcall(rb_const_get(cNMatrix, rb_intern("VERSION")), rb_intern("split"), 1, rb_str_new_cstr("."));
|
1099
|
+
VALUE* ary = RARRAY_PTR(version); // major, minor, and release
|
1100
|
+
|
1101
|
+
// Convert each to an integer
|
1102
|
+
VALUE maj = rb_funcall(ary[0], rb_intern("to_i"), 0);
|
1103
|
+
VALUE min = rb_funcall(ary[1], rb_intern("to_i"), 0);
|
1104
|
+
VALUE rel = rb_funcall(ary[2], rb_intern("to_i"), 0);
|
1105
|
+
|
1106
|
+
major = static_cast<uint16_t>(nm::RubyObject(maj));
|
1107
|
+
minor = static_cast<uint16_t>(nm::RubyObject(min));
|
1108
|
+
release = static_cast<uint16_t>(nm::RubyObject(rel));
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
|
1112
|
+
/*
|
1113
|
+
* Interpret the NMatrix::write symmetry argument (which should be nil or a symbol). Return a symm_t (enum).
|
1114
|
+
*/
|
1115
|
+
static nm::symm_t interpret_symm(VALUE symm) {
|
1116
|
+
if (symm == Qnil) return nm::NONSYMM;
|
1117
|
+
|
1118
|
+
ID rb_symm = rb_intern("symmetric"),
|
1119
|
+
rb_skew = rb_intern("skew"),
|
1120
|
+
rb_herm = rb_intern("hermitian");
|
1121
|
+
// nm_rb_upper, nm_rb_lower already set
|
1122
|
+
|
1123
|
+
ID symm_id = rb_to_id(symm);
|
1124
|
+
|
1125
|
+
if (symm_id == rb_symm) return nm::SYMM;
|
1126
|
+
else if (symm_id == rb_skew) return nm::SKEW;
|
1127
|
+
else if (symm_id == rb_herm) return nm::HERM;
|
1128
|
+
else if (symm_id == nm_rb_upper) return nm::UPPER;
|
1129
|
+
else if (symm_id == nm_rb_lower) return nm::LOWER;
|
1130
|
+
else rb_raise(rb_eArgError, "unrecognized symmetry argument");
|
1131
|
+
|
1132
|
+
return nm::NONSYMM;
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
|
1136
|
+
|
1137
|
+
void read_padded_shape(std::ifstream& f, size_t dim, size_t* shape, nm::itype_t itype) {
|
1138
|
+
NAMED_ITYPE_TEMPLATE_TABLE(ttable, nm::read_padded_shape, void, std::ifstream&, size_t, size_t*)
|
1139
|
+
|
1140
|
+
ttable[itype](f, dim, shape);
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
|
1144
|
+
void write_padded_shape(std::ofstream& f, size_t dim, size_t* shape, nm::itype_t itype) {
|
1145
|
+
NAMED_ITYPE_TEMPLATE_TABLE(ttable, nm::write_padded_shape, void, std::ofstream&, size_t, size_t*)
|
1146
|
+
|
1147
|
+
ttable[itype](f, dim, shape);
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
|
1151
|
+
void read_padded_yale_elements(std::ifstream& f, YALE_STORAGE* storage, size_t length, nm::symm_t symm, nm::dtype_t dtype, nm::itype_t itype) {
|
1152
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE_NO_ROBJ(ttable, nm::read_padded_yale_elements, void, std::ifstream&, YALE_STORAGE*, size_t, nm::symm_t)
|
1153
|
+
|
1154
|
+
ttable[dtype][itype](f, storage, length, symm);
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
|
1158
|
+
void write_padded_yale_elements(std::ofstream& f, YALE_STORAGE* storage, size_t length, nm::symm_t symm, nm::dtype_t dtype, nm::itype_t itype) {
|
1159
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE_NO_ROBJ(ttable, nm::write_padded_yale_elements, void, std::ofstream& f, YALE_STORAGE*, size_t, nm::symm_t)
|
1160
|
+
|
1161
|
+
ttable[dtype][itype](f, storage, length, symm);
|
1162
|
+
}
|
1163
|
+
|
1164
|
+
|
1165
|
+
void read_padded_dense_elements(std::ifstream& f, DENSE_STORAGE* storage, nm::symm_t symm, nm::dtype_t dtype) {
|
1166
|
+
NAMED_DTYPE_TEMPLATE_TABLE_NO_ROBJ(ttable, nm::read_padded_dense_elements, void, std::ifstream&, DENSE_STORAGE*, nm::symm_t)
|
1167
|
+
|
1168
|
+
ttable[dtype](f, storage, symm);
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
|
1172
|
+
void write_padded_dense_elements(std::ofstream& f, DENSE_STORAGE* storage, nm::symm_t symm, nm::dtype_t dtype) {
|
1173
|
+
NAMED_DTYPE_TEMPLATE_TABLE_NO_ROBJ(ttable, nm::write_padded_dense_elements, void, std::ofstream& f, DENSE_STORAGE*, nm::symm_t)
|
1174
|
+
|
1175
|
+
ttable[dtype](f, storage, symm);
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
|
1179
|
+
|
1180
|
+
/*
|
1181
|
+
* Binary file writer for NMatrix standard format. file should be a path, which we aren't going to
|
1182
|
+
* check very carefully (in other words, this function should generally be called from a Ruby
|
1183
|
+
* helper method). Function also takes a symmetry argument, which allows us to specify that we only want to
|
1184
|
+
* save the upper triangular portion of the matrix (or if the matrix is a lower triangular matrix, only
|
1185
|
+
* the lower triangular portion). nil means regular storage.
|
1186
|
+
*/
|
1187
|
+
static VALUE nm_write(int argc, VALUE* argv, VALUE self) {
|
1188
|
+
using std::ofstream;
|
1189
|
+
|
1190
|
+
if (argc < 1 || argc > 2) {
|
1191
|
+
rb_raise(rb_eArgError, "Expected one or two arguments");
|
1192
|
+
}
|
1193
|
+
VALUE file = argv[0],
|
1194
|
+
symm = argc == 1 ? Qnil : argv[1];
|
1195
|
+
|
1196
|
+
NMATRIX* nmatrix;
|
1197
|
+
UnwrapNMatrix( self, nmatrix );
|
1198
|
+
|
1199
|
+
nm::symm_t symm_ = interpret_symm(symm);
|
1200
|
+
nm::itype_t itype = (nmatrix->stype == nm::YALE_STORE) ? reinterpret_cast<YALE_STORAGE*>(nmatrix->storage)->itype : nm::UINT32;
|
1201
|
+
|
1202
|
+
if (nmatrix->storage->dtype == nm::RUBYOBJ) {
|
1203
|
+
rb_raise(rb_eNotImpError, "Ruby Object writing is not implemented yet");
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
// Get the dtype, stype, itype, and symm and ensure they're the correct number of bytes.
|
1207
|
+
uint8_t st = static_cast<uint8_t>(nmatrix->stype),
|
1208
|
+
dt = static_cast<uint8_t>(nmatrix->storage->dtype),
|
1209
|
+
sm = static_cast<uint8_t>(symm_),
|
1210
|
+
it = static_cast<uint8_t>(itype);
|
1211
|
+
uint16_t dim = nmatrix->storage->dim;
|
1212
|
+
|
1213
|
+
// Check arguments before starting to write.
|
1214
|
+
if (nmatrix->stype == nm::LIST_STORE) rb_raise(nm_eStorageTypeError, "cannot save list matrix; cast to yale or dense first");
|
1215
|
+
if (symm_ != nm::NONSYMM) {
|
1216
|
+
if (dim != 2) rb_raise(rb_eArgError, "symmetry/triangularity not defined for a non-2D matrix");
|
1217
|
+
if (nmatrix->storage->shape[0] != nmatrix->storage->shape[1])
|
1218
|
+
rb_raise(rb_eArgError, "symmetry/triangularity not defined for a non-square matrix");
|
1219
|
+
if (symm_ == nm::HERM &&
|
1220
|
+
dt != static_cast<uint8_t>(nm::COMPLEX64) && dt != static_cast<uint8_t>(nm::COMPLEX128) && dt != static_cast<uint8_t>(nm::RUBYOBJ))
|
1221
|
+
rb_raise(rb_eArgError, "cannot save a non-complex matrix as hermitian");
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
ofstream f(RSTRING_PTR(file), std::ios::out | std::ios::binary);
|
1225
|
+
|
1226
|
+
// Get the NMatrix version information.
|
1227
|
+
uint16_t major, minor, release, null16 = 0;
|
1228
|
+
get_version_info(major, minor, release);
|
1229
|
+
|
1230
|
+
// WRITE FIRST 64-BIT BLOCK
|
1231
|
+
f.write(reinterpret_cast<const char*>(&major), sizeof(uint16_t));
|
1232
|
+
f.write(reinterpret_cast<const char*>(&minor), sizeof(uint16_t));
|
1233
|
+
f.write(reinterpret_cast<const char*>(&release), sizeof(uint16_t));
|
1234
|
+
f.write(reinterpret_cast<const char*>(&null16), sizeof(uint16_t));
|
1235
|
+
|
1236
|
+
// WRITE SECOND 64-BIT BLOCK
|
1237
|
+
f.write(reinterpret_cast<const char*>(&dt), sizeof(uint8_t));
|
1238
|
+
f.write(reinterpret_cast<const char*>(&st), sizeof(uint8_t));
|
1239
|
+
f.write(reinterpret_cast<const char*>(&it), sizeof(uint8_t));
|
1240
|
+
f.write(reinterpret_cast<const char*>(&sm), sizeof(uint8_t));
|
1241
|
+
f.write(reinterpret_cast<const char*>(&null16), sizeof(uint16_t));
|
1242
|
+
f.write(reinterpret_cast<const char*>(&dim), sizeof(uint16_t));
|
1243
|
+
|
1244
|
+
// Write shape (in 64-bit blocks)
|
1245
|
+
write_padded_shape(f, nmatrix->storage->dim, nmatrix->storage->shape, itype);
|
1246
|
+
|
1247
|
+
if (nmatrix->stype == nm::DENSE_STORE) {
|
1248
|
+
write_padded_dense_elements(f, reinterpret_cast<DENSE_STORAGE*>(nmatrix->storage), symm_, nmatrix->storage->dtype);
|
1249
|
+
} else if (nmatrix->stype == nm::YALE_STORE) {
|
1250
|
+
YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(nmatrix->storage);
|
1251
|
+
uint32_t ndnz = s->ndnz,
|
1252
|
+
length = nm_yale_storage_get_size(s);
|
1253
|
+
f.write(reinterpret_cast<const char*>(&ndnz), sizeof(uint32_t));
|
1254
|
+
f.write(reinterpret_cast<const char*>(&length), sizeof(uint32_t));
|
1255
|
+
|
1256
|
+
write_padded_yale_elements(f, s, length, symm_, s->dtype, itype);
|
1257
|
+
}
|
1258
|
+
|
1259
|
+
f.close();
|
1260
|
+
|
1261
|
+
return Qtrue;
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
|
1265
|
+
/*
|
1266
|
+
* Binary file reader for NMatrix standard format. file should be a path, which we aren't going to
|
1267
|
+
* check very carefully (in other words, this function should generally be called from a Ruby
|
1268
|
+
* helper method).
|
1269
|
+
*
|
1270
|
+
* Note that currently, this function will by default refuse to read files that are newer than
|
1271
|
+
* your version of NMatrix. To force an override, set the second argument to anything other than nil.
|
1272
|
+
*
|
1273
|
+
* Returns an NMatrix Ruby object.
|
1274
|
+
*/
|
1275
|
+
static VALUE nm_read(int argc, VALUE* argv, VALUE self) {
|
1276
|
+
using std::ifstream;
|
1277
|
+
|
1278
|
+
// Read the arguments
|
1279
|
+
if (argc < 1 || argc > 2) {
|
1280
|
+
rb_raise(rb_eArgError, "expected one or two arguments");
|
1281
|
+
}
|
1282
|
+
VALUE file = argv[0];
|
1283
|
+
bool force = argc == 1 ? false : argv[1];
|
1284
|
+
|
1285
|
+
// Open a file stream
|
1286
|
+
ifstream f(RSTRING_PTR(file), std::ios::in | std::ios::binary);
|
1287
|
+
|
1288
|
+
uint16_t major, minor, release;
|
1289
|
+
get_version_info(major, minor, release); // compare to NMatrix version
|
1290
|
+
|
1291
|
+
uint16_t fmajor, fminor, frelease, null16;
|
1292
|
+
|
1293
|
+
// READ FIRST 64-BIT BLOCK
|
1294
|
+
f.read(reinterpret_cast<char*>(&fmajor), sizeof(uint16_t));
|
1295
|
+
f.read(reinterpret_cast<char*>(&fminor), sizeof(uint16_t));
|
1296
|
+
f.read(reinterpret_cast<char*>(&frelease), sizeof(uint16_t));
|
1297
|
+
f.read(reinterpret_cast<char*>(&null16), sizeof(uint16_t));
|
1298
|
+
|
1299
|
+
int ver = major * 10000 + minor * 100 + release,
|
1300
|
+
fver = fmajor * 10000 + fminor * 100 + release;
|
1301
|
+
if (fver > ver && force == false) {
|
1302
|
+
rb_raise(rb_eIOError, "File was created in newer version of NMatrix than current");
|
1303
|
+
}
|
1304
|
+
if (null16 != 0) fprintf(stderr, "Warning: Expected zero padding was not zero\n");
|
1305
|
+
|
1306
|
+
uint8_t dt, st, it, sm;
|
1307
|
+
uint16_t dim;
|
1308
|
+
|
1309
|
+
// READ SECOND 64-BIT BLOCK
|
1310
|
+
f.read(reinterpret_cast<char*>(&dt), sizeof(uint8_t));
|
1311
|
+
f.read(reinterpret_cast<char*>(&st), sizeof(uint8_t));
|
1312
|
+
f.read(reinterpret_cast<char*>(&it), sizeof(uint8_t));
|
1313
|
+
f.read(reinterpret_cast<char*>(&sm), sizeof(uint8_t));
|
1314
|
+
f.read(reinterpret_cast<char*>(&null16), sizeof(uint16_t));
|
1315
|
+
f.read(reinterpret_cast<char*>(&dim), sizeof(uint16_t));
|
1316
|
+
|
1317
|
+
if (null16 != 0) fprintf(stderr, "Warning: Expected zero padding was not zero\n");
|
1318
|
+
nm::stype_t stype = static_cast<nm::stype_t>(st);
|
1319
|
+
nm::dtype_t dtype = static_cast<nm::dtype_t>(dt);
|
1320
|
+
nm::symm_t symm = static_cast<nm::symm_t>(sm);
|
1321
|
+
nm::itype_t itype = static_cast<nm::itype_t>(it);
|
1322
|
+
|
1323
|
+
// READ NEXT FEW 64-BIT BLOCKS
|
1324
|
+
size_t* shape = ALLOC_N(size_t, dim);
|
1325
|
+
read_padded_shape(f, dim, shape, itype);
|
1326
|
+
|
1327
|
+
VALUE klass = dim == 1 ? cNVector : cNMatrix;
|
1328
|
+
|
1329
|
+
STORAGE* s;
|
1330
|
+
if (stype == nm::DENSE_STORE) {
|
1331
|
+
s = nm_dense_storage_create(dtype, shape, dim, NULL, 0);
|
1332
|
+
|
1333
|
+
read_padded_dense_elements(f, reinterpret_cast<DENSE_STORAGE*>(s), symm, dtype);
|
1334
|
+
|
1335
|
+
} else if (stype == nm::YALE_STORE) {
|
1336
|
+
uint32_t ndnz, length;
|
1337
|
+
|
1338
|
+
// READ YALE-SPECIFIC 64-BIT BLOCK
|
1339
|
+
f.read(reinterpret_cast<char*>(&ndnz), sizeof(uint32_t));
|
1340
|
+
f.read(reinterpret_cast<char*>(&length), sizeof(uint32_t));
|
1341
|
+
|
1342
|
+
s = nm_yale_storage_create(dtype, shape, dim, length); // set length as init capacity
|
1343
|
+
|
1344
|
+
read_padded_yale_elements(f, reinterpret_cast<YALE_STORAGE*>(s), length, symm, dtype, itype);
|
1345
|
+
} else {
|
1346
|
+
rb_raise(nm_eStorageTypeError, "please convert to yale or dense before saving");
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
NMATRIX* nm = nm_create(stype, s);
|
1350
|
+
|
1351
|
+
// Return the appropriate matrix object (Ruby VALUE)
|
1352
|
+
switch(stype) {
|
1353
|
+
case nm::DENSE_STORE:
|
1354
|
+
return Data_Wrap_Struct(klass, nm_dense_storage_mark, nm_delete, nm);
|
1355
|
+
case nm::YALE_STORE:
|
1356
|
+
return Data_Wrap_Struct(cNMatrix, nm_yale_storage_mark, nm_delete, nm);
|
1357
|
+
default:
|
1358
|
+
return Qnil;
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
|
1364
|
+
|
825
1365
|
/*
|
826
1366
|
* Create a new NMatrix helper for handling internal ia, ja, and a arguments.
|
827
1367
|
*
|
@@ -831,16 +1371,16 @@ static VALUE nm_init_copy(VALUE copy, VALUE original) {
|
|
831
1371
|
static VALUE nm_init_yale_from_old_yale(VALUE shape, VALUE dtype, VALUE ia, VALUE ja, VALUE a, VALUE from_dtype, VALUE nm) {
|
832
1372
|
size_t dim = 2;
|
833
1373
|
size_t* shape_ = interpret_shape(shape, &dim);
|
834
|
-
dtype_t dtype_ = nm_dtype_from_rbsymbol(dtype);
|
1374
|
+
nm::dtype_t dtype_ = nm_dtype_from_rbsymbol(dtype);
|
835
1375
|
char *ia_ = RSTRING_PTR(ia),
|
836
1376
|
*ja_ = RSTRING_PTR(ja),
|
837
1377
|
*a_ = RSTRING_PTR(a);
|
838
|
-
dtype_t from_dtype_ = nm_dtype_from_rbsymbol(from_dtype);
|
1378
|
+
nm::dtype_t from_dtype_ = nm_dtype_from_rbsymbol(from_dtype);
|
839
1379
|
NMATRIX* nmatrix;
|
840
1380
|
|
841
1381
|
UnwrapNMatrix( nm, nmatrix );
|
842
1382
|
|
843
|
-
nmatrix->stype = YALE_STORE;
|
1383
|
+
nmatrix->stype = nm::YALE_STORE;
|
844
1384
|
nmatrix->storage = (STORAGE*)nm_yale_storage_create_from_old_yale(dtype_, shape_, ia_, ja_, a_, from_dtype_);
|
845
1385
|
|
846
1386
|
return nm;
|
@@ -851,11 +1391,11 @@ static VALUE nm_init_yale_from_old_yale(VALUE shape, VALUE dtype, VALUE ia, VALU
|
|
851
1391
|
*/
|
852
1392
|
static VALUE nm_is_ref(VALUE self) {
|
853
1393
|
// Refs only allowed for dense and list matrices.
|
854
|
-
if (NM_STYPE(self) == DENSE_STORE) {
|
1394
|
+
if (NM_STYPE(self) == nm::DENSE_STORE) {
|
855
1395
|
return (NM_DENSE_SRC(self) == NM_STORAGE(self)) ? Qfalse : Qtrue;
|
856
1396
|
}
|
857
1397
|
|
858
|
-
if (NM_STYPE(self) == LIST_STORE) {
|
1398
|
+
if (NM_STYPE(self) == nm::LIST_STORE) {
|
859
1399
|
return (NM_LIST_SRC(self) == NM_STORAGE(self)) ? Qfalse : Qtrue;
|
860
1400
|
}
|
861
1401
|
|
@@ -921,10 +1461,10 @@ static VALUE nm_mset(int argc, VALUE* argv, VALUE self) {
|
|
921
1461
|
// FIXME: Can't use a function pointer table here currently because these functions have different
|
922
1462
|
// signatures (namely the return type).
|
923
1463
|
switch(NM_STYPE(self)) {
|
924
|
-
case DENSE_STORE:
|
1464
|
+
case nm::DENSE_STORE:
|
925
1465
|
nm_dense_storage_set(NM_STORAGE(self), slice, value);
|
926
1466
|
break;
|
927
|
-
case LIST_STORE:
|
1467
|
+
case nm::LIST_STORE:
|
928
1468
|
// Remove if it's a zero, insert otherwise
|
929
1469
|
if (!std::memcmp(value, NM_STORAGE_LIST(self)->default_val, DTYPE_SIZES[NM_DTYPE(self)])) {
|
930
1470
|
free(value);
|
@@ -934,7 +1474,7 @@ static VALUE nm_mset(int argc, VALUE* argv, VALUE self) {
|
|
934
1474
|
nm_list_storage_insert(NM_STORAGE(self), slice, value);
|
935
1475
|
}
|
936
1476
|
break;
|
937
|
-
case YALE_STORE:
|
1477
|
+
case nm::YALE_STORE:
|
938
1478
|
nm_yale_storage_set(NM_STORAGE(self), slice, value);
|
939
1479
|
break;
|
940
1480
|
}
|
@@ -988,6 +1528,8 @@ static VALUE nm_multiply(VALUE left_v, VALUE right_v) {
|
|
988
1528
|
return Qnil;
|
989
1529
|
}
|
990
1530
|
|
1531
|
+
|
1532
|
+
|
991
1533
|
/*
|
992
1534
|
* LU factorization of a matrix.
|
993
1535
|
*
|
@@ -995,7 +1537,7 @@ static VALUE nm_multiply(VALUE left_v, VALUE right_v) {
|
|
995
1537
|
* FIXME: result again. Ideally, this would be an in-place factorize instead, and would be called nm_factorize_lu_bang.
|
996
1538
|
*/
|
997
1539
|
static VALUE nm_factorize_lu(VALUE self) {
|
998
|
-
if (NM_STYPE(self) != DENSE_STORE) {
|
1540
|
+
if (NM_STYPE(self) != nm::DENSE_STORE) {
|
999
1541
|
rb_raise(rb_eNotImpError, "only implemented for dense storage");
|
1000
1542
|
}
|
1001
1543
|
|
@@ -1089,8 +1631,8 @@ static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(STORAGE*, SLIC
|
|
1089
1631
|
nm_yale_storage_ref
|
1090
1632
|
};
|
1091
1633
|
|
1092
|
-
if (NM_DTYPE(self) == RUBYOBJ) result = *reinterpret_cast<VALUE*>( ttable[NM_STYPE(self)](NM_STORAGE(self), slice) );
|
1093
|
-
else
|
1634
|
+
if (NM_DTYPE(self) == nm::RUBYOBJ) result = *reinterpret_cast<VALUE*>( ttable[NM_STYPE(self)](NM_STORAGE(self), slice) );
|
1635
|
+
else result = rubyobj_from_cval( ttable[NM_STYPE(self)](NM_STORAGE(self), slice), NM_DTYPE(self) ).rval;
|
1094
1636
|
|
1095
1637
|
} else {
|
1096
1638
|
STYPE_MARK_TABLE(mark_table);
|
@@ -1119,54 +1661,64 @@ static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(STORAGE*, SLIC
|
|
1119
1661
|
static VALUE elementwise_op(nm::ewop_t op, VALUE left_val, VALUE right_val) {
|
1120
1662
|
STYPE_MARK_TABLE(mark);
|
1121
1663
|
|
1122
|
-
static STORAGE* (*ew_op[nm::NUM_STYPES])(nm::ewop_t, const STORAGE*, const STORAGE
|
1664
|
+
static STORAGE* (*ew_op[nm::NUM_STYPES])(nm::ewop_t, const STORAGE*, const STORAGE*, VALUE scalar) = {
|
1123
1665
|
nm_dense_storage_ew_op,
|
1124
1666
|
nm_list_storage_ew_op,
|
1125
1667
|
nm_yale_storage_ew_op
|
1126
1668
|
// NULL
|
1127
1669
|
};
|
1128
1670
|
|
1129
|
-
NMATRIX*
|
1671
|
+
NMATRIX *result = ALLOC(NMATRIX), *left;
|
1130
1672
|
|
1131
1673
|
CheckNMatrixType(left_val);
|
1132
|
-
|
1674
|
+
UnwrapNMatrix(left_val, left);
|
1133
1675
|
|
1134
|
-
|
1135
|
-
|
1136
|
-
rb_raise(rb_eArgError, "The left- and right-hand sides of the operation must have the same dimensionality.");
|
1137
|
-
}
|
1138
|
-
|
1139
|
-
// Check that the left- and right-hand sides have the same shape.
|
1140
|
-
if (memcmp(&NM_SHAPE(left_val, 0), &NM_SHAPE(right_val, 0), sizeof(size_t) * NM_DIM(left_val)) != 0) {
|
1141
|
-
rb_raise(rb_eArgError, "The left- and right-hand sides of the operation must have the same shape.");
|
1142
|
-
}
|
1676
|
+
if (TYPE(right_val) != T_DATA || (RDATA(right_val)->dfree != (RUBY_DATA_FUNC)nm_delete && RDATA(right_val)->dfree != (RUBY_DATA_FUNC)nm_delete_ref)) {
|
1677
|
+
// This is a matrix-scalar element-wise operation.
|
1143
1678
|
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1679
|
+
if (left->stype != nm::YALE_STORE) {
|
1680
|
+
result->storage = ew_op[left->stype](op, reinterpret_cast<STORAGE*>(left->storage), NULL, right_val);
|
1681
|
+
result->stype = left->stype;
|
1682
|
+
} else {
|
1683
|
+
rb_raise(rb_eNotImpError, "Scalar element-wise operations not implemented for Yale storage yet");
|
1684
|
+
}
|
1685
|
+
|
1686
|
+
} else {
|
1687
|
+
|
1688
|
+
// Check that the left- and right-hand sides have the same dimensionality.
|
1689
|
+
if (NM_DIM(left_val) != NM_DIM(right_val)) {
|
1690
|
+
rb_raise(rb_eArgError, "The left- and right-hand sides of the operation must have the same dimensionality.");
|
1691
|
+
}
|
1692
|
+
|
1693
|
+
// Check that the left- and right-hand sides have the same shape.
|
1694
|
+
if (memcmp(&NM_SHAPE(left_val, 0), &NM_SHAPE(right_val, 0), sizeof(size_t) * NM_DIM(left_val)) != 0) {
|
1695
|
+
rb_raise(rb_eArgError, "The left- and right-hand sides of the operation must have the same shape.");
|
1696
|
+
}
|
1697
|
+
|
1698
|
+
NMATRIX* right;
|
1699
|
+
UnwrapNMatrix(right_val, right);
|
1147
1700
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
} else {
|
1158
|
-
rb_raise(rb_eArgError, "Element-wise operations are not currently supported between matrices with differing stypes.");
|
1159
|
-
}
|
1701
|
+
if (left->stype == right->stype) {
|
1702
|
+
|
1703
|
+
result->storage = ew_op[left->stype](op, reinterpret_cast<STORAGE*>(left->storage), reinterpret_cast<STORAGE*>(right->storage), Qnil);
|
1704
|
+
result->stype = left->stype;
|
1705
|
+
|
1706
|
+
} else {
|
1707
|
+
rb_raise(rb_eArgError, "Element-wise operations are not currently supported between matrices with differing stypes.");
|
1708
|
+
}
|
1709
|
+
}
|
1160
1710
|
|
1161
1711
|
return Data_Wrap_Struct(cNMatrix, mark[result->stype], nm_delete, result);
|
1162
1712
|
}
|
1163
1713
|
|
1714
|
+
|
1715
|
+
|
1164
1716
|
/*
|
1165
1717
|
* Check to determine whether matrix is a reference to another matrix.
|
1166
1718
|
*/
|
1167
1719
|
bool is_ref(const NMATRIX* matrix) {
|
1168
1720
|
// FIXME: Needs to work for other types
|
1169
|
-
if (matrix->stype != DENSE_STORE) {
|
1721
|
+
if (matrix->stype != nm::DENSE_STORE) {
|
1170
1722
|
return false;
|
1171
1723
|
}
|
1172
1724
|
|
@@ -1181,7 +1733,7 @@ static VALUE is_symmetric(VALUE self, bool hermitian) {
|
|
1181
1733
|
UnwrapNMatrix(self, m);
|
1182
1734
|
|
1183
1735
|
if (m->storage->shape[0] == m->storage->shape[1] and m->storage->dim == 2) {
|
1184
|
-
if (NM_STYPE(self) == DENSE_STORE) {
|
1736
|
+
if (NM_STYPE(self) == nm::DENSE_STORE) {
|
1185
1737
|
if (hermitian) {
|
1186
1738
|
nm_dense_storage_is_hermitian((DENSE_STORAGE*)(m->storage), m->storage->shape[0]);
|
1187
1739
|
|
@@ -1209,15 +1761,15 @@ static VALUE is_symmetric(VALUE self, bool hermitian) {
|
|
1209
1761
|
*
|
1210
1762
|
* TODO: Probably needs some work for Bignum.
|
1211
1763
|
*/
|
1212
|
-
|
1764
|
+
nm::dtype_t nm_dtype_guess(VALUE v) {
|
1213
1765
|
switch(TYPE(v)) {
|
1214
1766
|
case T_TRUE:
|
1215
1767
|
case T_FALSE:
|
1216
|
-
return BYTE;
|
1768
|
+
return nm::BYTE;
|
1217
1769
|
|
1218
1770
|
case T_STRING:
|
1219
1771
|
if (RSTRING_LEN(v) == 1) {
|
1220
|
-
return BYTE;
|
1772
|
+
return nm::BYTE;
|
1221
1773
|
|
1222
1774
|
} else {
|
1223
1775
|
rb_raise(rb_eArgError, "Strings of length > 1 may not be stored in a matrix.");
|
@@ -1225,45 +1777,45 @@ static dtype_t dtype_guess(VALUE v) {
|
|
1225
1777
|
|
1226
1778
|
#if SIZEOF_INT == 8
|
1227
1779
|
case T_FIXNUM:
|
1228
|
-
return INT64;
|
1780
|
+
return nm::INT64;
|
1229
1781
|
|
1230
1782
|
case T_RATIONAL:
|
1231
|
-
return RATIONAL128;
|
1783
|
+
return nm::RATIONAL128;
|
1232
1784
|
|
1233
1785
|
#else
|
1234
1786
|
# if SIZEOF_INT == 4
|
1235
1787
|
case T_FIXNUM:
|
1236
|
-
return INT32;
|
1788
|
+
return nm::INT32;
|
1237
1789
|
|
1238
1790
|
case T_RATIONAL:
|
1239
|
-
return RATIONAL64;
|
1791
|
+
return nm::RATIONAL64;
|
1240
1792
|
|
1241
1793
|
#else
|
1242
1794
|
case T_FIXNUM:
|
1243
|
-
return INT16;
|
1795
|
+
return nm::INT16;
|
1244
1796
|
|
1245
1797
|
case T_RATIONAL:
|
1246
|
-
return RATIONAL32;
|
1798
|
+
return nm::RATIONAL32;
|
1247
1799
|
# endif
|
1248
1800
|
#endif
|
1249
1801
|
|
1250
1802
|
case T_BIGNUM:
|
1251
|
-
return INT64;
|
1803
|
+
return nm::INT64;
|
1252
1804
|
|
1253
1805
|
#if SIZEOF_FLOAT == 4
|
1254
1806
|
case T_COMPLEX:
|
1255
|
-
return COMPLEX128;
|
1807
|
+
return nm::COMPLEX128;
|
1256
1808
|
|
1257
1809
|
case T_FLOAT:
|
1258
|
-
return FLOAT64;
|
1810
|
+
return nm::FLOAT64;
|
1259
1811
|
|
1260
1812
|
#else
|
1261
1813
|
# if SIZEOF_FLOAT == 2
|
1262
1814
|
case T_COMPLEX:
|
1263
|
-
return COMPLEX64;
|
1815
|
+
return nm::COMPLEX64;
|
1264
1816
|
|
1265
1817
|
case T_FLOAT:
|
1266
|
-
return FLOAT32;
|
1818
|
+
return nm::FLOAT32;
|
1267
1819
|
# endif
|
1268
1820
|
#endif
|
1269
1821
|
|
@@ -1274,7 +1826,7 @@ static dtype_t dtype_guess(VALUE v) {
|
|
1274
1826
|
* TODO: Look at entire array for most specific type.
|
1275
1827
|
*/
|
1276
1828
|
|
1277
|
-
return
|
1829
|
+
return nm_dtype_guess(RARRAY_PTR(v)[0]);
|
1278
1830
|
|
1279
1831
|
case T_NIL:
|
1280
1832
|
default:
|
@@ -1343,7 +1895,7 @@ static double get_time(void) {
|
|
1343
1895
|
* initial or dtype. If 2, is initial and dtype. This function returns the
|
1344
1896
|
* dtype.
|
1345
1897
|
*/
|
1346
|
-
static dtype_t interpret_dtype(int argc, VALUE* argv, stype_t stype) {
|
1898
|
+
static nm::dtype_t interpret_dtype(int argc, VALUE* argv, nm::stype_t stype) {
|
1347
1899
|
int offset;
|
1348
1900
|
|
1349
1901
|
switch (argc) {
|
@@ -1366,18 +1918,18 @@ static dtype_t interpret_dtype(int argc, VALUE* argv, stype_t stype) {
|
|
1366
1918
|
} else if (TYPE(argv[offset]) == T_STRING) {
|
1367
1919
|
return nm_dtype_from_rbstring(StringValue(argv[offset]));
|
1368
1920
|
|
1369
|
-
} else if (stype == YALE_STORE) {
|
1921
|
+
} else if (stype == nm::YALE_STORE) {
|
1370
1922
|
rb_raise(rb_eArgError, "Yale storage class requires a dtype.");
|
1371
1923
|
|
1372
1924
|
} else {
|
1373
|
-
return
|
1925
|
+
return nm_dtype_guess(argv[0]);
|
1374
1926
|
}
|
1375
1927
|
}
|
1376
1928
|
|
1377
1929
|
/*
|
1378
1930
|
* Convert an Ruby value or an array of Ruby values into initial C values.
|
1379
1931
|
*/
|
1380
|
-
static void* interpret_initial_value(VALUE arg, dtype_t dtype) {
|
1932
|
+
static void* interpret_initial_value(VALUE arg, nm::dtype_t dtype) {
|
1381
1933
|
unsigned int index;
|
1382
1934
|
void* init_val;
|
1383
1935
|
|
@@ -1432,7 +1984,7 @@ static size_t* interpret_shape(VALUE arg, size_t* dim) {
|
|
1432
1984
|
/*
|
1433
1985
|
* Convert a Ruby symbol or string into an storage type.
|
1434
1986
|
*/
|
1435
|
-
static stype_t interpret_stype(VALUE arg) {
|
1987
|
+
static nm::stype_t interpret_stype(VALUE arg) {
|
1436
1988
|
if (SYMBOL_P(arg)) {
|
1437
1989
|
return nm_stype_from_rbsymbol(arg);
|
1438
1990
|
|
@@ -1450,7 +2002,7 @@ static stype_t interpret_stype(VALUE arg) {
|
|
1450
2002
|
//////////////////
|
1451
2003
|
|
1452
2004
|
|
1453
|
-
STORAGE* matrix_storage_cast_alloc(NMATRIX* matrix, dtype_t new_dtype) {
|
2005
|
+
STORAGE* matrix_storage_cast_alloc(NMATRIX* matrix, nm::dtype_t new_dtype) {
|
1454
2006
|
if (matrix->storage->dtype == new_dtype && !is_ref(matrix))
|
1455
2007
|
return matrix->storage;
|
1456
2008
|
|
@@ -1461,7 +2013,7 @@ STORAGE* matrix_storage_cast_alloc(NMATRIX* matrix, dtype_t new_dtype) {
|
|
1461
2013
|
|
1462
2014
|
STORAGE_PAIR binary_storage_cast_alloc(NMATRIX* left_matrix, NMATRIX* right_matrix) {
|
1463
2015
|
STORAGE_PAIR casted;
|
1464
|
-
dtype_t new_dtype = Upcast[left_matrix->storage->dtype][right_matrix->storage->dtype];
|
2016
|
+
nm::dtype_t new_dtype = Upcast[left_matrix->storage->dtype][right_matrix->storage->dtype];
|
1465
2017
|
|
1466
2018
|
casted.left = matrix_storage_cast_alloc(left_matrix, new_dtype);
|
1467
2019
|
casted.right = matrix_storage_cast_alloc(right_matrix, new_dtype);
|
@@ -1530,7 +2082,7 @@ static VALUE matrix_multiply(NMATRIX* left, NMATRIX* right) {
|
|
1530
2082
|
* Note: Currently only implemented for 2x2 and 3x3 matrices.
|
1531
2083
|
*/
|
1532
2084
|
static VALUE nm_det_exact(VALUE self) {
|
1533
|
-
if (NM_STYPE(self) != DENSE_STORE) rb_raise(nm_eStorageTypeError, "can only calculate exact determinant for dense matrices");
|
2085
|
+
if (NM_STYPE(self) != nm::DENSE_STORE) rb_raise(nm_eStorageTypeError, "can only calculate exact determinant for dense matrices");
|
1534
2086
|
|
1535
2087
|
if (NM_DIM(self) != 2 || NM_SHAPE0(self) != NM_SHAPE1(self)) return Qnil;
|
1536
2088
|
|
@@ -1558,7 +2110,7 @@ static VALUE nm_det_exact(VALUE self) {
|
|
1558
2110
|
*
|
1559
2111
|
* TODO: Add a column-major option for libraries that use column-major matrices.
|
1560
2112
|
*/
|
1561
|
-
VALUE rb_nmatrix_dense_create(dtype_t dtype, size_t* shape, size_t dim, void* elements, size_t length) {
|
2113
|
+
VALUE rb_nmatrix_dense_create(nm::dtype_t dtype, size_t* shape, size_t dim, void* elements, size_t length) {
|
1562
2114
|
NMATRIX* nm;
|
1563
2115
|
VALUE klass;
|
1564
2116
|
size_t nm_dim;
|
@@ -1584,7 +2136,7 @@ VALUE rb_nmatrix_dense_create(dtype_t dtype, size_t* shape, size_t dim, void* el
|
|
1584
2136
|
memcpy(elements_copy, elements, DTYPE_SIZES[dtype]*length);
|
1585
2137
|
|
1586
2138
|
// allocate and create the matrix and its storage
|
1587
|
-
nm = nm_create(DENSE_STORE, nm_dense_storage_create(dtype, shape_copy, dim, elements_copy, length));
|
2139
|
+
nm = nm_create(nm::DENSE_STORE, nm_dense_storage_create(dtype, shape_copy, dim, elements_copy, length));
|
1588
2140
|
|
1589
2141
|
// tell Ruby about the matrix and its storage, particularly how to garbage collect it.
|
1590
2142
|
return Data_Wrap_Struct(klass, nm_dense_storage_mark, nm_dense_storage_delete, nm);
|
@@ -1600,7 +2152,7 @@ VALUE rb_nmatrix_dense_create(dtype_t dtype, size_t* shape, size_t dim, void* el
|
|
1600
2152
|
*
|
1601
2153
|
* TODO: Add a transpose option for setting the orientation of the vector?
|
1602
2154
|
*/
|
1603
|
-
VALUE rb_nvector_dense_create(dtype_t dtype, void* elements, size_t length) {
|
2155
|
+
VALUE rb_nvector_dense_create(nm::dtype_t dtype, void* elements, size_t length) {
|
1604
2156
|
size_t dim = 1, shape = length;
|
1605
2157
|
return rb_nmatrix_dense_create(dtype, &shape, dim, elements, length);
|
1606
2158
|
}
|