nmatrix 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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) {
|