nmatrix 0.0.6 → 0.0.7
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +5 -0
- data/History.txt +97 -0
- data/Manifest.txt +34 -7
- data/README.rdoc +13 -13
- data/Rakefile +36 -26
- data/ext/nmatrix/data/data.cpp +15 -2
- data/ext/nmatrix/data/data.h +4 -0
- data/ext/nmatrix/data/ruby_object.h +5 -14
- data/ext/nmatrix/extconf.rb +3 -2
- data/ext/nmatrix/{util/math.cpp → math.cpp} +296 -6
- data/ext/nmatrix/math/asum.h +143 -0
- data/ext/nmatrix/math/geev.h +82 -0
- data/ext/nmatrix/math/gemm.h +267 -0
- data/ext/nmatrix/math/gemv.h +208 -0
- data/ext/nmatrix/math/ger.h +96 -0
- data/ext/nmatrix/math/gesdd.h +80 -0
- data/ext/nmatrix/math/gesvd.h +78 -0
- data/ext/nmatrix/math/getf2.h +86 -0
- data/ext/nmatrix/math/getrf.h +240 -0
- data/ext/nmatrix/math/getri.h +107 -0
- data/ext/nmatrix/math/getrs.h +125 -0
- data/ext/nmatrix/math/idamax.h +86 -0
- data/ext/nmatrix/{util → math}/lapack.h +60 -356
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +52 -0
- data/ext/nmatrix/math/math.h +1154 -0
- data/ext/nmatrix/math/nrm2.h +181 -0
- data/ext/nmatrix/math/potrs.h +125 -0
- data/ext/nmatrix/math/rot.h +141 -0
- data/ext/nmatrix/math/rotg.h +115 -0
- data/ext/nmatrix/math/scal.h +73 -0
- data/ext/nmatrix/math/swap.h +73 -0
- data/ext/nmatrix/math/trsm.h +383 -0
- data/ext/nmatrix/nmatrix.cpp +176 -152
- data/ext/nmatrix/nmatrix.h +1 -2
- data/ext/nmatrix/ruby_constants.cpp +9 -4
- data/ext/nmatrix/ruby_constants.h +1 -0
- data/ext/nmatrix/storage/dense.cpp +57 -41
- data/ext/nmatrix/storage/list.cpp +52 -50
- data/ext/nmatrix/storage/storage.cpp +59 -43
- data/ext/nmatrix/storage/yale.cpp +352 -333
- data/ext/nmatrix/storage/yale.h +4 -0
- data/lib/nmatrix.rb +2 -2
- data/lib/nmatrix/blas.rb +4 -4
- data/lib/nmatrix/enumerate.rb +241 -0
- data/lib/nmatrix/lapack.rb +54 -1
- data/lib/nmatrix/math.rb +462 -0
- data/lib/nmatrix/nmatrix.rb +210 -486
- data/lib/nmatrix/nvector.rb +0 -62
- data/lib/nmatrix/rspec.rb +75 -0
- data/lib/nmatrix/shortcuts.rb +136 -108
- data/lib/nmatrix/version.rb +1 -1
- data/spec/blas_spec.rb +20 -12
- data/spec/elementwise_spec.rb +22 -13
- data/spec/io_spec.rb +1 -0
- data/spec/lapack_spec.rb +197 -0
- data/spec/nmatrix_spec.rb +39 -38
- data/spec/nvector_spec.rb +3 -9
- data/spec/rspec_monkeys.rb +29 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +14 -16
- data/spec/slice_spec.rb +242 -186
- data/spec/spec_helper.rb +19 -0
- metadata +33 -5
- data/ext/nmatrix/util/math.h +0 -2612
@@ -139,7 +139,8 @@ DENSE_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype
|
|
139
139
|
|
140
140
|
// Allocate and set shape.
|
141
141
|
size_t* shape = ALLOC_N(size_t, rhs->dim);
|
142
|
-
|
142
|
+
shape[0] = rhs->shape[0];
|
143
|
+
shape[1] = rhs->shape[1];
|
143
144
|
|
144
145
|
DENSE_STORAGE* lhs = nm_dense_storage_create(l_dtype, shape, rhs->dim, NULL, 0);
|
145
146
|
LDType* lhs_elements = reinterpret_cast<LDType*>(lhs->elements);
|
@@ -147,45 +148,49 @@ DENSE_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype
|
|
147
148
|
// Position in dense to write to.
|
148
149
|
size_t pos = 0;
|
149
150
|
|
150
|
-
LDType LCAST_ZERO = rhs_a[rhs->shape[0]];
|
151
|
+
LDType LCAST_ZERO = rhs_a[rhs->src->shape[0]];
|
151
152
|
|
152
153
|
// Walk through rows. For each entry we set in dense, increment pos.
|
153
|
-
for (
|
154
|
-
|
155
|
-
// Position in yale array
|
156
|
-
RIType ija = rhs_ija[i];
|
154
|
+
for (size_t i = 0; i < shape[0]; ++i) {
|
155
|
+
RIType ri = i + rhs->offset[0];
|
157
156
|
|
158
|
-
if (
|
157
|
+
if (rhs_ija[ri] == rhs_ija[ri+1]) { // Check boundaries of row: is row empty? (Yes.)
|
159
158
|
|
160
159
|
// Write zeros in each column.
|
161
|
-
for (
|
160
|
+
for (size_t j = 0; j < shape[1]; ++j) { // Move to next dense position.
|
162
161
|
|
163
|
-
// Fill in zeros
|
164
|
-
if (
|
165
|
-
else
|
162
|
+
// Fill in zeros and copy the diagonal entry for this empty row.
|
163
|
+
if (ri == j + rhs->offset[1]) lhs_elements[pos] = static_cast<LDType>(rhs_a[ri]);
|
164
|
+
else lhs_elements[pos] = LCAST_ZERO;
|
166
165
|
|
167
166
|
++pos;
|
168
167
|
}
|
169
168
|
|
170
|
-
} else {
|
171
|
-
|
172
|
-
|
169
|
+
} else { // Row contains entries: write those in each column, interspersed with zeros.
|
170
|
+
|
171
|
+
// Get the first ija position of the row (as sliced)
|
172
|
+
RIType ija = nm::yale_storage::binary_search_left_boundary<RIType>(rhs, rhs_ija[ri], rhs_ija[ri+1]-1, rhs->offset[1]);
|
173
|
+
|
174
|
+
// What column is it?
|
175
|
+
RIType next_stored_rj = rhs_ija[ija];
|
173
176
|
|
174
|
-
for (size_t j = 0; j <
|
175
|
-
|
176
|
-
lhs_elements[pos] = static_cast<LDType>(rhs_a[i]);
|
177
|
+
for (size_t j = 0; j < shape[1]; ++j) {
|
178
|
+
RIType rj = j + rhs->offset[1];
|
177
179
|
|
178
|
-
|
180
|
+
if (rj == ri) { // at a diagonal in RHS
|
181
|
+
lhs_elements[pos] = static_cast<LDType>(rhs_a[ri]);
|
182
|
+
|
183
|
+
} else if (rj == next_stored_rj) { // column ID was found in RHS
|
179
184
|
lhs_elements[pos] = static_cast<LDType>(rhs_a[ija]); // Copy from rhs.
|
180
185
|
|
181
186
|
// Get next.
|
182
187
|
++ija;
|
183
188
|
|
184
189
|
// Increment to next column ID (or go off the end).
|
185
|
-
if (ija < rhs_ija[
|
186
|
-
else
|
190
|
+
if (ija < rhs_ija[ri+1]) next_stored_rj = rhs_ija[ija];
|
191
|
+
else next_stored_rj = rhs->src->shape[1];
|
187
192
|
|
188
|
-
} else { //
|
193
|
+
} else { // rj < next_stored_rj
|
189
194
|
|
190
195
|
// Insert zero.
|
191
196
|
lhs_elements[pos] = LCAST_ZERO;
|
@@ -319,7 +324,7 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
319
324
|
shape[0] = rhs->shape[0]; shape[1] = rhs->shape[1];
|
320
325
|
|
321
326
|
RDType* rhs_a = reinterpret_cast<RDType*>(rhs->a);
|
322
|
-
RDType R_ZERO = rhs_a[ rhs->shape[0] ];
|
327
|
+
RDType R_ZERO = rhs_a[ rhs->src->shape[0] ];
|
323
328
|
|
324
329
|
// copy default value from the zero location in the Yale matrix
|
325
330
|
LDType* default_val = ALLOC_N(LDType, 1);
|
@@ -333,35 +338,43 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
333
338
|
|
334
339
|
NODE *last_row_added = NULL;
|
335
340
|
// Walk through rows and columns as if RHS were a dense matrix
|
336
|
-
for (RIType i = 0; i <
|
341
|
+
for (RIType i = 0; i < shape[0]; ++i) {
|
342
|
+
RIType ri = i + rhs->offset[0];
|
343
|
+
|
337
344
|
NODE *last_added = NULL;
|
338
345
|
|
339
346
|
// Get boundaries of beginning and end of row
|
340
|
-
RIType ija = rhs_ija[
|
341
|
-
ija_next = rhs_ija[
|
347
|
+
RIType ija = rhs_ija[ri],
|
348
|
+
ija_next = rhs_ija[ri+1];
|
342
349
|
|
343
350
|
// Are we going to need to add a diagonal for this row?
|
344
351
|
bool add_diag = false;
|
345
|
-
if (rhs_a[
|
352
|
+
if (rhs_a[ri] != R_ZERO) add_diag = true; // non-zero and located within the bounds of the slice
|
346
353
|
|
347
354
|
if (ija < ija_next || add_diag) {
|
355
|
+
ija = nm::yale_storage::binary_search_left_boundary<RIType>(rhs, ija, ija_next-1, rhs->offset[1]);
|
348
356
|
|
349
357
|
LIST* curr_row = list::create();
|
350
358
|
|
351
359
|
LDType* insert_val;
|
352
360
|
|
353
361
|
while (ija < ija_next) {
|
354
|
-
|
362
|
+
// Find first column in slice
|
363
|
+
RIType rj = rhs_ija[ija];
|
364
|
+
RIType j = rj - rhs->offset[1];
|
355
365
|
|
356
366
|
// Is there a nonzero diagonal item between the previously added item and the current one?
|
357
|
-
if (
|
367
|
+
if (rj > ri && add_diag) {
|
358
368
|
// Allocate and copy insertion value
|
359
369
|
insert_val = ALLOC_N(LDType, 1);
|
360
|
-
*insert_val = static_cast<LDType>(rhs_a[
|
370
|
+
*insert_val = static_cast<LDType>(rhs_a[ri]);
|
361
371
|
|
362
|
-
//
|
363
|
-
|
364
|
-
|
372
|
+
// Insert the item in the list at the appropriate location.
|
373
|
+
// What is the appropriate key? Well, it's definitely right(i)==right(j), but the
|
374
|
+
// rj index has already been advanced past ri. So we should treat ri as the column and
|
375
|
+
// subtract offset[1].
|
376
|
+
if (last_added) last_added = list::insert_after(last_added, ri - rhs->offset[1], insert_val);
|
377
|
+
else last_added = list::insert(curr_row, false, ri - rhs->offset[1], insert_val);
|
365
378
|
|
366
379
|
// don't add again!
|
367
380
|
add_diag = false;
|
@@ -371,20 +384,23 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
371
384
|
insert_val = ALLOC_N(LDType, 1);
|
372
385
|
*insert_val = static_cast<LDType>(rhs_a[ija]);
|
373
386
|
|
374
|
-
if (last_added) last_added = list::insert_after(last_added,
|
375
|
-
else last_added = list::insert(curr_row, false,
|
387
|
+
if (last_added) last_added = list::insert_after(last_added, j, insert_val);
|
388
|
+
else last_added = list::insert(curr_row, false, j, insert_val);
|
376
389
|
|
377
390
|
++ija; // move to next entry in Yale matrix
|
378
391
|
}
|
379
392
|
|
380
393
|
if (add_diag) {
|
394
|
+
|
381
395
|
// still haven't added the diagonal.
|
382
396
|
insert_val = ALLOC_N(LDType, 1);
|
383
|
-
*insert_val = static_cast<LDType>(rhs_a[
|
397
|
+
*insert_val = static_cast<LDType>(rhs_a[ri]);
|
384
398
|
|
385
399
|
// insert the item in the list at the appropriate location
|
386
|
-
if (last_added) last_added = list::insert_after(last_added,
|
387
|
-
else last_added = list::insert(curr_row, false,
|
400
|
+
if (last_added) last_added = list::insert_after(last_added, ri - rhs->offset[1], insert_val);
|
401
|
+
else last_added = list::insert(curr_row, false, ri - rhs->offset[1], insert_val);
|
402
|
+
|
403
|
+
// no need to set add_diag to false because it'll be reset automatically in next iteration.
|
388
404
|
}
|
389
405
|
|
390
406
|
// Now add the list at the appropriate location
|
@@ -458,6 +474,7 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
458
474
|
*/
|
459
475
|
template <typename LDType, typename RDType, typename LIType>
|
460
476
|
YALE_STORAGE* create_from_dense_storage(const DENSE_STORAGE* rhs, dtype_t l_dtype, void* init) {
|
477
|
+
|
461
478
|
if (rhs->dim != 2) rb_raise(nm_eStorageTypeError, "can only convert matrices of dim 2 to yale");
|
462
479
|
|
463
480
|
LIType pos = 0;
|
@@ -504,16 +521,15 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
504
521
|
|
505
522
|
// Start just after the zero position.
|
506
523
|
LIType ija = shape[0]+1;
|
507
|
-
LIType i;
|
508
524
|
pos = 0;
|
509
525
|
|
510
526
|
// Copy contents
|
511
|
-
for (i = 0; i < rhs->shape[0]; ++i) {
|
527
|
+
for (LIType i = 0; i < rhs->shape[0]; ++i) {
|
512
528
|
// indicate the beginning of a row in the IJA array
|
513
|
-
lhs_ija[i]= ija;
|
529
|
+
lhs_ija[i] = ija;
|
514
530
|
|
515
531
|
for (LIType j = 0; j < rhs->shape[1]; ++j) {
|
516
|
-
pos = rhs->stride[0]*(i + rhs->offset[0]) + rhs->stride[1]*(j + rhs->offset[1]); // calc position with offsets
|
532
|
+
pos = rhs->stride[0] * (i + rhs->offset[0]) + rhs->stride[1] * (j + rhs->offset[1]); // calc position with offsets
|
517
533
|
|
518
534
|
if (i == j) { // copy to diagonal
|
519
535
|
lhs_a[i] = static_cast<LDType>(rhs_elements[pos]);
|
@@ -570,13 +586,13 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
570
586
|
// Copy contents
|
571
587
|
for (NODE* i_curr = rhs->rows->first; i_curr; i_curr = i_curr->next) {
|
572
588
|
|
573
|
-
// Shrink
|
589
|
+
// Shrink reference
|
574
590
|
int i = i_curr->key - rhs->offset[0];
|
575
591
|
if (i < 0 || i >= (int)rhs->shape[0]) continue;
|
576
592
|
|
577
593
|
for (NODE* j_curr = ((LIST*)(i_curr->val))->first; j_curr; j_curr = j_curr->next) {
|
578
594
|
|
579
|
-
// Shrink
|
595
|
+
// Shrink reference
|
580
596
|
int j = j_curr->key - rhs->offset[1];
|
581
597
|
if (j < 0 || j >= (int)rhs->shape[1]) continue;
|
582
598
|
|
@@ -44,6 +44,7 @@
|
|
44
44
|
#include <cstdio> // std::fprintf
|
45
45
|
#include <iostream>
|
46
46
|
#include <array>
|
47
|
+
#include <typeinfo>
|
47
48
|
|
48
49
|
#define RB_P(OBJ) \
|
49
50
|
rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("object_id"), 0)); \
|
@@ -54,9 +55,8 @@
|
|
54
55
|
*/
|
55
56
|
|
56
57
|
// #include "types.h"
|
57
|
-
#include "util/math.h"
|
58
|
-
|
59
58
|
#include "data/data.h"
|
59
|
+
#include "math/math.h"
|
60
60
|
|
61
61
|
#include "common.h"
|
62
62
|
#include "yale.h"
|
@@ -86,8 +86,11 @@ extern "C" {
|
|
86
86
|
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);
|
87
87
|
static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim, nm::itype_t min_itype);
|
88
88
|
|
89
|
+
static size_t yale_count_slice_copy_ndnz(const YALE_STORAGE* s, size_t*, size_t*);
|
90
|
+
|
89
91
|
static void* default_value_ptr(const YALE_STORAGE* s);
|
90
92
|
static VALUE default_value(const YALE_STORAGE* s);
|
93
|
+
static VALUE obj_at(YALE_STORAGE* s, size_t k);
|
91
94
|
|
92
95
|
/* Ruby-accessible functions */
|
93
96
|
static VALUE nm_size(VALUE self);
|
@@ -100,6 +103,9 @@ extern "C" {
|
|
100
103
|
|
101
104
|
static VALUE nm_nd_row(int argc, VALUE* argv, VALUE self);
|
102
105
|
|
106
|
+
static inline size_t src_ndnz(const YALE_STORAGE* s) {
|
107
|
+
return reinterpret_cast<YALE_STORAGE*>(s->src)->ndnz;
|
108
|
+
}
|
103
109
|
|
104
110
|
} // end extern "C" block
|
105
111
|
|
@@ -241,72 +247,6 @@ YALE_STORAGE* create_from_old_yale(dtype_t dtype, size_t* shape, void* r_ia, voi
|
|
241
247
|
}
|
242
248
|
|
243
249
|
|
244
|
-
/*
|
245
|
-
* Take two Yale storages and merge them into a new Yale storage.
|
246
|
-
*
|
247
|
-
* Uses the left as a template for the creation of a new one.
|
248
|
-
*/
|
249
|
-
template <typename DType, typename IType>
|
250
|
-
YALE_STORAGE* create_merged__(const YALE_STORAGE* left, const YALE_STORAGE* right) {
|
251
|
-
char ins_type;
|
252
|
-
|
253
|
-
size_t size = get_size<IType>(left);
|
254
|
-
|
255
|
-
// s represents the resulting storage
|
256
|
-
YALE_STORAGE* s = copy_alloc_struct<IType>(left, left->dtype, NM_MAX(left->capacity, right->capacity), size);
|
257
|
-
|
258
|
-
IType* sija = reinterpret_cast<IType*>(s->ija);
|
259
|
-
IType* rija = reinterpret_cast<IType*>(right->ija);
|
260
|
-
|
261
|
-
// set the element between D and LU (the boundary in A), which should be 0.
|
262
|
-
reinterpret_cast<DType*>(s->a)[s->shape[0]] = reinterpret_cast<DType*>(left->a)[left->shape[0]];
|
263
|
-
|
264
|
-
if (right && right != left) {
|
265
|
-
// some operations are unary and don't need this; others are x+x and don't need this
|
266
|
-
|
267
|
-
for (IType i = 0; i < s->shape[0]; ++i) {
|
268
|
-
|
269
|
-
IType ija = sija[i];
|
270
|
-
IType ija_next = sija[i+1];
|
271
|
-
|
272
|
-
for (IType r_ija = rija[i]; r_ija < rija[i+1]; ++r_ija) {
|
273
|
-
|
274
|
-
size_t ja = sija[ija]; // insert expects a size_t
|
275
|
-
|
276
|
-
if (ija == ija_next) {
|
277
|
-
// destination row is empty
|
278
|
-
ins_type = vector_insert<DType,IType>(s, ija, &ja, NULL, 1, true);
|
279
|
-
increment_ia_after<IType>(s, s->shape[0], i, 1);
|
280
|
-
++(s->ndnz);
|
281
|
-
++ija;
|
282
|
-
|
283
|
-
if (ins_type == 'i') ++ija_next;
|
284
|
-
|
285
|
-
} else {
|
286
|
-
bool found;
|
287
|
-
|
288
|
-
// merge positions into destination row
|
289
|
-
IType pos = insert_search<IType>(s, ija, ija_next-1, sija[ija], &found);
|
290
|
-
|
291
|
-
if (!found) {
|
292
|
-
vector_insert<DType,IType>(s, pos, &ja, NULL, 1, true);
|
293
|
-
increment_ia_after<IType>(s, s->shape[0], i, 1);
|
294
|
-
++(s->ndnz);
|
295
|
-
|
296
|
-
if (ins_type == 'i') ++ija_next;
|
297
|
-
}
|
298
|
-
|
299
|
-
// can now set a left boundary for the next search
|
300
|
-
ija = pos + 1;
|
301
|
-
}
|
302
|
-
}
|
303
|
-
}
|
304
|
-
}
|
305
|
-
|
306
|
-
return s;
|
307
|
-
}
|
308
|
-
|
309
|
-
|
310
250
|
/*
|
311
251
|
* Empty the matrix by initializing the IJA vector and setting the diagonal to 0.
|
312
252
|
*
|
@@ -332,29 +272,27 @@ size_t max_size(YALE_STORAGE* s) {
|
|
332
272
|
|
333
273
|
return result;
|
334
274
|
}
|
275
|
+
|
276
|
+
|
335
277
|
///////////////
|
336
278
|
// Accessors //
|
337
279
|
///////////////
|
338
280
|
|
281
|
+
|
339
282
|
/*
|
340
|
-
*
|
283
|
+
* Determine the number of non-diagonal non-zeros in a not-yet-created copy of a slice or matrix.
|
341
284
|
*/
|
342
|
-
template <typename DType,typename IType>
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
// Copy shape for yale construction
|
347
|
-
size_t* shape = ALLOC_N(size_t, 2);
|
348
|
-
shape[0] = slice->lengths[0];
|
349
|
-
shape[1] = slice->lengths[1];
|
285
|
+
template <typename DType, typename IType>
|
286
|
+
static size_t count_slice_copy_ndnz(const YALE_STORAGE* s, size_t* offset, size_t* shape) {
|
287
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
288
|
+
DType* a = reinterpret_cast<DType*>(s->a);
|
350
289
|
|
351
|
-
|
352
|
-
DType* src_a = reinterpret_cast<DType*>(storage->a);
|
290
|
+
DType ZERO(*reinterpret_cast<DType*>(default_value_ptr(s)));
|
353
291
|
|
354
292
|
// Calc ndnz for the destination
|
355
293
|
size_t ndnz = 0;
|
356
|
-
size_t i,j; // indexes of destination matrix
|
357
|
-
size_t k,l; // indexes of source matrix
|
294
|
+
size_t i, j; // indexes of destination matrix
|
295
|
+
size_t k, l; // indexes of source matrix
|
358
296
|
for (i = 0; i < shape[0]; i++) {
|
359
297
|
k = i + offset[0];
|
360
298
|
for (j = 0; j < shape[1]; j++) {
|
@@ -363,42 +301,54 @@ void* get(YALE_STORAGE* storage, SLICE* slice) {
|
|
363
301
|
if (j == i) continue;
|
364
302
|
|
365
303
|
if (k == l) { // for diagonal element of source
|
366
|
-
if (
|
304
|
+
if (a[k] != ZERO) ++ndnz;
|
367
305
|
} else { // for non-diagonal element
|
368
|
-
for (size_t c =
|
369
|
-
if (
|
306
|
+
for (size_t c = ija[k]; c < ija[k+1]; c++) {
|
307
|
+
if (ija[c] == l) {
|
370
308
|
++ndnz;
|
371
309
|
break;
|
372
310
|
}
|
373
311
|
}
|
374
312
|
}
|
375
|
-
|
376
313
|
}
|
377
314
|
}
|
378
315
|
|
379
|
-
|
380
|
-
|
381
|
-
|
316
|
+
return ndnz;
|
317
|
+
}
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
/*
|
322
|
+
* Copy some portion of a matrix into a new matrix.
|
323
|
+
*/
|
324
|
+
template <typename LDType, typename RDType, typename IType>
|
325
|
+
static void slice_copy(YALE_STORAGE* ns, const YALE_STORAGE* s, size_t* offset, size_t* lengths, dtype_t new_dtype) {
|
326
|
+
|
327
|
+
IType* src_ija = reinterpret_cast<IType*>(s->ija);
|
328
|
+
RDType* src_a = reinterpret_cast<RDType*>(s->a);
|
382
329
|
|
383
|
-
|
384
|
-
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, ns->capacity);
|
330
|
+
RDType RZERO(*reinterpret_cast<RDType*>(default_value_ptr(s)));
|
385
331
|
|
386
332
|
// Initialize the A and IJA arrays
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
333
|
+
LDType val(RZERO); // need default value for init. Can't use ns default value because it's not initialized yet
|
334
|
+
init<LDType,IType>(ns, &val);
|
335
|
+
IType* dst_ija = reinterpret_cast<IType*>(ns->ija);
|
336
|
+
LDType* dst_a = reinterpret_cast<LDType*>(ns->a);
|
337
|
+
|
338
|
+
size_t ija = lengths[0] + 1;
|
339
|
+
|
340
|
+
size_t i, j; // indexes of destination matrix
|
341
|
+
size_t k, l; // indexes of source matrix
|
342
|
+
|
343
|
+
for (i = 0; i < lengths[0]; ++i) {
|
394
344
|
k = i + offset[0];
|
395
|
-
for (j = 0; j <
|
345
|
+
for (j = 0; j < lengths[1]; ++j) {
|
396
346
|
bool found = false;
|
397
347
|
l = j + offset[1];
|
398
|
-
|
348
|
+
|
399
349
|
// Get value from source matrix
|
400
350
|
if (k == l) { // source diagonal
|
401
|
-
if (src_a[k] !=
|
351
|
+
if (src_a[k] != RZERO) { // don't bother copying non-zero values from the diagonal
|
402
352
|
val = src_a[k];
|
403
353
|
found = true;
|
404
354
|
}
|
@@ -420,9 +370,8 @@ void* get(YALE_STORAGE* storage, SLICE* slice) {
|
|
420
370
|
// copy non-diagonal element
|
421
371
|
dst_ija[ija] = j;
|
422
372
|
dst_a[ija] = val;
|
423
|
-
|
424
373
|
++ija;
|
425
|
-
for (size_t c = i + 1; c <=
|
374
|
+
for (size_t c = i + 1; c <= lengths[0]; ++c) {
|
426
375
|
dst_ija[c] = ija;
|
427
376
|
}
|
428
377
|
}
|
@@ -430,39 +379,71 @@ void* get(YALE_STORAGE* storage, SLICE* slice) {
|
|
430
379
|
}
|
431
380
|
}
|
432
381
|
|
433
|
-
dst_ija[
|
434
|
-
ns->ndnz
|
435
|
-
|
382
|
+
dst_ija[lengths[0]] = ija; // indicate the end of the last row
|
383
|
+
ns->ndnz = ija - lengths[0] - 1; // update ndnz count
|
384
|
+
}
|
385
|
+
|
386
|
+
|
387
|
+
/*
|
388
|
+
* Get a single element of a yale storage object
|
389
|
+
*/
|
390
|
+
template <typename DType, typename IType>
|
391
|
+
static void* get_single(YALE_STORAGE* storage, SLICE* slice) {
|
392
|
+
|
393
|
+
DType* a = reinterpret_cast<DType*>(storage->a);
|
394
|
+
IType* ija = reinterpret_cast<IType*>(storage->ija);
|
395
|
+
|
396
|
+
size_t coord0 = storage->offset[0] + slice->coords[0];
|
397
|
+
size_t coord1 = storage->offset[1] + slice->coords[1];
|
398
|
+
|
399
|
+
if (coord0 == coord1)
|
400
|
+
return &(a[ coord0 ]); // return diagonal entry
|
401
|
+
|
402
|
+
if (ija[coord0] == ija[coord0+1])
|
403
|
+
return &(a[ storage->src->shape[0] ]); // return zero pointer
|
404
|
+
|
405
|
+
// binary search for the column's location
|
406
|
+
int pos = binary_search<IType>(storage, ija[coord0], ija[coord0+1]-1, coord1);
|
407
|
+
|
408
|
+
if (pos != -1 && ija[pos] == coord1)
|
409
|
+
return &(a[pos]); // found exact value
|
410
|
+
|
411
|
+
return &(a[ storage->src->shape[0] ]); // return a pointer that happens to be zero
|
436
412
|
}
|
413
|
+
|
414
|
+
|
437
415
|
/*
|
438
416
|
* Returns a pointer to the correct location in the A vector of a YALE_STORAGE object, given some set of coordinates
|
439
417
|
* (the coordinates are stored in slice).
|
440
418
|
*/
|
441
419
|
template <typename DType,typename IType>
|
442
|
-
void* ref(YALE_STORAGE*
|
443
|
-
size_t* coords = slice->coords;
|
420
|
+
void* ref(YALE_STORAGE* s, SLICE* slice) {
|
444
421
|
|
445
|
-
|
422
|
+
YALE_STORAGE* ns = ALLOC( YALE_STORAGE );
|
446
423
|
|
447
|
-
|
448
|
-
|
424
|
+
ns->dim = s->dim;
|
425
|
+
ns->offset = ALLOC_N(size_t, ns->dim);
|
426
|
+
ns->shape = ALLOC_N(size_t, ns->dim);
|
449
427
|
|
450
|
-
|
451
|
-
|
428
|
+
for (size_t i = 0; i < ns->dim; ++i) {
|
429
|
+
ns->offset[i] = slice->coords[i] + s->offset[i];
|
430
|
+
ns->shape[i] = slice->lengths[i];
|
431
|
+
}
|
452
432
|
|
453
|
-
|
454
|
-
|
433
|
+
ns->dtype = s->dtype;
|
434
|
+
ns->itype = s->itype; // or should we go by shape?
|
455
435
|
|
456
|
-
|
457
|
-
|
458
|
-
ija[coords[0]],
|
459
|
-
ija[coords[0]+1]-1,
|
460
|
-
coords[1]);
|
436
|
+
ns->a = s->a;
|
437
|
+
ns->ija = s->ija;
|
461
438
|
|
462
|
-
|
463
|
-
|
439
|
+
ns->src = s->src;
|
440
|
+
s->src->count++;
|
441
|
+
|
442
|
+
ns->ndnz = 0;
|
443
|
+
ns->capacity= 0;
|
444
|
+
|
445
|
+
return ns;
|
464
446
|
|
465
|
-
return &(a[ storage->shape[0] ]); // return a pointer that happens to be zero
|
466
447
|
}
|
467
448
|
|
468
449
|
/*
|
@@ -472,22 +453,23 @@ void* ref(YALE_STORAGE* storage, SLICE* slice) {
|
|
472
453
|
template <typename DType, typename IType>
|
473
454
|
char set(YALE_STORAGE* storage, SLICE* slice, void* value) {
|
474
455
|
DType* v = reinterpret_cast<DType*>(value);
|
475
|
-
size_t
|
456
|
+
size_t coord0 = storage->offset[0] + slice->coords[0],
|
457
|
+
coord1 = storage->offset[1] + slice->coords[1];
|
476
458
|
|
477
459
|
bool found = false;
|
478
460
|
char ins_type;
|
479
461
|
|
480
|
-
if (
|
481
|
-
reinterpret_cast<DType*>(storage->a)[
|
462
|
+
if (coord0 == coord1) {
|
463
|
+
reinterpret_cast<DType*>(storage->a)[coord0] = *v; // set diagonal
|
482
464
|
return 'r';
|
483
465
|
}
|
484
466
|
|
485
467
|
// Get IJA positions of the beginning and end of the row
|
486
|
-
if (reinterpret_cast<IType*>(storage->ija)[
|
468
|
+
if (reinterpret_cast<IType*>(storage->ija)[coord0] == reinterpret_cast<IType*>(storage->ija)[coord0+1]) {
|
487
469
|
// empty row
|
488
|
-
ins_type = vector_insert<DType,IType>(storage, reinterpret_cast<IType*>(storage->ija)[
|
489
|
-
increment_ia_after<IType>(storage, storage->shape[0],
|
490
|
-
storage->ndnz++;
|
470
|
+
ins_type = vector_insert<DType,IType>(storage, reinterpret_cast<IType*>(storage->ija)[coord0], &(coord1), v, 1, false);
|
471
|
+
increment_ia_after<IType>(storage, storage->shape[0], coord0, 1);
|
472
|
+
reinterpret_cast<YALE_STORAGE*>(storage->src)->ndnz++;
|
491
473
|
|
492
474
|
return ins_type;
|
493
475
|
}
|
@@ -498,19 +480,19 @@ char set(YALE_STORAGE* storage, SLICE* slice, void* value) {
|
|
498
480
|
|
499
481
|
// Do a binary search for the column
|
500
482
|
size_t pos = insert_search<IType>(storage,
|
501
|
-
reinterpret_cast<IType*>(storage->ija)[
|
502
|
-
reinterpret_cast<IType*>(storage->ija)[
|
503
|
-
|
483
|
+
reinterpret_cast<IType*>(storage->ija)[coord0],
|
484
|
+
reinterpret_cast<IType*>(storage->ija)[coord0+1]-1,
|
485
|
+
coord1, &found);
|
504
486
|
|
505
487
|
if (found) { // replace
|
506
|
-
reinterpret_cast<IType*>(storage->ija)[pos] =
|
488
|
+
reinterpret_cast<IType*>(storage->ija)[pos] = coord1;
|
507
489
|
reinterpret_cast<DType*>(storage->a)[pos] = *v;
|
508
490
|
return 'r';
|
509
491
|
}
|
510
492
|
|
511
|
-
ins_type = vector_insert<DType,IType>(storage, pos, &(
|
512
|
-
increment_ia_after<IType>(storage, storage->shape[0],
|
513
|
-
storage->ndnz++;
|
493
|
+
ins_type = vector_insert<DType,IType>(storage, pos, &(coord1), v, 1, false);
|
494
|
+
increment_ia_after<IType>(storage, storage->shape[0], coord0, 1);
|
495
|
+
reinterpret_cast<YALE_STORAGE*>(storage->src)->ndnz++;
|
514
496
|
|
515
497
|
return ins_type;
|
516
498
|
}
|
@@ -682,6 +664,31 @@ static bool ndrow_is_empty(const YALE_STORAGE* s, IType ija, const IType ija_nex
|
|
682
664
|
// Utility //
|
683
665
|
/////////////
|
684
666
|
|
667
|
+
|
668
|
+
/*
|
669
|
+
* Binary search for finding the beginning of a slice. Returns the position of the first element which is larger than
|
670
|
+
* bound.
|
671
|
+
*/
|
672
|
+
template <typename IType>
|
673
|
+
IType binary_search_left_boundary(const YALE_STORAGE* s, IType left, IType right, IType bound) {
|
674
|
+
if (left > right) return -1;
|
675
|
+
|
676
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
677
|
+
|
678
|
+
if (ija[left] >= bound) return left; // shortcut
|
679
|
+
|
680
|
+
IType mid = (left + right) / 2;
|
681
|
+
IType mid_j = ija[mid];
|
682
|
+
|
683
|
+
if (mid_j == bound)
|
684
|
+
return mid;
|
685
|
+
else if (mid_j > bound) { // eligible! don't exclude it.
|
686
|
+
return binary_search_left_boundary<IType>(s, left, mid, bound);
|
687
|
+
} else // (mid_j < bound)
|
688
|
+
return binary_search_left_boundary<IType>(s, mid + 1, right, bound);
|
689
|
+
}
|
690
|
+
|
691
|
+
|
685
692
|
/*
|
686
693
|
* Binary search for returning stored values. Returns a non-negative position, or -1 for not found.
|
687
694
|
*/
|
@@ -710,6 +717,8 @@ int binary_search(YALE_STORAGE* s, IType left, IType right, IType key) {
|
|
710
717
|
* Resize yale storage vectors A and IJA, copying values.
|
711
718
|
*/
|
712
719
|
static void vector_grow(YALE_STORAGE* s) {
|
720
|
+
if (s->src != s) throw; // need to correct this quickly.
|
721
|
+
|
713
722
|
size_t new_capacity = s->capacity * GROWTH_CONSTANT;
|
714
723
|
size_t max_capacity = max_size(s);
|
715
724
|
|
@@ -742,6 +751,8 @@ static void vector_grow(YALE_STORAGE* s) {
|
|
742
751
|
*/
|
743
752
|
template <typename DType, typename IType>
|
744
753
|
static char vector_insert_resize(YALE_STORAGE* s, size_t current_size, size_t pos, size_t* j, size_t n, bool struct_only) {
|
754
|
+
if (s != s->src) throw;
|
755
|
+
|
745
756
|
// Determine the new capacity for the IJA and A vectors.
|
746
757
|
size_t new_capacity = s->capacity * GROWTH_CONSTANT;
|
747
758
|
size_t max_capacity = max_size(s);
|
@@ -916,15 +927,30 @@ static IType insert_search(YALE_STORAGE* s, IType left, IType right, IType key,
|
|
916
927
|
template <typename LDType, typename RDType, typename IType>
|
917
928
|
YALE_STORAGE* cast_copy(const YALE_STORAGE* rhs, dtype_t new_dtype) {
|
918
929
|
|
919
|
-
|
920
|
-
size_t size = get_size<IType>(rhs);
|
921
|
-
YALE_STORAGE* lhs = copy_alloc_struct<IType>(rhs, new_dtype, rhs->capacity, size);
|
930
|
+
YALE_STORAGE* lhs;
|
922
931
|
|
923
|
-
if (rhs->
|
932
|
+
if (rhs->src != rhs) { // copy the reference
|
933
|
+
// Copy shape for yale construction
|
934
|
+
size_t* shape = ALLOC_N(size_t, 2);
|
935
|
+
shape[0] = rhs->shape[0];
|
936
|
+
shape[1] = rhs->shape[1];
|
937
|
+
size_t ndnz = src_ndnz(rhs);
|
938
|
+
if (shape[0] != rhs->src->shape[0] || shape[1] != rhs->src->shape[1])
|
939
|
+
ndnz = count_slice_copy_ndnz<RDType,IType>(rhs, rhs->offset, rhs->shape); // expensive, avoid if possible
|
940
|
+
size_t request_capacity = shape[0] + ndnz + 1;
|
941
|
+
// FIXME: Should we use a different itype? Or same?
|
942
|
+
lhs = nm_yale_storage_create(new_dtype, shape, 2, request_capacity, rhs->itype);
|
924
943
|
|
925
|
-
|
944
|
+
// This check probably isn't necessary.
|
945
|
+
if (lhs->capacity < request_capacity)
|
946
|
+
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, lhs->capacity);
|
926
947
|
|
927
|
-
|
948
|
+
slice_copy<LDType, RDType, IType>(lhs, rhs, rhs->offset, rhs->shape, new_dtype);
|
949
|
+
} else { // regular copy
|
950
|
+
|
951
|
+
// Allocate a new structure
|
952
|
+
size_t size = get_size<IType>(rhs);
|
953
|
+
lhs = copy_alloc_struct<IType>(rhs, new_dtype, rhs->capacity, size);
|
928
954
|
|
929
955
|
LDType* la = reinterpret_cast<LDType*>(lhs->a);
|
930
956
|
RDType* ra = reinterpret_cast<RDType*>(rhs->a);
|
@@ -932,7 +958,6 @@ YALE_STORAGE* cast_copy(const YALE_STORAGE* rhs, dtype_t new_dtype) {
|
|
932
958
|
for (size_t index = 0; index < size; ++index) {
|
933
959
|
la[index] = ra[index];
|
934
960
|
}
|
935
|
-
|
936
961
|
}
|
937
962
|
|
938
963
|
return lhs;
|
@@ -958,7 +983,10 @@ static YALE_STORAGE* copy_alloc_struct(const YALE_STORAGE* rhs, const dtype_t ne
|
|
958
983
|
lhs->shape = ALLOC_N( size_t, lhs->dim );
|
959
984
|
lhs->offset = ALLOC_N( size_t, lhs->dim );
|
960
985
|
memcpy(lhs->shape, rhs->shape, lhs->dim * sizeof(size_t));
|
961
|
-
memcpy(lhs->
|
986
|
+
//memcpy(lhs->offset, rhs->offset, lhs->dim * sizeof(size_t));
|
987
|
+
lhs->offset[0] = 0;
|
988
|
+
lhs->offset[1] = 0;
|
989
|
+
|
962
990
|
lhs->itype = rhs->itype;
|
963
991
|
lhs->capacity = new_capacity;
|
964
992
|
lhs->dtype = new_dtype;
|
@@ -967,12 +995,16 @@ static YALE_STORAGE* copy_alloc_struct(const YALE_STORAGE* rhs, const dtype_t ne
|
|
967
995
|
lhs->ija = ALLOC_N( IType, lhs->capacity );
|
968
996
|
lhs->a = ALLOC_N( char, DTYPE_SIZES[new_dtype] * lhs->capacity );
|
969
997
|
lhs->src = lhs;
|
998
|
+
lhs->count = 1;
|
970
999
|
|
971
1000
|
// Now copy the contents -- but only within the boundaries set by the size. Leave
|
972
1001
|
// the rest uninitialized.
|
973
|
-
|
974
|
-
|
975
|
-
|
1002
|
+
if (!rhs->offset[0] && !rhs->offset[1]) {
|
1003
|
+
for (size_t i = 0; i < get_size<IType>(rhs); ++i)
|
1004
|
+
reinterpret_cast<IType*>(lhs->ija)[i] = reinterpret_cast<IType*>(rhs->ija)[i]; // copy indices
|
1005
|
+
} else {
|
1006
|
+
rb_raise(rb_eNotImpError, "cannot copy struct due to different offsets");
|
1007
|
+
}
|
976
1008
|
return lhs;
|
977
1009
|
}
|
978
1010
|
|
@@ -1045,13 +1077,6 @@ static std::array<size_t,2> get_offsets(YALE_STORAGE* x) {
|
|
1045
1077
|
}
|
1046
1078
|
|
1047
1079
|
|
1048
|
-
static VALUE obj_at(YALE_STORAGE* s, size_t k) {
|
1049
|
-
if (s->dtype == nm::RUBYOBJ) return reinterpret_cast<VALUE*>(s->a)[k];
|
1050
|
-
else return rubyobj_from_cval(reinterpret_cast<void*>(reinterpret_cast<char*>(s->a) + k * DTYPE_SIZES[s->dtype]), s->dtype).rval;
|
1051
|
-
}
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
1080
|
template <typename IType>
|
1056
1081
|
class IJAManager {
|
1057
1082
|
protected:
|
@@ -1127,10 +1152,6 @@ public:
|
|
1127
1152
|
}
|
1128
1153
|
|
1129
1154
|
inline IType proper_j() const {
|
1130
|
-
//if (!diag && k >= s->capacity) {
|
1131
|
-
// std::cerr << "proper_j(): Warning: (nondiag) k exceeded capacity at row " << int(i) << ": k=" << int(k) << ", cap=" << s->capacity << std::endl;
|
1132
|
-
// throw;
|
1133
|
-
//}
|
1134
1155
|
return diag ? i : ija[k];
|
1135
1156
|
}
|
1136
1157
|
|
@@ -1193,7 +1214,6 @@ public:
|
|
1193
1214
|
} else if (!row_has_diag()) { // row has no diagonal entries
|
1194
1215
|
if (row_has_no_nd() || k_is_last_nd()) End = true; // row is totally empty, or we're at last entry
|
1195
1216
|
else k++; // still entries to visit
|
1196
|
-
// } else if (row_has_no_nd()) { // in this case we started at diag, so don't check it
|
1197
1217
|
} else { // not at diag but it exists somewhere in the row, and row has at least one nd entry
|
1198
1218
|
if (diag_is_ahead()) { // diag is ahead
|
1199
1219
|
if (k_is_last_nd()) diag = true; // diag is next and last
|
@@ -1207,9 +1227,6 @@ public:
|
|
1207
1227
|
}
|
1208
1228
|
}
|
1209
1229
|
|
1210
|
-
//if (k >= s->capacity)
|
1211
|
-
// std::cerr << "operator++: Warning: k has exceeded capacity for row " << int(i) << "; k=" << int(k) << ", cap=" << s->capacity << std::endl;
|
1212
|
-
|
1213
1230
|
return *this;
|
1214
1231
|
}
|
1215
1232
|
|
@@ -1222,6 +1239,7 @@ public:
|
|
1222
1239
|
};
|
1223
1240
|
|
1224
1241
|
|
1242
|
+
|
1225
1243
|
template <typename IType>
|
1226
1244
|
static VALUE map_stored(VALUE self) {
|
1227
1245
|
|
@@ -1236,7 +1254,15 @@ static VALUE map_stored(VALUE self) {
|
|
1236
1254
|
RETURN_SIZED_ENUMERATOR(self, 0, 0, nm_yale_enumerator_length);
|
1237
1255
|
VALUE init = rb_yield(default_value(s));
|
1238
1256
|
|
1239
|
-
|
1257
|
+
// Try to find a reasonable capacity to request when creating the matrix
|
1258
|
+
size_t ndnz = src_ndnz(s);
|
1259
|
+
if (s->src != s) // need to guess capacity
|
1260
|
+
ndnz = yale_count_slice_copy_ndnz(s, s->offset, s->shape);
|
1261
|
+
size_t request_capacity = s->shape[0] + ndnz + 1;
|
1262
|
+
|
1263
|
+
YALE_STORAGE* r = nm_yale_storage_create(nm::RUBYOBJ, shape, 2, request_capacity, NM_ITYPE(self));
|
1264
|
+
if (r->capacity < request_capacity)
|
1265
|
+
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, r->capacity);
|
1240
1266
|
nm_yale_storage_init(r, &init);
|
1241
1267
|
|
1242
1268
|
for (IType ri = 0; ri < shape[0]; ++ri) {
|
@@ -1314,7 +1340,16 @@ static VALUE map_merged_stored(VALUE left, VALUE right, VALUE init, nm::itype_t
|
|
1314
1340
|
if (init == Qnil)
|
1315
1341
|
init = rb_yield_values(2, s_init, t_init);
|
1316
1342
|
|
1317
|
-
|
1343
|
+
// Make a reasonable approximation of the resulting capacity
|
1344
|
+
size_t s_ndnz = src_ndnz(s), t_ndnz = src_ndnz(t);
|
1345
|
+
if (s->src != s) s_ndnz = yale_count_slice_copy_ndnz(s, s->offset, s->shape);
|
1346
|
+
if (t->src != t) t_ndnz = yale_count_slice_copy_ndnz(t, t->offset, t->shape);
|
1347
|
+
size_t request_capacity = shape[0] + NM_MAX(s_ndnz, t_ndnz) + 1;
|
1348
|
+
|
1349
|
+
YALE_STORAGE* r = nm_yale_storage_create(nm::RUBYOBJ, shape, 2, request_capacity, itype);
|
1350
|
+
if (r->capacity < request_capacity)
|
1351
|
+
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, r->capacity);
|
1352
|
+
|
1318
1353
|
nm_yale_storage_init(r, &init);
|
1319
1354
|
|
1320
1355
|
IJAManager<IType> sm(s, itype),
|
@@ -1325,7 +1360,7 @@ static VALUE map_merged_stored(VALUE left, VALUE right, VALUE init, nm::itype_t
|
|
1325
1360
|
RowIterator<IType> tit(t, tm.ija, ri + t_offsets[0], shape[1], t_offsets[1]);
|
1326
1361
|
|
1327
1362
|
RowIterator<IType> rit(r, reinterpret_cast<IType*>(r->ija), ri, shape[1]);
|
1328
|
-
while (!
|
1363
|
+
while (!sit.end() || !tit.end()) {
|
1329
1364
|
VALUE rv;
|
1330
1365
|
IType rj;
|
1331
1366
|
|
@@ -1360,179 +1395,99 @@ static VALUE map_merged_stored(VALUE left, VALUE right, VALUE init, nm::itype_t
|
|
1360
1395
|
}
|
1361
1396
|
|
1362
1397
|
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
// the matrix's storage.
|
1368
|
-
static VALUE nm_yale_stored_enumerator_length(VALUE nmatrix) {
|
1369
|
-
long len = nm_yale_storage_get_size(NM_STORAGE_YALE(nmatrix));
|
1370
|
-
return LONG2NUM(len);
|
1371
|
-
}
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1398
|
+
/*
|
1399
|
+
* This function and the two helper structs enable us to use partial template specialization.
|
1400
|
+
* See also: http://stackoverflow.com/questions/6623375/c-template-specialization-on-functions
|
1401
|
+
*/
|
1375
1402
|
template <typename DType, typename IType>
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
DType* a = reinterpret_cast<DType*>(s->a);
|
1381
|
-
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1382
|
-
|
1383
|
-
// If we don't have a block, return an enumerator.
|
1384
|
-
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_enumerator_length);
|
1403
|
+
static VALUE each_stored_with_indices(VALUE nm) {
|
1404
|
+
YALE_STORAGE* s = NM_STORAGE_YALE(nm);
|
1405
|
+
DType* a = reinterpret_cast<DType*>(s->a);
|
1406
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1385
1407
|
|
1386
|
-
|
1387
|
-
|
1388
|
-
VALUE ii = LONG2NUM(i);
|
1408
|
+
// If we don't have a block, return an enumerator.
|
1409
|
+
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_stored_enumerator_length);
|
1389
1410
|
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
// zero is stored in s->shape[0]
|
1396
|
-
if (i == j) {
|
1397
|
-
v = rubyobj_from_cval(&(a[i]), NM_DTYPE(nm)).rval;
|
1398
|
-
} else {
|
1399
|
-
// Walk through the row until we find the correct location.
|
1400
|
-
while (ija[k] < j && k < k_next) ++k;
|
1401
|
-
if (k < k_next && ija[k] == j) {
|
1402
|
-
v = rubyobj_from_cval(&(a[k]), NM_DTYPE(nm)).rval;
|
1403
|
-
++k;
|
1404
|
-
} else v = rubyobj_from_cval(&(a[s->shape[0]]), NM_DTYPE(nm)).rval;
|
1405
|
-
}
|
1406
|
-
rb_yield_values(3, v, ii, jj);
|
1407
|
-
}
|
1408
|
-
}
|
1411
|
+
// Iterate along diagonal
|
1412
|
+
for (size_t sk = NM_MAX(s->offset[0], s->offset[1]); sk < NM_MIN(s->shape[0] + s->offset[0], s->shape[1] + s->offset[1]); ++sk) {
|
1413
|
+
VALUE ii = LONG2NUM(sk - s->offset[0]),
|
1414
|
+
jj = LONG2NUM(sk - s->offset[1]);
|
1409
1415
|
|
1410
|
-
|
1416
|
+
rb_yield_values(3, obj_at(s, sk), ii, jj);
|
1411
1417
|
}
|
1412
1418
|
|
1419
|
+
// Iterate through non-diagonal elements, row by row
|
1420
|
+
for (long ri = 0; ri < s->shape[0]; ++ri) {
|
1421
|
+
long si = ri + s->offset[0];
|
1422
|
+
IType p = ija[si],
|
1423
|
+
next_p = ija[si+1];
|
1413
1424
|
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
DType* a = reinterpret_cast<DType*>(s->a);
|
1418
|
-
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1419
|
-
|
1420
|
-
// If we don't have a block, return an enumerator.
|
1421
|
-
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_stored_enumerator_length);
|
1422
|
-
|
1423
|
-
// Iterate along diagonal
|
1424
|
-
for (size_t k = 0; k < s->shape[0]; ++k) {
|
1425
|
-
VALUE ii = LONG2NUM(k),
|
1426
|
-
jj = LONG2NUM(k);
|
1425
|
+
// if this is a reference to another matrix, we should find the left boundary of the slice
|
1426
|
+
if (s != s->src && p < next_p)
|
1427
|
+
p = binary_search_left_boundary<IType>(s, p, next_p-1, s->offset[1]);
|
1427
1428
|
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
// Iterate through non-diagonal elements, row by row
|
1433
|
-
for (long i = 0; i < s->shape[0]; ++i) {
|
1434
|
-
long p = static_cast<long>( ija[i] ),
|
1435
|
-
next_p = static_cast<long>( ija[i+1] );
|
1429
|
+
for (; p < next_p; ++p) {
|
1430
|
+
long sj = static_cast<long>(ija[p]),
|
1431
|
+
rj = sj - s->offset[1];
|
1432
|
+
if (rj < 0) continue;
|
1436
1433
|
|
1437
|
-
|
1438
|
-
long j = static_cast<long>(ija[p]);
|
1439
|
-
VALUE ii = LONG2NUM(i),
|
1440
|
-
jj = LONG2NUM(j);
|
1434
|
+
if (rj >= s->shape[1]) break;
|
1441
1435
|
|
1442
|
-
|
1443
|
-
rb_yield_values(3, v, ii, jj);
|
1444
|
-
}
|
1436
|
+
rb_yield_values(3, obj_at(s, p), LONG2NUM(ri), LONG2NUM(rj));
|
1445
1437
|
}
|
1446
|
-
|
1447
|
-
return nm;
|
1448
1438
|
}
|
1449
|
-
};
|
1450
1439
|
|
1440
|
+
return nm;
|
1441
|
+
}
|
1451
1442
|
|
1452
|
-
template <typename IType>
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1443
|
+
template <typename DType, typename IType>
|
1444
|
+
static VALUE each_with_indices(VALUE nm) {
|
1445
|
+
YALE_STORAGE* s = NM_STORAGE_YALE(nm);
|
1446
|
+
DType* a = reinterpret_cast<DType*>(s->a);
|
1447
|
+
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1458
1448
|
|
1459
|
-
|
1460
|
-
|
1449
|
+
// If we don't have a block, return an enumerator.
|
1450
|
+
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_enumerator_length);
|
1461
1451
|
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1452
|
+
// Iterate in two dimensions.
|
1453
|
+
// s stands for src, r stands for ref (for ri, rj, si, sj)
|
1454
|
+
for (long ri = 0; ri < s->shape[0]; ++ri) {
|
1455
|
+
long si = ri + s->offset[0];
|
1456
|
+
VALUE ii = LONG2NUM(ri + s->offset[0]);
|
1465
1457
|
|
1466
|
-
|
1458
|
+
IType k = ija[si], k_next = ija[si+1];
|
1467
1459
|
|
1468
|
-
|
1469
|
-
|
1460
|
+
for (long rj = 0; rj < s->shape[1]; ++rj) {
|
1461
|
+
long sj = rj + s->offset[1];
|
1462
|
+
VALUE v, jj = LONG2NUM(rj);
|
1470
1463
|
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
}
|
1482
|
-
rb_yield_values(3, v, ii, jj);
|
1464
|
+
// zero is stored in s->shape[0]
|
1465
|
+
if (si == sj) {
|
1466
|
+
v = obj_at(s, si);
|
1467
|
+
} else {
|
1468
|
+
// Walk through the row until we find the correct location.
|
1469
|
+
while (ija[k] < sj && k < k_next) ++k;
|
1470
|
+
if (k < k_next && ija[k] == sj) {
|
1471
|
+
v = obj_at(s, k);
|
1472
|
+
++k;
|
1473
|
+
} else v = default_value(s); // rubyobj_from_cval(&(a[s->shape[0]]), NM_DTYPE(nm)).rval;
|
1483
1474
|
}
|
1475
|
+
rb_yield_values(3, v, ii, jj);
|
1484
1476
|
}
|
1485
|
-
|
1486
|
-
return nm;
|
1487
1477
|
}
|
1488
1478
|
|
1489
|
-
|
1490
|
-
|
1491
|
-
YALE_STORAGE* s = NM_STORAGE_YALE(nm);
|
1492
|
-
RubyObject* a = reinterpret_cast<RubyObject*>(s->a);
|
1493
|
-
IType* ija = reinterpret_cast<IType*>(s->ija);
|
1494
|
-
|
1495
|
-
// If we don't have a block, return an enumerator.
|
1496
|
-
RETURN_SIZED_ENUMERATOR(nm, 0, 0, nm_yale_stored_enumerator_length);
|
1497
|
-
|
1498
|
-
// Iterate along diagonal
|
1499
|
-
for (size_t k = 0; k < s->shape[0]; ++k) {
|
1500
|
-
VALUE ii = LONG2NUM(k),
|
1501
|
-
jj = LONG2NUM(k);
|
1502
|
-
rb_yield_values(3, a[k].rval, ii, jj ); // yield element, i, j
|
1503
|
-
}
|
1504
|
-
|
1505
|
-
// Iterate through non-diagonal elements, row by row
|
1506
|
-
for (long i = 0; i < s->shape[0]; ++i) {
|
1507
|
-
IType p = ija[i],
|
1508
|
-
next_p = ija[i+1];
|
1509
|
-
|
1510
|
-
for (; p < next_p; ++p) {
|
1511
|
-
long j = static_cast<long>(ija[p]);
|
1512
|
-
VALUE ii = LONG2NUM(i),
|
1513
|
-
jj = LONG2NUM(j);
|
1514
|
-
|
1515
|
-
rb_yield_values(3, a[p].rval, ii, jj );
|
1516
|
-
}
|
1517
|
-
}
|
1479
|
+
return nm;
|
1480
|
+
}
|
1518
1481
|
|
1519
|
-
return nm;
|
1520
|
-
}
|
1521
|
-
};
|
1522
1482
|
|
1483
|
+
} // end of namespace nm::yale_storage
|
1523
1484
|
|
1524
|
-
/*
|
1525
|
-
* This function and the two helper structs enable us to use partial template specialization.
|
1526
|
-
* See also: http://stackoverflow.com/questions/6623375/c-template-specialization-on-functions
|
1527
|
-
*/
|
1528
|
-
template <typename DType, typename IType>
|
1529
|
-
static VALUE yale_each_stored_with_indices(VALUE nm) {
|
1530
|
-
return yale_iteration_helper<DType, IType>::iterate_stored_with_indices(nm);
|
1531
|
-
}
|
1532
1485
|
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1486
|
+
// Helper function used only for the RETURN_SIZED_ENUMERATOR macro. Returns the length of
|
1487
|
+
// the matrix's storage.
|
1488
|
+
static VALUE nm_yale_stored_enumerator_length(VALUE nmatrix) {
|
1489
|
+
long len = nm_yale_storage_get_size(NM_STORAGE_YALE(nmatrix));
|
1490
|
+
return LONG2NUM(len);
|
1536
1491
|
}
|
1537
1492
|
|
1538
1493
|
|
@@ -1577,7 +1532,7 @@ VALUE nm_yale_each_with_indices(VALUE nmatrix) {
|
|
1577
1532
|
nm::dtype_t d = NM_DTYPE(nmatrix);
|
1578
1533
|
nm::itype_t i = NM_ITYPE(nmatrix);
|
1579
1534
|
|
1580
|
-
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::
|
1535
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::each_with_indices, VALUE, VALUE)
|
1581
1536
|
|
1582
1537
|
return ttable[d][i](nmatrix);
|
1583
1538
|
}
|
@@ -1588,7 +1543,7 @@ VALUE nm_yale_each_stored_with_indices(VALUE nmatrix) {
|
|
1588
1543
|
nm::dtype_t d = NM_DTYPE(nmatrix);
|
1589
1544
|
nm::itype_t i = NM_ITYPE(nmatrix);
|
1590
1545
|
|
1591
|
-
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::
|
1546
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::each_stored_with_indices, VALUE, VALUE)
|
1592
1547
|
|
1593
1548
|
return ttable[d][i](nmatrix);
|
1594
1549
|
}
|
@@ -1606,18 +1561,53 @@ char nm_yale_storage_set(STORAGE* storage, SLICE* slice, void* v) {
|
|
1606
1561
|
return ttable[casted_storage->dtype][casted_storage->itype](casted_storage, slice, v);
|
1607
1562
|
}
|
1608
1563
|
|
1564
|
+
|
1565
|
+
/*
|
1566
|
+
* Determine the number of non-diagonal non-zeros in a not-yet-created copy of a slice or matrix.
|
1567
|
+
*/
|
1568
|
+
static size_t yale_count_slice_copy_ndnz(const YALE_STORAGE* s, size_t* offset, size_t* shape) {
|
1569
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::count_slice_copy_ndnz, size_t, const YALE_STORAGE*, size_t*, size_t*)
|
1570
|
+
|
1571
|
+
return ttable[s->dtype][s->itype](s, offset, shape);
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
|
1609
1575
|
/*
|
1610
|
-
* C accessor for yale_storage::get, which returns a slice of YALE_STORAGE object by
|
1576
|
+
* C accessor for yale_storage::get, which returns a slice of YALE_STORAGE object by copy
|
1611
1577
|
*
|
1612
1578
|
* Slicing-related.
|
1613
1579
|
*/
|
1614
1580
|
void* nm_yale_storage_get(STORAGE* storage, SLICE* slice) {
|
1615
|
-
|
1616
|
-
YALE_STORAGE* s = (YALE_STORAGE*)storage;
|
1581
|
+
YALE_STORAGE* casted_storage = (YALE_STORAGE*)storage;
|
1617
1582
|
|
1583
|
+
if (slice->single) {
|
1584
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(elem_copy_table, nm::yale_storage::get_single, void*, YALE_STORAGE*, SLICE*)
|
1618
1585
|
|
1619
|
-
|
1620
|
-
|
1586
|
+
return elem_copy_table[casted_storage->dtype][casted_storage->itype](casted_storage, slice);
|
1587
|
+
} else {
|
1588
|
+
// Copy shape for yale construction
|
1589
|
+
size_t* shape = ALLOC_N(size_t, 2);
|
1590
|
+
shape[0] = slice->lengths[0];
|
1591
|
+
shape[1] = slice->lengths[1];
|
1592
|
+
|
1593
|
+
// only count ndnz if our slice is smaller, otherwise use the given value
|
1594
|
+
size_t ndnz = src_ndnz(casted_storage);
|
1595
|
+
if (shape[0] != casted_storage->shape[0] || shape[1] != casted_storage->shape[1])
|
1596
|
+
ndnz = yale_count_slice_copy_ndnz(casted_storage, slice->coords, shape); // expensive operation
|
1597
|
+
|
1598
|
+
size_t request_capacity = shape[0] + ndnz + 1; // capacity of new matrix
|
1599
|
+
YALE_STORAGE* ns = nm_yale_storage_create(casted_storage->dtype, shape, 2, request_capacity, casted_storage->itype);
|
1600
|
+
|
1601
|
+
// This check probably isn't necessary.
|
1602
|
+
if (ns->capacity < request_capacity)
|
1603
|
+
rb_raise(nm_eStorageTypeError, "conversion failed; capacity of %ld requested, max allowable is %ld", request_capacity, ns->capacity);
|
1604
|
+
|
1605
|
+
NAMED_LRI_DTYPE_TEMPLATE_TABLE(slice_copy_table, nm::yale_storage::slice_copy, void, YALE_STORAGE* ns, const YALE_STORAGE* s, size_t*, size_t*, nm::dtype_t)
|
1606
|
+
|
1607
|
+
slice_copy_table[ns->dtype][casted_storage->dtype][casted_storage->itype](ns, casted_storage, slice->coords, slice->lengths, casted_storage->dtype);
|
1608
|
+
|
1609
|
+
return ns;
|
1610
|
+
}
|
1621
1611
|
}
|
1622
1612
|
|
1623
1613
|
/*
|
@@ -1644,10 +1634,15 @@ static void nm_yale_storage_increment_ia_after(YALE_STORAGE* s, size_t ija_size,
|
|
1644
1634
|
* for some set of coordinates.
|
1645
1635
|
*/
|
1646
1636
|
void* nm_yale_storage_ref(STORAGE* storage, SLICE* slice) {
|
1647
|
-
NAMED_LI_DTYPE_TEMPLATE_TABLE(ttable, nm::yale_storage::ref, void*, YALE_STORAGE* storage, SLICE* slice);
|
1648
|
-
|
1649
1637
|
YALE_STORAGE* casted_storage = (YALE_STORAGE*)storage;
|
1650
|
-
|
1638
|
+
|
1639
|
+
if (slice->single) {
|
1640
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(elem_copy_table, nm::yale_storage::get_single, void*, YALE_STORAGE*, SLICE*)
|
1641
|
+
return elem_copy_table[casted_storage->dtype][casted_storage->itype](casted_storage, slice);
|
1642
|
+
} else {
|
1643
|
+
NAMED_LI_DTYPE_TEMPLATE_TABLE(ref_table, nm::yale_storage::ref, void*, YALE_STORAGE* storage, SLICE* slice)
|
1644
|
+
return ref_table[casted_storage->dtype][casted_storage->itype](casted_storage, slice);
|
1645
|
+
}
|
1651
1646
|
}
|
1652
1647
|
|
1653
1648
|
|
@@ -1685,11 +1680,20 @@ size_t nm_yale_storage_get_size(const YALE_STORAGE* storage) {
|
|
1685
1680
|
}
|
1686
1681
|
|
1687
1682
|
|
1683
|
+
|
1688
1684
|
/*
|
1689
1685
|
* Return a void pointer to the matrix's default value entry.
|
1690
1686
|
*/
|
1691
1687
|
static void* default_value_ptr(const YALE_STORAGE* s) {
|
1692
|
-
return reinterpret_cast<void*>(reinterpret_cast<char*>(s->a) + (s->shape[0] * DTYPE_SIZES[s->dtype]));
|
1688
|
+
return reinterpret_cast<void*>(reinterpret_cast<char*>(s->a) + (s->src->shape[0] * DTYPE_SIZES[s->dtype]));
|
1689
|
+
}
|
1690
|
+
|
1691
|
+
/*
|
1692
|
+
* Return the Ruby object at a given location in storage.
|
1693
|
+
*/
|
1694
|
+
static VALUE obj_at(YALE_STORAGE* s, size_t k) {
|
1695
|
+
if (s->dtype == nm::RUBYOBJ) return reinterpret_cast<VALUE*>(s->a)[k];
|
1696
|
+
else return rubyobj_from_cval(reinterpret_cast<void*>(reinterpret_cast<char*>(s->a) + k * DTYPE_SIZES[s->dtype]), s->dtype).rval;
|
1693
1697
|
}
|
1694
1698
|
|
1695
1699
|
|
@@ -1816,11 +1820,26 @@ YALE_STORAGE* nm_yale_storage_create(nm::dtype_t dtype, size_t* shape, size_t di
|
|
1816
1820
|
void nm_yale_storage_delete(STORAGE* s) {
|
1817
1821
|
if (s) {
|
1818
1822
|
YALE_STORAGE* storage = (YALE_STORAGE*)s;
|
1823
|
+
if (storage->count-- == 1) {
|
1824
|
+
xfree(storage->shape);
|
1825
|
+
xfree(storage->offset);
|
1826
|
+
xfree(storage->ija);
|
1827
|
+
xfree(storage->a);
|
1828
|
+
xfree(storage);
|
1829
|
+
}
|
1830
|
+
}
|
1831
|
+
}
|
1832
|
+
|
1833
|
+
/*
|
1834
|
+
* Destructor for the yale storage ref
|
1835
|
+
*/
|
1836
|
+
void nm_yale_storage_delete_ref(STORAGE* s) {
|
1837
|
+
if (s) {
|
1838
|
+
YALE_STORAGE* storage = (YALE_STORAGE*)s;
|
1839
|
+
nm_yale_storage_delete( reinterpret_cast<STORAGE*>(storage->src) );
|
1819
1840
|
xfree(storage->shape);
|
1820
1841
|
xfree(storage->offset);
|
1821
|
-
xfree(
|
1822
|
-
xfree(storage->a);
|
1823
|
-
xfree(storage);
|
1842
|
+
xfree(s);
|
1824
1843
|
}
|
1825
1844
|
}
|
1826
1845
|
|
@@ -1850,6 +1869,7 @@ void nm_yale_storage_mark(void* storage_base) {
|
|
1850
1869
|
}
|
1851
1870
|
}
|
1852
1871
|
|
1872
|
+
|
1853
1873
|
/*
|
1854
1874
|
* Allocates and initializes the basic struct (but not the IJA or A vectors).
|
1855
1875
|
*/
|
@@ -1867,6 +1887,7 @@ static YALE_STORAGE* alloc(nm::dtype_t dtype, size_t* shape, size_t dim, nm::ity
|
|
1867
1887
|
s->dim = dim;
|
1868
1888
|
s->itype = nm_yale_storage_itype_by_shape(shape);
|
1869
1889
|
s->src = reinterpret_cast<STORAGE*>(s);
|
1890
|
+
s->count = 1;
|
1870
1891
|
|
1871
1892
|
// See if a higher itype has been requested.
|
1872
1893
|
if (static_cast<int8_t>(s->itype) < static_cast<int8_t>(min_itype))
|
@@ -1935,7 +1956,7 @@ static VALUE nm_a(int argc, VALUE* argv, VALUE self) {
|
|
1935
1956
|
}
|
1936
1957
|
VALUE ary = rb_ary_new4(size, vals);
|
1937
1958
|
|
1938
|
-
for (size_t i = size; i < s->capacity; ++i)
|
1959
|
+
for (size_t i = size; i < reinterpret_cast<YALE_STORAGE*>(s->src)->capacity; ++i)
|
1939
1960
|
rb_ary_push(ary, Qnil);
|
1940
1961
|
|
1941
1962
|
return ary;
|
@@ -2008,7 +2029,7 @@ static VALUE nm_lu(VALUE self) {
|
|
2008
2029
|
|
2009
2030
|
VALUE ary = rb_ary_new4(size - s->shape[0] - 1, vals);
|
2010
2031
|
|
2011
|
-
for (size_t i = size; i < s->capacity; ++i)
|
2032
|
+
for (size_t i = size; i < reinterpret_cast<YALE_STORAGE*>(s->src)->capacity; ++i)
|
2012
2033
|
rb_ary_push(ary, Qnil);
|
2013
2034
|
|
2014
2035
|
return ary;
|
@@ -2053,7 +2074,7 @@ static VALUE nm_ja(VALUE self) {
|
|
2053
2074
|
|
2054
2075
|
VALUE ary = rb_ary_new4(size - s->shape[0] - 1, vals);
|
2055
2076
|
|
2056
|
-
for (size_t i = size; i < s->capacity; ++i)
|
2077
|
+
for (size_t i = size; i < reinterpret_cast<YALE_STORAGE*>(s->src)->capacity; ++i)
|
2057
2078
|
rb_ary_push(ary, Qnil);
|
2058
2079
|
|
2059
2080
|
return ary;
|
@@ -2083,7 +2104,7 @@ static VALUE nm_ija(int argc, VALUE* argv, VALUE self) {
|
|
2083
2104
|
|
2084
2105
|
VALUE ary = rb_ary_new4(size, vals);
|
2085
2106
|
|
2086
|
-
for (size_t i = size; i < s->capacity; ++i)
|
2107
|
+
for (size_t i = size; i < reinterpret_cast<YALE_STORAGE*>(s->src)->capacity; ++i)
|
2087
2108
|
rb_ary_push(ary, Qnil);
|
2088
2109
|
|
2089
2110
|
return ary;
|
@@ -2127,9 +2148,7 @@ static VALUE nm_nd_row(int argc, VALUE* argv, VALUE self) {
|
|
2127
2148
|
size_t nextpos = FIX2INT(rubyobj_from_cval_by_itype((char*)(s->ija) + ITYPE_SIZES[itype]*(i+1), itype).rval);
|
2128
2149
|
size_t diff = nextpos - pos;
|
2129
2150
|
|
2130
|
-
|
2131
|
-
|
2132
|
-
VALUE ret; // HERE
|
2151
|
+
VALUE ret;
|
2133
2152
|
if (keys) {
|
2134
2153
|
ret = rb_ary_new3(diff);
|
2135
2154
|
|
@@ -2212,7 +2231,7 @@ VALUE nm_vector_set(int argc, VALUE* argv, VALUE self) { //, VALUE i_, VALUE jv,
|
|
2212
2231
|
|
2213
2232
|
char ins_type = nm_yale_storage_vector_insert(s, pos, j, vals, len, false, dtype, itype);
|
2214
2233
|
nm_yale_storage_increment_ia_after(s, s->shape[0], i, len, itype);
|
2215
|
-
s->ndnz += len;
|
2234
|
+
reinterpret_cast<YALE_STORAGE*>(s->src)->ndnz += len;
|
2216
2235
|
|
2217
2236
|
// Return the updated position
|
2218
2237
|
pos += len;
|