nmatrix 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +1 -1
- data/History.txt +68 -10
- data/LICENSE.txt +2 -2
- data/Manifest.txt +2 -0
- data/README.rdoc +90 -69
- data/Rakefile +18 -9
- data/ext/nmatrix/data/complex.h +7 -7
- data/ext/nmatrix/data/data.cpp +2 -7
- data/ext/nmatrix/data/data.h +7 -4
- data/ext/nmatrix/data/rational.h +2 -2
- data/ext/nmatrix/data/ruby_object.h +3 -10
- data/ext/nmatrix/extconf.rb +79 -54
- data/ext/nmatrix/new_extconf.rb +11 -12
- data/ext/nmatrix/nmatrix.cpp +94 -125
- data/ext/nmatrix/nmatrix.h +38 -17
- data/ext/nmatrix/ruby_constants.cpp +2 -15
- data/ext/nmatrix/ruby_constants.h +2 -14
- data/ext/nmatrix/storage/common.cpp +2 -2
- data/ext/nmatrix/storage/common.h +2 -2
- data/ext/nmatrix/storage/dense.cpp +206 -31
- data/ext/nmatrix/storage/dense.h +5 -2
- data/ext/nmatrix/storage/list.cpp +52 -4
- data/ext/nmatrix/storage/list.h +3 -2
- data/ext/nmatrix/storage/storage.cpp +6 -6
- data/ext/nmatrix/storage/storage.h +2 -2
- data/ext/nmatrix/storage/yale.cpp +202 -49
- data/ext/nmatrix/storage/yale.h +5 -4
- data/ext/nmatrix/ttable_helper.rb +108 -108
- data/ext/nmatrix/types.h +2 -15
- data/ext/nmatrix/util/io.cpp +2 -2
- data/ext/nmatrix/util/io.h +2 -2
- data/ext/nmatrix/util/lapack.h +2 -2
- data/ext/nmatrix/util/math.cpp +14 -14
- data/ext/nmatrix/util/math.h +2 -2
- data/ext/nmatrix/util/sl_list.cpp +2 -2
- data/ext/nmatrix/util/sl_list.h +2 -2
- data/ext/nmatrix/util/util.h +2 -2
- data/lib/nmatrix.rb +13 -35
- data/lib/nmatrix/blas.rb +182 -56
- data/lib/nmatrix/io/market.rb +38 -14
- data/lib/nmatrix/io/mat5_reader.rb +393 -278
- data/lib/nmatrix/io/mat_reader.rb +121 -107
- data/lib/nmatrix/lapack.rb +59 -14
- data/lib/nmatrix/monkeys.rb +32 -30
- data/lib/nmatrix/nmatrix.rb +204 -100
- data/lib/nmatrix/nvector.rb +166 -57
- data/lib/nmatrix/shortcuts.rb +364 -231
- data/lib/nmatrix/version.rb +8 -4
- data/nmatrix.gemspec +5 -3
- data/scripts/mac-brew-gcc.sh +1 -1
- data/spec/blas_spec.rb +80 -2
- data/spec/math_spec.rb +78 -32
- data/spec/nmatrix_list_spec.rb +55 -55
- data/spec/nmatrix_spec.rb +60 -117
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +214 -198
- data/spec/nvector_spec.rb +58 -2
- data/spec/shortcuts_spec.rb +156 -32
- data/spec/slice_spec.rb +229 -178
- data/spec/spec_helper.rb +2 -2
- metadata +71 -21
data/ext/nmatrix/storage/dense.h
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -78,6 +78,8 @@ void nm_dense_storage_mark(void*);
|
|
78
78
|
// Accessors //
|
79
79
|
///////////////
|
80
80
|
|
81
|
+
VALUE nm_dense_each(VALUE nmatrix);
|
82
|
+
VALUE nm_dense_each_with_indices(VALUE nmatrix);
|
81
83
|
void* nm_dense_storage_get(STORAGE* s, SLICE* slice);
|
82
84
|
void* nm_dense_storage_ref(STORAGE* s, SLICE* slice);
|
83
85
|
void nm_dense_storage_set(STORAGE* s, SLICE* slice, void* val);
|
@@ -102,6 +104,7 @@ STORAGE* nm_dense_storage_matrix_multiply(const STORAGE_PAIR& casted_storage, si
|
|
102
104
|
/////////////
|
103
105
|
|
104
106
|
size_t nm_dense_storage_pos(const DENSE_STORAGE* s, const size_t* coords);
|
107
|
+
void nm_dense_storage_coords(const DENSE_STORAGE* s, const size_t slice_pos, size_t* coords_out);
|
105
108
|
|
106
109
|
/////////////////////////
|
107
110
|
// Copying and Casting //
|
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -182,9 +182,57 @@ NODE* list_storage_get_single_node(LIST_STORAGE* s, SLICE* slice)
|
|
182
182
|
return n;
|
183
183
|
}
|
184
184
|
|
185
|
+
/*
|
186
|
+
* Each stored iterator, brings along the indices
|
187
|
+
*/
|
188
|
+
VALUE nm_list_each_stored_with_indices(VALUE nmatrix) {
|
185
189
|
|
186
|
-
|
187
|
-
|
190
|
+
// If we don't have a block, return an enumerator.
|
191
|
+
RETURN_SIZED_ENUMERATOR(nmatrix, 0, 0, 0);
|
192
|
+
|
193
|
+
LIST_STORAGE* s = NM_STORAGE_LIST(nmatrix);
|
194
|
+
// Create indices and initialize to zero
|
195
|
+
size_t* coords = ALLOCA_N(size_t, s->dim);
|
196
|
+
memset(coords, 0, sizeof(size_t) * s->dim);
|
197
|
+
|
198
|
+
// Set up the LIST and NODE
|
199
|
+
LIST* l = s->rows;
|
200
|
+
NODE* curr = l->first;
|
201
|
+
|
202
|
+
// Levels...
|
203
|
+
while (curr) { // LOOPS through the rows
|
204
|
+
NODE* subnode = reinterpret_cast<LIST*>(curr->val)->first;
|
205
|
+
size_t row = curr->key;
|
206
|
+
// Iterate along each row, yielding the val, row, col for each non-default entry
|
207
|
+
while (subnode) {
|
208
|
+
VALUE ary = rb_ary_new();
|
209
|
+
size_t col = subnode->key;
|
210
|
+
|
211
|
+
// Conditional type handling
|
212
|
+
if (NM_DTYPE(nmatrix) == nm::RUBYOBJ) {
|
213
|
+
rb_ary_push(ary, *reinterpret_cast<VALUE*>(subnode->val));
|
214
|
+
} else {
|
215
|
+
rb_ary_push(ary, rubyobj_from_cval((char*)(subnode->val ) , NM_DTYPE(nmatrix)).rval);
|
216
|
+
}
|
217
|
+
|
218
|
+
// Push the coordinate values into the ary
|
219
|
+
rb_ary_push(ary, INT2FIX(row));
|
220
|
+
rb_ary_push(ary, INT2FIX(col));
|
221
|
+
|
222
|
+
// Yield the ary
|
223
|
+
rb_yield(ary);
|
224
|
+
|
225
|
+
// Update the col position
|
226
|
+
subnode = subnode->next;
|
227
|
+
}
|
228
|
+
// Update the row node
|
229
|
+
curr = curr->next;
|
230
|
+
}
|
231
|
+
return nmatrix;
|
232
|
+
}
|
233
|
+
|
234
|
+
|
235
|
+
static LIST* slice_copy(const LIST_STORAGE *src, LIST *src_rows, size_t *coords, size_t *lengths, size_t n) {
|
188
236
|
NODE *src_node;
|
189
237
|
LIST *dst_rows = NULL;
|
190
238
|
void *val = NULL;
|
data/ext/nmatrix/storage/list.h
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -82,6 +82,7 @@ extern "C" {
|
|
82
82
|
// Accessors //
|
83
83
|
///////////////
|
84
84
|
|
85
|
+
VALUE nm_list_each_stored_with_indices(VALUE nmatrix);
|
85
86
|
void* nm_list_storage_ref(STORAGE* s, SLICE* slice);
|
86
87
|
void* nm_list_storage_get(STORAGE* s, SLICE* slice);
|
87
88
|
void* nm_list_storage_insert(STORAGE* s, SLICE* slice, void* val);
|
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -485,7 +485,7 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
485
485
|
size_t request_capacity = shape[0] + ndnz + 1;
|
486
486
|
|
487
487
|
// Create with minimum possible capacity -- just enough to hold all of the entries
|
488
|
-
YALE_STORAGE* lhs = nm_yale_storage_create(l_dtype, shape, 2, request_capacity);
|
488
|
+
YALE_STORAGE* lhs = nm_yale_storage_create(l_dtype, shape, 2, request_capacity, UINT8);
|
489
489
|
|
490
490
|
if (lhs->capacity < request_capacity)
|
491
491
|
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", (unsigned long)request_capacity, (unsigned long)(lhs->capacity));
|
@@ -546,7 +546,7 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
546
546
|
shape[1] = rhs->shape[1];
|
547
547
|
|
548
548
|
size_t request_capacity = shape[0] + ndnz + 1;
|
549
|
-
YALE_STORAGE* lhs = nm_yale_storage_create(l_dtype, shape, 2, request_capacity);
|
549
|
+
YALE_STORAGE* lhs = nm_yale_storage_create(l_dtype, shape, 2, request_capacity, UINT8);
|
550
550
|
|
551
551
|
if (lhs->capacity < request_capacity)
|
552
552
|
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", (unsigned long)request_capacity, (unsigned long)(lhs->capacity));
|
@@ -614,7 +614,7 @@ extern "C" {
|
|
614
614
|
STORAGE* nm_yale_storage_from_dense(const STORAGE* right, nm::dtype_t l_dtype) {
|
615
615
|
NAMED_LRI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::create_from_dense_storage, YALE_STORAGE*, const DENSE_STORAGE* rhs, nm::dtype_t l_dtype);
|
616
616
|
|
617
|
-
nm::itype_t itype =
|
617
|
+
nm::itype_t itype = nm_yale_storage_default_itype((const YALE_STORAGE*)right);
|
618
618
|
|
619
619
|
return (STORAGE*)ttable[l_dtype][right->dtype][itype]((const DENSE_STORAGE*)right, l_dtype);
|
620
620
|
}
|
@@ -622,7 +622,7 @@ extern "C" {
|
|
622
622
|
STORAGE* nm_yale_storage_from_list(const STORAGE* right, nm::dtype_t l_dtype) {
|
623
623
|
NAMED_LRI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::create_from_list_storage, YALE_STORAGE*, const LIST_STORAGE* rhs, nm::dtype_t l_dtype);
|
624
624
|
|
625
|
-
nm::itype_t itype =
|
625
|
+
nm::itype_t itype = nm_yale_storage_default_itype((const YALE_STORAGE*)right);
|
626
626
|
|
627
627
|
return (STORAGE*)ttable[l_dtype][right->dtype][itype]((const LIST_STORAGE*)right, l_dtype);
|
628
628
|
}
|
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -42,6 +42,7 @@
|
|
42
42
|
#include <ruby.h>
|
43
43
|
#include <algorithm> // std::min
|
44
44
|
#include <cstdio> // std::fprintf
|
45
|
+
#include <iostream>
|
45
46
|
|
46
47
|
/*
|
47
48
|
* Project Includes
|
@@ -61,23 +62,19 @@
|
|
61
62
|
/*
|
62
63
|
* Macros
|
63
64
|
*/
|
65
|
+
|
64
66
|
#ifndef NM_MAX
|
65
67
|
#define NM_MAX(a,b) (((a)>(b))?(a):(b))
|
66
68
|
#define NM_MIN(a,b) (((a)<(b))?(a):(b))
|
67
69
|
#endif
|
68
70
|
|
69
|
-
|
70
|
-
/*
|
71
|
-
* Global Variables
|
72
|
-
*/
|
73
|
-
|
74
71
|
/*
|
75
72
|
* Forward Declarations
|
76
73
|
*/
|
77
74
|
|
78
75
|
extern "C" {
|
79
76
|
static YALE_STORAGE* nm_copy_alloc_struct(const YALE_STORAGE* rhs, const nm::dtype_t new_dtype, const size_t new_capacity, const size_t new_size);
|
80
|
-
static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim);
|
77
|
+
static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim, nm::itype_t min_itype);
|
81
78
|
|
82
79
|
/* Ruby-accessible functions */
|
83
80
|
static VALUE nm_size(VALUE self);
|
@@ -90,8 +87,6 @@ extern "C" {
|
|
90
87
|
|
91
88
|
} // end extern "C" block
|
92
89
|
|
93
|
-
|
94
|
-
|
95
90
|
namespace nm { namespace yale_storage {
|
96
91
|
|
97
92
|
template <typename DType, typename IType>
|
@@ -149,7 +144,7 @@ YALE_STORAGE* create_from_old_yale(dtype_t dtype, size_t* shape, void* r_ia, voi
|
|
149
144
|
}
|
150
145
|
|
151
146
|
// Having walked through the matrix, we now go about allocating the space for it.
|
152
|
-
YALE_STORAGE* s = alloc(dtype, shape, 2);
|
147
|
+
YALE_STORAGE* s = alloc(dtype, shape, 2, UINT8);
|
153
148
|
|
154
149
|
s->capacity = shape[0] + ndnz + 1;
|
155
150
|
s->ndnz = ndnz;
|
@@ -299,9 +294,7 @@ size_t max_size(YALE_STORAGE* s) {
|
|
299
294
|
///////////////
|
300
295
|
|
301
296
|
/*
|
302
|
-
* Returns a slice of YALE_STORAGE object by
|
303
|
-
*
|
304
|
-
* Slicing-related.
|
297
|
+
* Returns a slice of YALE_STORAGE object by copy
|
305
298
|
*/
|
306
299
|
template <typename DType,typename IType>
|
307
300
|
void* get(YALE_STORAGE* storage, SLICE* slice) {
|
@@ -312,10 +305,10 @@ void* get(YALE_STORAGE* storage, SLICE* slice) {
|
|
312
305
|
shape[0] = slice->lengths[0];
|
313
306
|
shape[1] = slice->lengths[1];
|
314
307
|
|
315
|
-
IType
|
316
|
-
DType
|
308
|
+
IType* src_ija = reinterpret_cast<IType*>(storage->ija);
|
309
|
+
DType* src_a = reinterpret_cast<DType*>(storage->a);
|
317
310
|
|
318
|
-
// Calc ndnz
|
311
|
+
// Calc ndnz for the destination
|
319
312
|
size_t ndnz = 0;
|
320
313
|
size_t i,j; // indexes of destination matrix
|
321
314
|
size_t k,l; // indexes of source matrix
|
@@ -326,54 +319,71 @@ void* get(YALE_STORAGE* storage, SLICE* slice) {
|
|
326
319
|
|
327
320
|
if (j == i) continue;
|
328
321
|
|
329
|
-
if (k == l
|
330
|
-
|
331
|
-
|
332
|
-
|
322
|
+
if (k == l) { // for diagonal element of source
|
323
|
+
if (src_a[k] != 0) ++ndnz;
|
324
|
+
} else { // for non-diagonal element
|
325
|
+
for (size_t c = src_ija[k]; c < src_ija[k+1]; c++) {
|
326
|
+
if (src_ija[c] == l) {
|
327
|
+
++ndnz;
|
328
|
+
break;
|
329
|
+
}
|
330
|
+
}
|
333
331
|
}
|
334
332
|
|
335
333
|
}
|
336
334
|
}
|
337
335
|
|
338
336
|
size_t request_capacity = shape[0] + ndnz + 1;
|
339
|
-
|
337
|
+
//fprintf(stderr, "yale get copy: shape0=%d, shape1=%d, ndnz=%d, request_capacity=%d\n", shape[0], shape[1], ndnz, request_capacity);
|
338
|
+
YALE_STORAGE* ns = nm_yale_storage_create(storage->dtype, shape, 2, request_capacity, storage->itype);
|
340
339
|
|
341
340
|
if (ns->capacity < request_capacity)
|
342
|
-
|
341
|
+
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, ns->capacity);
|
343
342
|
|
344
343
|
// Initialize the A and IJA arrays
|
345
344
|
init<DType,IType>(ns);
|
346
|
-
IType
|
347
|
-
DType
|
345
|
+
IType* dst_ija = reinterpret_cast<IType*>(ns->ija);
|
346
|
+
DType* dst_a = reinterpret_cast<DType*>(ns->a);
|
348
347
|
|
349
348
|
size_t ija = shape[0] + 1;
|
350
|
-
DType val;
|
349
|
+
DType val = src_a[storage->shape[0]]; // use 0 as the default for copy
|
351
350
|
for (i = 0; i < shape[0]; ++i) {
|
352
351
|
k = i + offset[0];
|
353
352
|
for (j = 0; j < shape[1]; ++j) {
|
353
|
+
bool found = false;
|
354
354
|
l = j + offset[1];
|
355
355
|
|
356
356
|
// Get value from source matrix
|
357
|
-
if (k == l)
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
357
|
+
if (k == l) { // source diagonal
|
358
|
+
if (src_a[k] != 0) { // don't bother copying non-zero values from the diagonal
|
359
|
+
val = src_a[k];
|
360
|
+
found = true;
|
361
|
+
}
|
362
|
+
} else {
|
363
|
+
// copy one non-diagonal element
|
364
|
+
for (size_t c = src_ija[k]; !found && c < src_ija[k+1]; ++c) {
|
365
|
+
if (src_ija[c] == l) {
|
366
|
+
val = src_a[c];
|
367
|
+
found = true;
|
368
|
+
}
|
362
369
|
}
|
363
370
|
}
|
364
371
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
372
|
+
if (found) {
|
373
|
+
// Set value in destination matrix
|
374
|
+
if (i == j) {
|
375
|
+
dst_a[i] = val;
|
376
|
+
} else {
|
377
|
+
// copy non-diagonal element
|
378
|
+
dst_ija[ija] = j;
|
379
|
+
dst_a[ija] = val;
|
371
380
|
|
372
|
-
|
373
|
-
|
374
|
-
|
381
|
+
++ija;
|
382
|
+
for (size_t c = i + 1; c <= shape[0]; ++c) {
|
383
|
+
dst_ija[c] = ija;
|
384
|
+
}
|
375
385
|
}
|
376
|
-
}
|
386
|
+
}
|
377
387
|
}
|
378
388
|
}
|
379
389
|
|
@@ -643,7 +653,7 @@ YALE_STORAGE* ew_op(const YALE_STORAGE* left, const YALE_STORAGE* right, dtype_t
|
|
643
653
|
|
644
654
|
init_capacity = std::min(left->ndnz + right->ndnz + new_shape[0], new_shape[0] * new_shape[1]);
|
645
655
|
|
646
|
-
dest = nm_yale_storage_create(dtype, new_shape, 2, init_capacity);
|
656
|
+
dest = nm_yale_storage_create(dtype, new_shape, 2, init_capacity, left->itype);
|
647
657
|
da = reinterpret_cast<DType*>(dest->a);
|
648
658
|
|
649
659
|
// Calculate diagonal values.
|
@@ -838,7 +848,7 @@ YALE_STORAGE* ew_op(const YALE_STORAGE* left, const YALE_STORAGE* right, dtype_t
|
|
838
848
|
// Set the number of non-diagonal non-zero entries in the destination matrix.
|
839
849
|
dest->ndnz = da_index;
|
840
850
|
|
841
|
-
printf("Number of non-diagonal non-zero
|
851
|
+
printf("Number of non-diagonal non-zero entries: %ld\n\n", (unsigned long)(dest->ndnz));
|
842
852
|
|
843
853
|
// Set the capacity of the destination matrix.
|
844
854
|
dest->capacity = dest->shape[0] + dest->ndnz + 1;
|
@@ -940,6 +950,8 @@ static char vector_insert_resize(YALE_STORAGE* s, size_t current_size, size_t po
|
|
940
950
|
s->ija = reinterpret_cast<void*>(new_ija);
|
941
951
|
s->a = reinterpret_cast<void*>(new_a);
|
942
952
|
|
953
|
+
fprintf(stderr, "resize\n");
|
954
|
+
|
943
955
|
return 'i';
|
944
956
|
}
|
945
957
|
|
@@ -1122,7 +1134,8 @@ static STORAGE* matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resu
|
|
1122
1134
|
// int8_t dtype = left->dtype;
|
1123
1135
|
|
1124
1136
|
// Create result storage.
|
1125
|
-
|
1137
|
+
nm::itype_t result_itype = static_cast<uint8_t>(left->itype) < static_cast<uint8_t>(right->itype) ? right->itype : left->itype;
|
1138
|
+
YALE_STORAGE* result = nm_yale_storage_create(left->dtype, resulting_shape, 2, left->capacity + right->capacity, result_itype);
|
1126
1139
|
init<DType,IType>(result);
|
1127
1140
|
|
1128
1141
|
IType* ijl = reinterpret_cast<IType*>(left->ija);
|
@@ -1144,7 +1157,106 @@ static STORAGE* matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resu
|
|
1144
1157
|
return reinterpret_cast<STORAGE*>(result);
|
1145
1158
|
}
|
1146
1159
|
|
1147
|
-
|
1160
|
+
|
1161
|
+
} // end of namespace nm::yale_storage
|
1162
|
+
|
1163
|
+
|
1164
|
+
// Helper function used only for the RETURN_SIZED_ENUMERATOR macro. Returns the length of
|
1165
|
+
// the matrix's storage.
|
1166
|
+
static VALUE nm_yale_enumerator_length(VALUE nmatrix) {
|
1167
|
+
long len = nm_yale_storage_get_size(NM_STORAGE_YALE(nmatrix));
|
1168
|
+
return LONG2NUM(len);
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
|
1172
|
+
template <typename DType, typename IType>
|
1173
|
+
struct yale_each_stored_with_indices_helper {
|
1174
|
+
static VALUE iterate(VALUE nm) {
|
1175
|
+
|
1176
|
+
YALE_STORAGE* s = NM_STORAGE_YALE(nm);
|
1177
|
+
DType* a = reinterpret_cast<DType*>(s->a);
|
1178
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1179
|
+
|
1180
|
+
// If we don't have a block, return an enumerator.
|
1181
|
+
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_enumerator_length);
|
1182
|
+
|
1183
|
+
// Iterate along diagonal
|
1184
|
+
for (size_t k = 0; k < s->shape[0]; ++k) {
|
1185
|
+
VALUE ii = LONG2NUM(k),
|
1186
|
+
jj = LONG2NUM(k);
|
1187
|
+
|
1188
|
+
VALUE v = rubyobj_from_cval(&(a[k]), NM_DTYPE(nm)).rval;
|
1189
|
+
rb_yield_values(3, v, ii, jj );
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
// Iterate through non-diagonal elements, row by row
|
1193
|
+
for (long i = 0; i < s->shape[0]; ++i) {
|
1194
|
+
long p = static_cast<long>( ija[i] ),
|
1195
|
+
next_p = static_cast<long>( ija[i+1] );
|
1196
|
+
|
1197
|
+
for (; p < next_p; ++p) {
|
1198
|
+
long j = static_cast<long>(ija[p]);
|
1199
|
+
VALUE ii = LONG2NUM(i),
|
1200
|
+
jj = LONG2NUM(j);
|
1201
|
+
|
1202
|
+
VALUE v = rubyobj_from_cval(&(a[p]), NM_DTYPE(nm)).rval;
|
1203
|
+
rb_yield_values(3, v, ii, jj );
|
1204
|
+
}
|
1205
|
+
}
|
1206
|
+
|
1207
|
+
return nm;
|
1208
|
+
}
|
1209
|
+
};
|
1210
|
+
|
1211
|
+
|
1212
|
+
template <typename IType>
|
1213
|
+
struct yale_each_stored_with_indices_helper<RubyObject, IType> {
|
1214
|
+
static VALUE iterate(VALUE nm) {
|
1215
|
+
|
1216
|
+
YALE_STORAGE* s = NM_STORAGE_YALE(nm);
|
1217
|
+
RubyObject* a = reinterpret_cast<RubyObject*>(s->a);
|
1218
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1219
|
+
|
1220
|
+
// If we don't have a block, return an enumerator.
|
1221
|
+
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_enumerator_length);
|
1222
|
+
|
1223
|
+
// Iterate along diagonal
|
1224
|
+
for (size_t k = 0; k < s->shape[0]; ++k) {
|
1225
|
+
VALUE ii = LONG2NUM(k),
|
1226
|
+
jj = LONG2NUM(k);
|
1227
|
+
rb_yield_values(3, a[k].rval, ii, jj ); // yield element, i, j
|
1228
|
+
}
|
1229
|
+
|
1230
|
+
// Iterate through non-diagonal elements, row by row
|
1231
|
+
for (long i = 0; i < s->shape[0]; ++i) {
|
1232
|
+
long p = static_cast<long>( ija[i] ),
|
1233
|
+
next_p = static_cast<long>( ija[i+1] );
|
1234
|
+
|
1235
|
+
for (; p < next_p; ++p) {
|
1236
|
+
long j = static_cast<long>(ija[p]);
|
1237
|
+
VALUE ii = LONG2NUM(i),
|
1238
|
+
jj = LONG2NUM(j);
|
1239
|
+
|
1240
|
+
rb_yield_values(3, a[p].rval, ii, jj );
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
return nm;
|
1245
|
+
}
|
1246
|
+
};
|
1247
|
+
|
1248
|
+
|
1249
|
+
/*
|
1250
|
+
* This function and the two helper structs enable us to use partial template specialization.
|
1251
|
+
* See also: http://stackoverflow.com/questions/6623375/c-template-specialization-on-functions
|
1252
|
+
*/
|
1253
|
+
template <typename DType, typename IType>
|
1254
|
+
static VALUE yale_each_stored_with_indices(VALUE nm) {
|
1255
|
+
return yale_each_stored_with_indices_helper<DType, IType>::iterate(nm);
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
|
1259
|
+
} // end of namespace nm.
|
1148
1260
|
|
1149
1261
|
///////////////////
|
1150
1262
|
// Ruby Bindings //
|
@@ -1155,6 +1267,10 @@ static STORAGE* matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resu
|
|
1155
1267
|
extern "C" {
|
1156
1268
|
|
1157
1269
|
void nm_init_yale_functions() {
|
1270
|
+
/*
|
1271
|
+
* This module stores methods that are useful for debugging Yale matrices,
|
1272
|
+
* i.e. the ones with +:yale+ stype.
|
1273
|
+
*/
|
1158
1274
|
cNMatrix_YaleFunctions = rb_define_module_under(cNMatrix, "YaleFunctions");
|
1159
1275
|
|
1160
1276
|
rb_define_method(cNMatrix_YaleFunctions, "yale_ija", (METHOD)nm_ija, 0);
|
@@ -1172,6 +1288,18 @@ void nm_init_yale_functions() {
|
|
1172
1288
|
// C ACCESSORS //
|
1173
1289
|
/////////////////
|
1174
1290
|
|
1291
|
+
|
1292
|
+
|
1293
|
+
VALUE nm_yale_each_stored_with_indices(VALUE nmatrix) {
|
1294
|
+
nm::dtype_t d = NM_DTYPE(nmatrix);
|
1295
|
+
nm::itype_t i = NM_ITYPE(nmatrix);
|
1296
|
+
|
1297
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_each_stored_with_indices, VALUE, VALUE)
|
1298
|
+
|
1299
|
+
return ttable[d][i](nmatrix);
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
|
1175
1303
|
/*
|
1176
1304
|
* C accessor for inserting some value in a matrix (or replacing an existing cell).
|
1177
1305
|
*/
|
@@ -1262,7 +1390,7 @@ STORAGE* nm_yale_storage_copy_transposed(const STORAGE* rhs_base) {
|
|
1262
1390
|
|
1263
1391
|
size_t size = nm_yale_storage_get_size(rhs);
|
1264
1392
|
|
1265
|
-
YALE_STORAGE* lhs = nm_yale_storage_create(rhs->dtype, shape, 2, size);
|
1393
|
+
YALE_STORAGE* lhs = nm_yale_storage_create(rhs->dtype, shape, 2, size, nm::UINT8);
|
1266
1394
|
nm_yale_storage_init(lhs);
|
1267
1395
|
|
1268
1396
|
NAMED_LI_DTYPE_TEMPLATE_TABLE(transp, nm::math::transpose_yale, void, const size_t n, const size_t m, const void* ia_, const void* ja_, const void* a_, const bool diaga, void* ib_, void* jb_, void* b_, const bool move);
|
@@ -1362,7 +1490,7 @@ STORAGE* nm_yale_storage_ew_op(nm::ewop_t op, const STORAGE* left, const STORAGE
|
|
1362
1490
|
* create the storage.
|
1363
1491
|
*/
|
1364
1492
|
|
1365
|
-
YALE_STORAGE* nm_yale_storage_create(nm::dtype_t dtype, size_t* shape, size_t dim, size_t init_capacity) {
|
1493
|
+
YALE_STORAGE* nm_yale_storage_create(nm::dtype_t dtype, size_t* shape, size_t dim, size_t init_capacity, nm::itype_t min_itype) {
|
1366
1494
|
YALE_STORAGE* s;
|
1367
1495
|
size_t max_capacity;
|
1368
1496
|
|
@@ -1371,7 +1499,7 @@ YALE_STORAGE* nm_yale_storage_create(nm::dtype_t dtype, size_t* shape, size_t di
|
|
1371
1499
|
rb_raise(rb_eNotImpError, "Can only support 2D matrices");
|
1372
1500
|
}
|
1373
1501
|
|
1374
|
-
s = alloc(dtype, shape, dim);
|
1502
|
+
s = alloc(dtype, shape, dim, min_itype);
|
1375
1503
|
max_capacity = nm::yale_storage::max_size(s);
|
1376
1504
|
|
1377
1505
|
// Set matrix capacity (and ensure its validity)
|
@@ -1434,7 +1562,7 @@ void nm_yale_storage_mark(void* storage_base) {
|
|
1434
1562
|
/*
|
1435
1563
|
* Allocates and initializes the basic struct (but not the IJA or A vectors).
|
1436
1564
|
*/
|
1437
|
-
static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim) {
|
1565
|
+
static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim, nm::itype_t min_itype) {
|
1438
1566
|
YALE_STORAGE* s;
|
1439
1567
|
|
1440
1568
|
s = ALLOC( YALE_STORAGE );
|
@@ -1445,6 +1573,10 @@ static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim) {
|
|
1445
1573
|
s->dim = dim;
|
1446
1574
|
s->itype = nm_yale_storage_itype_by_shape(shape);
|
1447
1575
|
|
1576
|
+
// See if a higher itype has been requested.
|
1577
|
+
if (static_cast<int8_t>(s->itype) < static_cast<int8_t>(min_itype))
|
1578
|
+
s->itype = min_itype;
|
1579
|
+
|
1448
1580
|
return s;
|
1449
1581
|
}
|
1450
1582
|
|
@@ -1466,6 +1598,9 @@ YALE_STORAGE* nm_yale_storage_create_from_old_yale(nm::dtype_t dtype, size_t* sh
|
|
1466
1598
|
//////////////////////////////////////////////
|
1467
1599
|
|
1468
1600
|
/*
|
1601
|
+
* call-seq:
|
1602
|
+
* yale_size -> Integer
|
1603
|
+
*
|
1469
1604
|
* Get the size of a Yale matrix (the number of elements actually stored).
|
1470
1605
|
*
|
1471
1606
|
* For capacity (the maximum number of elements that can be stored without a resize), use capacity instead.
|
@@ -1478,6 +1613,9 @@ static VALUE nm_size(VALUE self) {
|
|
1478
1613
|
|
1479
1614
|
|
1480
1615
|
/*
|
1616
|
+
* call-seq:
|
1617
|
+
* yale_a -> Array
|
1618
|
+
*
|
1481
1619
|
* Get the A array of a Yale matrix (which stores the diagonal and the LU portions of the matrix).
|
1482
1620
|
*/
|
1483
1621
|
static VALUE nm_a(VALUE self) {
|
@@ -1499,6 +1637,9 @@ static VALUE nm_a(VALUE self) {
|
|
1499
1637
|
|
1500
1638
|
|
1501
1639
|
/*
|
1640
|
+
* call-seq:
|
1641
|
+
* yale_d -> Array
|
1642
|
+
*
|
1502
1643
|
* Get the diagonal ("D") portion of the A array of a Yale matrix.
|
1503
1644
|
*/
|
1504
1645
|
static VALUE nm_d(VALUE self) {
|
@@ -1513,6 +1654,9 @@ static VALUE nm_d(VALUE self) {
|
|
1513
1654
|
}
|
1514
1655
|
|
1515
1656
|
/*
|
1657
|
+
* call-seq:
|
1658
|
+
* yale_lu -> Array
|
1659
|
+
*
|
1516
1660
|
* Get the non-diagonal ("LU") portion of the A array of a Yale matrix.
|
1517
1661
|
*/
|
1518
1662
|
static VALUE nm_lu(VALUE self) {
|
@@ -1535,6 +1679,9 @@ static VALUE nm_lu(VALUE self) {
|
|
1535
1679
|
}
|
1536
1680
|
|
1537
1681
|
/*
|
1682
|
+
* call-seq:
|
1683
|
+
* yale_ia -> Array
|
1684
|
+
*
|
1538
1685
|
* Get the IA portion of the IJA array of a Yale matrix. This gives the start and end positions of rows in the
|
1539
1686
|
* JA and LU portions of the IJA and A arrays, respectively.
|
1540
1687
|
*/
|
@@ -1551,6 +1698,9 @@ static VALUE nm_ia(VALUE self) {
|
|
1551
1698
|
}
|
1552
1699
|
|
1553
1700
|
/*
|
1701
|
+
* call-seq:
|
1702
|
+
* yale_ja -> Array
|
1703
|
+
*
|
1554
1704
|
* Get the JA portion of the IJA array of a Yale matrix. This gives the column indices for entries in corresponding
|
1555
1705
|
* positions in the LU portion of the A array.
|
1556
1706
|
*/
|
@@ -1574,6 +1724,9 @@ static VALUE nm_ja(VALUE self) {
|
|
1574
1724
|
}
|
1575
1725
|
|
1576
1726
|
/*
|
1727
|
+
* call-seq:
|
1728
|
+
* yale_ija -> Array
|
1729
|
+
*
|
1577
1730
|
* Get the IJA array of a Yale matrix.
|
1578
1731
|
*/
|
1579
1732
|
static VALUE nm_ija(VALUE self) {
|