nmatrix 0.2.0 → 0.2.1
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/ext/nmatrix/data/complex.h +183 -159
- data/ext/nmatrix/data/data.cpp +113 -112
- data/ext/nmatrix/data/data.h +306 -292
- data/ext/nmatrix/data/ruby_object.h +193 -193
- data/ext/nmatrix/extconf.rb +11 -9
- data/ext/nmatrix/math.cpp +9 -11
- data/ext/nmatrix/math/math.h +3 -2
- data/ext/nmatrix/math/trsm.h +152 -152
- data/ext/nmatrix/nmatrix.h +30 -0
- data/ext/nmatrix/ruby_constants.cpp +67 -67
- data/ext/nmatrix/ruby_constants.h +35 -35
- data/ext/nmatrix/ruby_nmatrix.c +168 -183
- data/ext/nmatrix/storage/common.h +4 -3
- data/ext/nmatrix/storage/dense/dense.cpp +50 -50
- data/ext/nmatrix/storage/dense/dense.h +8 -7
- data/ext/nmatrix/storage/list/list.cpp +16 -16
- data/ext/nmatrix/storage/list/list.h +7 -6
- data/ext/nmatrix/storage/storage.cpp +32 -32
- data/ext/nmatrix/storage/storage.h +12 -11
- data/ext/nmatrix/storage/yale/class.h +2 -2
- data/ext/nmatrix/storage/yale/iterators/base.h +2 -1
- data/ext/nmatrix/storage/yale/iterators/iterator.h +2 -1
- data/ext/nmatrix/storage/yale/iterators/row.h +2 -1
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +2 -1
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +1 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +2 -1
- data/ext/nmatrix/storage/yale/yale.cpp +27 -27
- data/ext/nmatrix/storage/yale/yale.h +7 -6
- data/ext/nmatrix/ttable_helper.rb +10 -10
- data/ext/nmatrix/types.h +3 -2
- data/ext/nmatrix/util/io.cpp +7 -7
- data/ext/nmatrix/util/sl_list.cpp +26 -26
- data/ext/nmatrix/util/sl_list.h +19 -18
- data/lib/nmatrix/blas.rb +7 -7
- data/lib/nmatrix/io/mat5_reader.rb +30 -30
- data/lib/nmatrix/math.rb +73 -17
- data/lib/nmatrix/nmatrix.rb +10 -8
- data/lib/nmatrix/shortcuts.rb +3 -3
- data/lib/nmatrix/version.rb +3 -3
- data/spec/00_nmatrix_spec.rb +6 -0
- data/spec/math_spec.rb +77 -0
- data/spec/spec_helper.rb +9 -0
- metadata +2 -2
@@ -32,6 +32,7 @@
|
|
32
32
|
* Standard Includes
|
33
33
|
*/
|
34
34
|
|
35
|
+
#include <ruby.h>
|
35
36
|
#include <cmath> // pow().
|
36
37
|
|
37
38
|
/*
|
@@ -57,9 +58,9 @@ struct STORAGE_PAIR {
|
|
57
58
|
};
|
58
59
|
|
59
60
|
struct SLICE {
|
60
|
-
size_t*
|
61
|
-
size_t*
|
62
|
-
bool
|
61
|
+
size_t* coords; // Coordinate of first element
|
62
|
+
size_t* lengths; // Lengths of slice
|
63
|
+
bool single; // true if all lengths equal to 1 (represents single matrix element)
|
63
64
|
};
|
64
65
|
|
65
66
|
/*
|
@@ -62,8 +62,8 @@ namespace nm { namespace dense_storage {
|
|
62
62
|
template <typename LDType, typename RDType>
|
63
63
|
DENSE_STORAGE* cast_copy(const DENSE_STORAGE* rhs, nm::dtype_t new_dtype);
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
template <typename LDType, typename RDType>
|
66
|
+
bool eqeq(const DENSE_STORAGE* left, const DENSE_STORAGE* right);
|
67
67
|
|
68
68
|
template <typename DType>
|
69
69
|
static DENSE_STORAGE* matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resulting_shape, bool vector);
|
@@ -216,7 +216,7 @@ static DENSE_STORAGE* nm_dense_storage_create_dummy(nm::dtype_t dtype, size_t* s
|
|
216
216
|
s->count = 1;
|
217
217
|
s->src = s;
|
218
218
|
|
219
|
-
|
219
|
+
s->elements = NULL;
|
220
220
|
|
221
221
|
return s;
|
222
222
|
}
|
@@ -255,7 +255,7 @@ DENSE_STORAGE* nm_dense_storage_create(nm::dtype_t dtype, size_t* shape, size_t
|
|
255
255
|
for (size_t i = 0; i < count; i += elements_length) {
|
256
256
|
|
257
257
|
if (i + elements_length > count) {
|
258
|
-
|
258
|
+
copy_length = count - i;
|
259
259
|
}
|
260
260
|
|
261
261
|
memcpy((char*)(s->elements)+i*DTYPE_SIZES[dtype], (char*)(elements)+(i % elements_length)*DTYPE_SIZES[dtype], copy_length*DTYPE_SIZES[dtype]);
|
@@ -316,7 +316,7 @@ void nm_dense_storage_mark(STORAGE* storage_base) {
|
|
316
316
|
if (els) {
|
317
317
|
rb_gc_mark_locations(els, &(els[nm_storage_count_max_elements(storage)-1]));
|
318
318
|
}
|
319
|
-
|
319
|
+
//for (size_t index = nm_storage_count_max_elements(storage); index-- > 0;) {
|
320
320
|
// rb_gc_mark(els[index]);
|
321
321
|
//}
|
322
322
|
}
|
@@ -390,9 +390,9 @@ VALUE nm_dense_map_pair(VALUE self, VALUE right) {
|
|
390
390
|
size_t s_index = nm_dense_storage_pos(s, coords),
|
391
391
|
t_index = nm_dense_storage_pos(t, coords);
|
392
392
|
|
393
|
-
VALUE sval = NM_DTYPE(self) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(s->elements)[s_index] : rubyobj_from_cval((char*)(s->elements) + s_index*DTYPE_SIZES[NM_DTYPE(self)], NM_DTYPE(self)).rval;
|
393
|
+
VALUE sval = NM_DTYPE(self) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(s->elements)[s_index] : nm::rubyobj_from_cval((char*)(s->elements) + s_index*DTYPE_SIZES[NM_DTYPE(self)], NM_DTYPE(self)).rval;
|
394
394
|
nm_register_value(&sval);
|
395
|
-
VALUE tval = NM_DTYPE(right) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(t->elements)[t_index] : rubyobj_from_cval((char*)(t->elements) + t_index*DTYPE_SIZES[NM_DTYPE(right)], NM_DTYPE(right)).rval;
|
395
|
+
VALUE tval = NM_DTYPE(right) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(t->elements)[t_index] : nm::rubyobj_from_cval((char*)(t->elements) + t_index*DTYPE_SIZES[NM_DTYPE(right)], NM_DTYPE(right)).rval;
|
396
396
|
result_elem[k] = rb_yield_values(2, sval, tval);
|
397
397
|
nm_unregister_value(&sval);
|
398
398
|
}
|
@@ -442,7 +442,7 @@ VALUE nm_dense_map(VALUE self) {
|
|
442
442
|
nm_dense_storage_coords(result, k, coords);
|
443
443
|
size_t s_index = nm_dense_storage_pos(s, coords);
|
444
444
|
|
445
|
-
result_elem[k] = rb_yield(NM_DTYPE(self) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(s->elements)[s_index] : rubyobj_from_cval((char*)(s->elements) + s_index*DTYPE_SIZES[NM_DTYPE(self)], NM_DTYPE(self)).rval);
|
445
|
+
result_elem[k] = rb_yield(NM_DTYPE(self) == nm::RUBYOBJ ? reinterpret_cast<VALUE*>(s->elements)[s_index] : nm::rubyobj_from_cval((char*)(s->elements) + s_index*DTYPE_SIZES[NM_DTYPE(self)], NM_DTYPE(self)).rval);
|
446
446
|
}
|
447
447
|
|
448
448
|
VALUE klass = CLASS_OF(self);
|
@@ -488,7 +488,7 @@ VALUE nm_dense_each_with_indices(VALUE nmatrix) {
|
|
488
488
|
VALUE ary = rb_ary_new();
|
489
489
|
nm_register_value(&ary);
|
490
490
|
if (NM_DTYPE(nmatrix) == nm::RUBYOBJ) rb_ary_push(ary, reinterpret_cast<VALUE*>(s->elements)[slice_index]);
|
491
|
-
else rb_ary_push(ary, rubyobj_from_cval((char*)(s->elements) + slice_index*DTYPE_SIZES[NM_DTYPE(nmatrix)], NM_DTYPE(nmatrix)).rval);
|
491
|
+
else rb_ary_push(ary, nm::rubyobj_from_cval((char*)(s->elements) + slice_index*DTYPE_SIZES[NM_DTYPE(nmatrix)], NM_DTYPE(nmatrix)).rval);
|
492
492
|
|
493
493
|
for (size_t p = 0; p < s->dim; ++p) {
|
494
494
|
rb_ary_push(ary, INT2FIX(coords[p]));
|
@@ -547,7 +547,7 @@ VALUE nm_dense_each(VALUE nmatrix) {
|
|
547
547
|
for (size_t i = 0; i < nm_storage_count_max_elements(s); ++i) {
|
548
548
|
nm_dense_storage_coords(sliced_dummy, i, temp_coords);
|
549
549
|
sliced_index = nm_dense_storage_pos(s, temp_coords);
|
550
|
-
VALUE v = rubyobj_from_cval((char*)(s->elements) + sliced_index*DTYPE_SIZES[NM_DTYPE(nmatrix)], NM_DTYPE(nmatrix)).rval;
|
550
|
+
VALUE v = nm::rubyobj_from_cval((char*)(s->elements) + sliced_index*DTYPE_SIZES[NM_DTYPE(nmatrix)], NM_DTYPE(nmatrix)).rval;
|
551
551
|
rb_yield( v ); // yield to the copy we made
|
552
552
|
}
|
553
553
|
}
|
@@ -657,7 +657,7 @@ void nm_dense_storage_set(VALUE left, SLICE* slice, VALUE right) {
|
|
657
657
|
*
|
658
658
|
* TODO: Test the shape of the two matrices.
|
659
659
|
* TODO: See if using memcmp is faster when the left- and right-hand matrices
|
660
|
-
*
|
660
|
+
* have the same dtype.
|
661
661
|
*/
|
662
662
|
bool nm_dense_storage_eqeq(const STORAGE* left, const STORAGE* right) {
|
663
663
|
LR_DTYPE_TEMPLATE_TABLE(nm::dense_storage::eqeq, bool, const DENSE_STORAGE*, const DENSE_STORAGE*)
|
@@ -667,7 +667,7 @@ bool nm_dense_storage_eqeq(const STORAGE* left, const STORAGE* right) {
|
|
667
667
|
return false;
|
668
668
|
}
|
669
669
|
|
670
|
-
|
670
|
+
return ttable[left->dtype][right->dtype]((const DENSE_STORAGE*)left, (const DENSE_STORAGE*)right);
|
671
671
|
}
|
672
672
|
|
673
673
|
/*
|
@@ -675,24 +675,24 @@ bool nm_dense_storage_eqeq(const STORAGE* left, const STORAGE* right) {
|
|
675
675
|
* dtype of Complex64 or Complex128 this is the same as testing for symmetry.
|
676
676
|
*/
|
677
677
|
bool nm_dense_storage_is_hermitian(const DENSE_STORAGE* mat, int lda) {
|
678
|
-
|
679
|
-
|
678
|
+
if (mat->dtype == nm::COMPLEX64) {
|
679
|
+
return nm::dense_storage::is_hermitian<nm::Complex64>(mat, lda);
|
680
680
|
|
681
|
-
|
682
|
-
|
681
|
+
} else if (mat->dtype == nm::COMPLEX128) {
|
682
|
+
return nm::dense_storage::is_hermitian<nm::Complex128>(mat, lda);
|
683
683
|
|
684
|
-
|
685
|
-
|
686
|
-
|
684
|
+
} else {
|
685
|
+
return nm_dense_storage_is_symmetric(mat, lda);
|
686
|
+
}
|
687
687
|
}
|
688
688
|
|
689
689
|
/*
|
690
690
|
* Is this dense matrix symmetric about the diagonal?
|
691
691
|
*/
|
692
692
|
bool nm_dense_storage_is_symmetric(const DENSE_STORAGE* mat, int lda) {
|
693
|
-
|
693
|
+
DTYPE_TEMPLATE_TABLE(nm::dense_storage::is_symmetric, bool, const DENSE_STORAGE*, int);
|
694
694
|
|
695
|
-
|
695
|
+
return ttable[mat->dtype](mat, lda);
|
696
696
|
}
|
697
697
|
|
698
698
|
//////////
|
@@ -798,7 +798,7 @@ DENSE_STORAGE* nm_dense_storage_copy(const DENSE_STORAGE* rhs) {
|
|
798
798
|
count = nm_storage_count_max_elements(lhs);
|
799
799
|
|
800
800
|
|
801
|
-
|
801
|
+
// Ensure that allocation worked before copying.
|
802
802
|
if (lhs && count) {
|
803
803
|
if (rhs == rhs->src) // not a reference
|
804
804
|
memcpy(lhs->elements, rhs->elements, DTYPE_SIZES[rhs->dtype] * count);
|
@@ -941,7 +941,7 @@ DENSE_STORAGE* cast_copy(const DENSE_STORAGE* rhs, dtype_t new_dtype) {
|
|
941
941
|
|
942
942
|
nm_dense_storage_register(lhs);
|
943
943
|
|
944
|
-
|
944
|
+
// Ensure that allocation worked before copying.
|
945
945
|
if (lhs && count) {
|
946
946
|
if (rhs->src != rhs) { // Make a copy of a ref to a matrix.
|
947
947
|
size_t* offset = NM_ALLOCA_N(size_t, rhs->dim);
|
@@ -956,7 +956,7 @@ DENSE_STORAGE* cast_copy(const DENSE_STORAGE* rhs, dtype_t new_dtype) {
|
|
956
956
|
LDType* lhs_els = reinterpret_cast<LDType*>(lhs->elements);
|
957
957
|
|
958
958
|
for (size_t i = 0; i < count; ++i)
|
959
|
-
|
959
|
+
lhs_els[i] = rhs_els[i];
|
960
960
|
}
|
961
961
|
}
|
962
962
|
|
@@ -977,7 +977,7 @@ bool eqeq(const DENSE_STORAGE* left, const DENSE_STORAGE* right) {
|
|
977
977
|
bool result = true;
|
978
978
|
/* FIXME: Very strange behavior! The GC calls the method directly with non-initialized data. */
|
979
979
|
|
980
|
-
LDType* left_elements
|
980
|
+
LDType* left_elements = (LDType*)left->elements;
|
981
981
|
RDType* right_elements = (RDType*)right->elements;
|
982
982
|
|
983
983
|
// Copy elements in temp matrix if you have reference to the right.
|
@@ -1017,39 +1017,39 @@ bool eqeq(const DENSE_STORAGE* left, const DENSE_STORAGE* right) {
|
|
1017
1017
|
|
1018
1018
|
template <typename DType>
|
1019
1019
|
bool is_hermitian(const DENSE_STORAGE* mat, int lda) {
|
1020
|
-
|
1021
|
-
|
1020
|
+
unsigned int i, j;
|
1021
|
+
register DType complex_conj;
|
1022
1022
|
|
1023
|
-
|
1023
|
+
const DType* els = (DType*) mat->elements;
|
1024
1024
|
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1025
|
+
for (i = mat->shape[0]; i-- > 0;) {
|
1026
|
+
for (j = i + 1; j < mat->shape[1]; ++j) {
|
1027
|
+
complex_conj = els[j*lda + i];
|
1028
|
+
complex_conj.i = -complex_conj.i;
|
1029
1029
|
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1030
|
+
if (els[i*lda+j] != complex_conj) {
|
1031
|
+
return false;
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
}
|
1035
1035
|
|
1036
|
-
|
1036
|
+
return true;
|
1037
1037
|
}
|
1038
1038
|
|
1039
1039
|
template <typename DType>
|
1040
1040
|
bool is_symmetric(const DENSE_STORAGE* mat, int lda) {
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1041
|
+
unsigned int i, j;
|
1042
|
+
const DType* els = (DType*) mat->elements;
|
1043
|
+
|
1044
|
+
for (i = mat->shape[0]; i-- > 0;) {
|
1045
|
+
for (j = i + 1; j < mat->shape[1]; ++j) {
|
1046
|
+
if (els[i*lda+j] != els[j*lda+i]) {
|
1047
|
+
return false;
|
1048
|
+
}
|
1049
|
+
}
|
1050
|
+
}
|
1051
|
+
|
1052
|
+
return true;
|
1053
1053
|
}
|
1054
1054
|
|
1055
1055
|
|
@@ -32,7 +32,8 @@
|
|
32
32
|
* Standard Includes
|
33
33
|
*/
|
34
34
|
|
35
|
-
#include <
|
35
|
+
#include <ruby.h>
|
36
|
+
#include <cstdlib>
|
36
37
|
|
37
38
|
/*
|
38
39
|
* Project Includes
|
@@ -69,10 +70,10 @@ extern "C" {
|
|
69
70
|
// Lifecycle //
|
70
71
|
///////////////
|
71
72
|
|
72
|
-
DENSE_STORAGE*
|
73
|
-
void
|
74
|
-
void
|
75
|
-
void
|
73
|
+
DENSE_STORAGE* nm_dense_storage_create(nm::dtype_t dtype, size_t* shape, size_t dim, void* elements, size_t elements_length);
|
74
|
+
void nm_dense_storage_delete(STORAGE* s);
|
75
|
+
void nm_dense_storage_delete_ref(STORAGE* s);
|
76
|
+
void nm_dense_storage_mark(STORAGE*);
|
76
77
|
void nm_dense_storage_register(const STORAGE* s);
|
77
78
|
void nm_dense_storage_unregister(const STORAGE* s);
|
78
79
|
|
@@ -86,8 +87,8 @@ VALUE nm_dense_map_pair(VALUE self, VALUE right);
|
|
86
87
|
VALUE nm_dense_map(VALUE self);
|
87
88
|
VALUE nm_dense_each(VALUE nmatrix);
|
88
89
|
VALUE nm_dense_each_with_indices(VALUE nmatrix);
|
89
|
-
void*
|
90
|
-
void*
|
90
|
+
void* nm_dense_storage_get(const STORAGE* s, SLICE* slice);
|
91
|
+
void* nm_dense_storage_ref(const STORAGE* s, SLICE* slice);
|
91
92
|
void nm_dense_storage_set(VALUE left, SLICE* slice, VALUE right);
|
92
93
|
|
93
94
|
///////////
|
@@ -85,7 +85,7 @@ public:
|
|
85
85
|
actual_shape_ = actual->shape;
|
86
86
|
|
87
87
|
if (init_obj_ == Qnil) {
|
88
|
-
init_obj_ = s->dtype == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(s->default_val) : rubyobj_from_cval(s->default_val, s->dtype).rval;
|
88
|
+
init_obj_ = s->dtype == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(s->default_val) : nm::rubyobj_from_cval(s->default_val, s->dtype).rval;
|
89
89
|
}
|
90
90
|
nm_register_value(&init_obj_);
|
91
91
|
}
|
@@ -181,7 +181,7 @@ static void map_empty_stored_r(RecurseData& result, RecurseData& s, LIST* x, con
|
|
181
181
|
if (!val->first) nm::list::del(val, 0);
|
182
182
|
else {
|
183
183
|
nm_list_storage_register_list(val, rec-1);
|
184
|
-
|
184
|
+
temp_vals.push_front(val);
|
185
185
|
nm::list::insert_helper(x, xcurr, curr->key - offset, val);
|
186
186
|
}
|
187
187
|
curr = curr->next;
|
@@ -193,7 +193,7 @@ static void map_empty_stored_r(RecurseData& result, RecurseData& s, LIST* x, con
|
|
193
193
|
while (curr) {
|
194
194
|
VALUE val, s_val;
|
195
195
|
if (s.dtype() == nm::RUBYOBJ) s_val = (*reinterpret_cast<nm::RubyObject*>(curr->val)).rval;
|
196
|
-
else s_val = rubyobj_from_cval(curr->val, s.dtype()).rval;
|
196
|
+
else s_val = nm::rubyobj_from_cval(curr->val, s.dtype()).rval;
|
197
197
|
|
198
198
|
if (rev) val = rb_yield_values(2, t_init, s_val);
|
199
199
|
else val = rb_yield_values(2, s_val, t_init);
|
@@ -265,7 +265,7 @@ static void map_stored_r(RecurseData& result, RecurseData& left, LIST* x, const
|
|
265
265
|
size_t key;
|
266
266
|
VALUE val;
|
267
267
|
|
268
|
-
val = rb_yield_values(1, left.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(lcurr->val) : rubyobj_from_cval(lcurr->val, left.dtype()).rval);
|
268
|
+
val = rb_yield_values(1, left.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(lcurr->val) : nm::rubyobj_from_cval(lcurr->val, left.dtype()).rval);
|
269
269
|
key = lcurr->key - left.offset(rec);
|
270
270
|
lcurr = lcurr->next;
|
271
271
|
|
@@ -355,15 +355,15 @@ static void map_merged_stored_r(RecurseData& result, RecurseData& left, RecurseD
|
|
355
355
|
VALUE val;
|
356
356
|
|
357
357
|
if (!rcurr || (lcurr && (lcurr->key - left.offset(rec) < rcurr->key - right.offset(rec)))) {
|
358
|
-
val = rb_yield_values(2, rubyobj_from_cval(lcurr->val, left.dtype()).rval, right.init_obj());
|
358
|
+
val = rb_yield_values(2, nm::rubyobj_from_cval(lcurr->val, left.dtype()).rval, right.init_obj());
|
359
359
|
key = lcurr->key - left.offset(rec);
|
360
360
|
lcurr = lcurr->next;
|
361
361
|
} else if (!lcurr || (rcurr && (rcurr->key - right.offset(rec) < lcurr->key - left.offset(rec)))) {
|
362
|
-
|
362
|
+
val = rb_yield_values(2, left.init_obj(), nm::rubyobj_from_cval(rcurr->val, right.dtype()).rval);
|
363
363
|
key = rcurr->key - right.offset(rec);
|
364
364
|
rcurr = rcurr->next;
|
365
365
|
} else { // == and both present
|
366
|
-
val = rb_yield_values(2, rubyobj_from_cval(lcurr->val, left.dtype()).rval, rubyobj_from_cval(rcurr->val, right.dtype()).rval);
|
366
|
+
val = rb_yield_values(2, nm::rubyobj_from_cval(lcurr->val, left.dtype()).rval, nm::rubyobj_from_cval(rcurr->val, right.dtype()).rval);
|
367
367
|
key = lcurr->key - left.offset(rec);
|
368
368
|
lcurr = lcurr->next;
|
369
369
|
rcurr = rcurr->next;
|
@@ -855,7 +855,7 @@ static void each_with_indices_r(nm::list_storage::RecurseData& s, const LIST* l,
|
|
855
855
|
rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(s.init()) : s.init_obj());
|
856
856
|
|
857
857
|
} else { // index == curr->key - offset
|
858
|
-
rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(curr->val) : rubyobj_from_cval(curr->val, s.dtype()).rval);
|
858
|
+
rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(curr->val) : nm::rubyobj_from_cval(curr->val, s.dtype()).rval);
|
859
859
|
|
860
860
|
curr = curr->next;
|
861
861
|
}
|
@@ -902,7 +902,7 @@ static void each_stored_with_indices_r(nm::list_storage::RecurseData& s, const L
|
|
902
902
|
rb_ary_push(stack, LONG2NUM(static_cast<long>(curr->key - offset))); // add index to end
|
903
903
|
|
904
904
|
// add value to beginning
|
905
|
-
rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(curr->val) : rubyobj_from_cval(curr->val, s.dtype()).rval);
|
905
|
+
rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(curr->val) : nm::rubyobj_from_cval(curr->val, s.dtype()).rval);
|
906
906
|
// yield to the whole stack (value, i, j, k, ...)
|
907
907
|
rb_yield_splat(stack);
|
908
908
|
|
@@ -975,7 +975,7 @@ VALUE nm_list_map_stored(VALUE left, VALUE init) {
|
|
975
975
|
init = rb_yield_values(1, sdata.init_obj());
|
976
976
|
nm_register_value(&init);
|
977
977
|
}
|
978
|
-
|
978
|
+
// Allocate a new shape array for the resulting matrix.
|
979
979
|
void* init_val = NM_ALLOC(VALUE);
|
980
980
|
memcpy(init_val, &init, sizeof(VALUE));
|
981
981
|
nm_register_value(&*reinterpret_cast<VALUE*>(init_val));
|
@@ -1316,12 +1316,12 @@ void nm_list_storage_remove(STORAGE* storage, SLICE* slice) {
|
|
1316
1316
|
* Comparison of contents for list storage.
|
1317
1317
|
*/
|
1318
1318
|
bool nm_list_storage_eqeq(const STORAGE* left, const STORAGE* right) {
|
1319
|
-
|
1319
|
+
NAMED_LR_DTYPE_TEMPLATE_TABLE(ttable, nm::list_storage::eqeq_r, bool, nm::list_storage::RecurseData& left, nm::list_storage::RecurseData& right, const LIST* l, const LIST* r, size_t rec)
|
1320
1320
|
|
1321
1321
|
nm::list_storage::RecurseData ldata(reinterpret_cast<const LIST_STORAGE*>(left)),
|
1322
1322
|
rdata(reinterpret_cast<const LIST_STORAGE*>(right));
|
1323
1323
|
|
1324
|
-
|
1324
|
+
return ttable[left->dtype][right->dtype](ldata, rdata, ldata.top_level_list(), rdata.top_level_list(), ldata.dim()-1);
|
1325
1325
|
}
|
1326
1326
|
|
1327
1327
|
//////////
|
@@ -1349,7 +1349,7 @@ STORAGE* nm_list_storage_matrix_multiply(const STORAGE_PAIR& casted_storage, siz
|
|
1349
1349
|
VALUE nm_list_storage_to_hash(const LIST_STORAGE* s, const nm::dtype_t dtype) {
|
1350
1350
|
nm_list_storage_register(s);
|
1351
1351
|
// Get the default value for the list storage.
|
1352
|
-
VALUE default_value = rubyobj_from_cval(s->default_val, dtype).rval;
|
1352
|
+
VALUE default_value = nm::rubyobj_from_cval(s->default_val, dtype).rval;
|
1353
1353
|
nm_list_storage_unregister(s);
|
1354
1354
|
// Recursively copy each dimension of the matrix into a nested hash.
|
1355
1355
|
return nm_list_copy_to_hash(s->rows, dtype, s->dim - 1, default_value);
|
@@ -1390,7 +1390,7 @@ size_t nm_list_storage_count_nd_elements(const LIST_STORAGE* s) {
|
|
1390
1390
|
size_t count = 0;
|
1391
1391
|
|
1392
1392
|
if (s->dim != 2) {
|
1393
|
-
|
1393
|
+
rb_raise(rb_eNotImpError, "non-diagonal element counting only defined for dim = 2");
|
1394
1394
|
}
|
1395
1395
|
|
1396
1396
|
for (i_curr = s->rows->first; i_curr; i_curr = i_curr->next) {
|
@@ -1401,7 +1401,7 @@ size_t nm_list_storage_count_nd_elements(const LIST_STORAGE* s) {
|
|
1401
1401
|
int j = j_curr->key - s->offset[1];
|
1402
1402
|
if (j < 0 || j >= (int)s->shape[1]) continue;
|
1403
1403
|
|
1404
|
-
if (i != j)
|
1404
|
+
if (i != j) ++count;
|
1405
1405
|
}
|
1406
1406
|
}
|
1407
1407
|
|
@@ -1621,7 +1621,7 @@ extern "C" {
|
|
1621
1621
|
*/
|
1622
1622
|
VALUE nm_list_default_value(VALUE self) {
|
1623
1623
|
NM_CONSERVATIVE(nm_register_value(&self));
|
1624
|
-
VALUE to_return = (NM_DTYPE(self) == nm::RUBYOBJ) ? *reinterpret_cast<VALUE*>(NM_DEFAULT_VAL(self)) : rubyobj_from_cval(NM_DEFAULT_VAL(self), NM_DTYPE(self)).rval;
|
1624
|
+
VALUE to_return = (NM_DTYPE(self) == nm::RUBYOBJ) ? *reinterpret_cast<VALUE*>(NM_DEFAULT_VAL(self)) : nm::rubyobj_from_cval(NM_DEFAULT_VAL(self), NM_DTYPE(self)).rval;
|
1625
1625
|
NM_CONSERVATIVE(nm_unregister_value(&self));
|
1626
1626
|
return to_return;
|
1627
1627
|
}
|
@@ -33,7 +33,8 @@
|
|
33
33
|
* Standard Includes
|
34
34
|
*/
|
35
35
|
|
36
|
-
#include <
|
36
|
+
#include <ruby.h>
|
37
|
+
#include <cstdlib>
|
37
38
|
#include <list>
|
38
39
|
/*
|
39
40
|
* Project Includes
|
@@ -69,17 +70,17 @@ extern "C" {
|
|
69
70
|
// Lifecycle //
|
70
71
|
///////////////
|
71
72
|
|
72
|
-
LIST_STORAGE*
|
73
|
-
void
|
74
|
-
void
|
75
|
-
void
|
73
|
+
LIST_STORAGE* nm_list_storage_create(nm::dtype_t dtype, size_t* shape, size_t dim, void* init_val);
|
74
|
+
void nm_list_storage_delete(STORAGE* s);
|
75
|
+
void nm_list_storage_delete_ref(STORAGE* s);
|
76
|
+
void nm_list_storage_mark(STORAGE*);
|
76
77
|
void nm_list_storage_register(const STORAGE* s);
|
77
78
|
void nm_list_storage_unregister(const STORAGE* s);
|
78
79
|
void nm_list_storage_register_list(const LIST* l, size_t recursions);
|
79
80
|
void nm_list_storage_unregister_list(const LIST* l, size_t recursions);
|
80
81
|
void nm_list_storage_register_node(const NODE* n);
|
81
82
|
void nm_list_storage_unregister_node(const NODE* n);
|
82
|
-
void
|
83
|
+
void nm_list_storage_completely_unregister_node(const NODE* curr);
|
83
84
|
///////////////
|
84
85
|
// Accessors //
|
85
86
|
///////////////
|
@@ -50,9 +50,9 @@
|
|
50
50
|
extern "C" {
|
51
51
|
|
52
52
|
const char* const STYPE_NAMES[nm::NUM_STYPES] = {
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
"dense",
|
54
|
+
"list",
|
55
|
+
"yale"
|
56
56
|
};
|
57
57
|
|
58
58
|
} // end extern "C" block
|
@@ -152,14 +152,14 @@ DENSE_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype
|
|
152
152
|
|
153
153
|
if (rhs_ija[ri] == rhs_ija[ri+1]) { // Check boundaries of row: is row empty? (Yes.)
|
154
154
|
|
155
|
-
|
156
|
-
|
155
|
+
// Write zeros in each column.
|
156
|
+
for (size_t j = 0; j < shape[1]; ++j) { // Move to next dense position.
|
157
157
|
|
158
158
|
// Fill in zeros and copy the diagonal entry for this empty row.
|
159
159
|
if (ri == j + rhs->offset[1]) lhs_elements[pos] = static_cast<LDType>(rhs_a[ri]);
|
160
|
-
|
160
|
+
else lhs_elements[pos] = LCAST_ZERO;
|
161
161
|
|
162
|
-
|
162
|
+
++pos;
|
163
163
|
}
|
164
164
|
|
165
165
|
} else { // Row contains entries: write those in each column, interspersed with zeros.
|
@@ -170,8 +170,8 @@ DENSE_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype
|
|
170
170
|
// What column is it?
|
171
171
|
IType next_stored_rj = rhs_ija[ija];
|
172
172
|
|
173
|
-
|
174
|
-
|
173
|
+
for (size_t j = 0; j < shape[1]; ++j) {
|
174
|
+
IType rj = j + rhs->offset[1];
|
175
175
|
|
176
176
|
if (rj == ri) { // at a diagonal in RHS
|
177
177
|
lhs_elements[pos] = static_cast<LDType>(rhs_a[ri]);
|
@@ -184,7 +184,7 @@ DENSE_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype
|
|
184
184
|
|
185
185
|
// Increment to next column ID (or go off the end).
|
186
186
|
if (ija < rhs_ija[ri+1]) next_stored_rj = rhs_ija[ija];
|
187
|
-
else
|
187
|
+
else next_stored_rj = rhs->src->shape[1];
|
188
188
|
|
189
189
|
} else { // rj < next_stored_rj
|
190
190
|
|
@@ -219,14 +219,14 @@ static void cast_copy_list_contents(LDType* lhs, const LIST* rhs, RDType* defaul
|
|
219
219
|
if (!curr || (curr->key > (size_t)(last_key+1))) {
|
220
220
|
|
221
221
|
if (recursions == 0) lhs[pos] = static_cast<LDType>(*default_val);
|
222
|
-
else
|
222
|
+
else cast_copy_list_default<LDType,RDType>(lhs, default_val, pos, shape, dim, max_elements, recursions-1);
|
223
223
|
|
224
224
|
++last_key;
|
225
225
|
|
226
226
|
} else {
|
227
227
|
|
228
228
|
if (recursions == 0) lhs[pos] = static_cast<LDType>(*reinterpret_cast<RDType*>(curr->val));
|
229
|
-
else
|
229
|
+
else cast_copy_list_contents<LDType,RDType>(lhs, (const LIST*)(curr->val),
|
230
230
|
default_val, pos, shape, dim, max_elements, recursions-1);
|
231
231
|
|
232
232
|
last_key = curr->key;
|
@@ -247,7 +247,7 @@ static void cast_copy_list_default(LDType* lhs, RDType* default_val, size_t& pos
|
|
247
247
|
for (size_t i = 0; i < shape[dim - 1 - recursions]; ++i, ++pos) {
|
248
248
|
|
249
249
|
if (recursions == 0) lhs[pos] = static_cast<LDType>(*default_val);
|
250
|
-
else
|
250
|
+
else cast_copy_list_default<LDType,RDType>(lhs, default_val, pos, shape, dim, max_elements, recursions-1);
|
251
251
|
|
252
252
|
}
|
253
253
|
|
@@ -283,13 +283,13 @@ LIST_STORAGE* create_from_dense_storage(const DENSE_STORAGE* rhs, dtype_t l_dtyp
|
|
283
283
|
// set list default_val to 0
|
284
284
|
if (init) *l_default_val = *reinterpret_cast<LDType*>(init);
|
285
285
|
else {
|
286
|
-
if (l_dtype == RUBYOBJ)
|
287
|
-
else
|
286
|
+
if (l_dtype == RUBYOBJ) *l_default_val = INT2FIX(0);
|
287
|
+
else *l_default_val = 0;
|
288
288
|
}
|
289
289
|
|
290
290
|
// need test default value for comparing to elements in dense matrix
|
291
291
|
if (rhs->dtype == l_dtype || rhs->dtype != RUBYOBJ) *r_default_val = static_cast<RDType>(*l_default_val);
|
292
|
-
else *r_default_val = rubyobj_from_cval(l_default_val, l_dtype);
|
292
|
+
else *r_default_val = nm::rubyobj_from_cval(l_default_val, l_dtype);
|
293
293
|
|
294
294
|
|
295
295
|
LIST_STORAGE* lhs = nm_list_storage_create(l_dtype, shape, rhs->dim, l_default_val);
|
@@ -382,10 +382,10 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
382
382
|
// What is the appropriate key? Well, it's definitely right(i)==right(j), but the
|
383
383
|
// rj index has already been advanced past ri. So we should treat ri as the column and
|
384
384
|
// subtract offset[1].
|
385
|
-
if (last_added)
|
386
|
-
else
|
385
|
+
if (last_added) last_added = list::insert_after(last_added, ri - rhs->offset[1], insert_val);
|
386
|
+
else last_added = list::insert(curr_row, false, ri - rhs->offset[1], insert_val);
|
387
387
|
|
388
|
-
|
388
|
+
// don't add again!
|
389
389
|
add_diag = false;
|
390
390
|
}
|
391
391
|
|
@@ -393,21 +393,21 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
393
393
|
insert_val = NM_ALLOC_N(LDType, 1);
|
394
394
|
*insert_val = static_cast<LDType>(rhs_a[ija]);
|
395
395
|
|
396
|
-
if (last_added)
|
397
|
-
else
|
396
|
+
if (last_added) last_added = list::insert_after(last_added, j, insert_val);
|
397
|
+
else last_added = list::insert(curr_row, false, j, insert_val);
|
398
398
|
|
399
399
|
++ija; // move to next entry in Yale matrix
|
400
400
|
}
|
401
401
|
|
402
402
|
if (add_diag) {
|
403
403
|
|
404
|
-
|
404
|
+
// still haven't added the diagonal.
|
405
405
|
insert_val = NM_ALLOC_N(LDType, 1);
|
406
406
|
*insert_val = static_cast<LDType>(rhs_a[ri]);
|
407
407
|
|
408
408
|
// insert the item in the list at the appropriate location
|
409
|
-
if (last_added)
|
410
|
-
else
|
409
|
+
if (last_added) last_added = list::insert_after(last_added, ri - rhs->offset[1], insert_val);
|
410
|
+
else last_added = list::insert(curr_row, false, ri - rhs->offset[1], insert_val);
|
411
411
|
|
412
412
|
// no need to set add_diag to false because it'll be reset automatically in next iteration.
|
413
413
|
}
|
@@ -417,7 +417,7 @@ LIST_STORAGE* create_from_yale_storage(const YALE_STORAGE* rhs, dtype_t l_dtype)
|
|
417
417
|
else last_row_added = list::insert(lhs->rows, false, i, curr_row);
|
418
418
|
}
|
419
419
|
|
420
|
-
|
420
|
+
// end of walk through rows
|
421
421
|
}
|
422
422
|
|
423
423
|
nm_yale_storage_unregister(rhs);
|
@@ -443,17 +443,17 @@ static bool cast_copy_contents_dense(LIST* lhs, const RDType* rhs, RDType* zero,
|
|
443
443
|
for (coords[dim-1-recursions] = 0; coords[dim-1-recursions] < shape[dim-1-recursions]; ++coords[dim-1-recursions], ++pos) {
|
444
444
|
|
445
445
|
if (recursions == 0) {
|
446
|
-
|
446
|
+
// create nodes
|
447
447
|
|
448
448
|
if (rhs[pos] != *zero) {
|
449
|
-
|
449
|
+
// is not zero
|
450
450
|
|
451
451
|
// Create a copy of our value that we will insert in the list
|
452
452
|
LDType* insert_value = NM_ALLOC_N(LDType, 1);
|
453
453
|
*insert_value = static_cast<LDType>(rhs[pos]);
|
454
454
|
|
455
455
|
if (!lhs->first) prev = list::insert(lhs, false, coords[dim-1-recursions], insert_value);
|
456
|
-
else
|
456
|
+
else prev = list::insert_after(prev, coords[dim-1-recursions], insert_value);
|
457
457
|
|
458
458
|
added = true;
|
459
459
|
}
|
@@ -465,9 +465,9 @@ static bool cast_copy_contents_dense(LIST* lhs, const RDType* rhs, RDType* zero,
|
|
465
465
|
|
466
466
|
added_list = list_storage::cast_copy_contents_dense<LDType,RDType>(sub_list, rhs, zero, pos, coords, shape, dim, recursions-1);
|
467
467
|
|
468
|
-
if (!added_list)
|
469
|
-
else if (!lhs->first)
|
470
|
-
else
|
468
|
+
if (!added_list) list::del(sub_list, recursions-1);
|
469
|
+
else if (!lhs->first) prev = list::insert(lhs, false, coords[dim-1-recursions], sub_list);
|
470
|
+
else prev = list::insert_after(prev, coords[dim-1-recursions], sub_list);
|
471
471
|
|
472
472
|
// added = (added || added_list);
|
473
473
|
}
|
@@ -512,7 +512,7 @@ namespace yale_storage { // FIXME: Move to yale.cpp
|
|
512
512
|
for (size_t i = rhs->shape[0]; i-- > 0;) {
|
513
513
|
for (size_t j = rhs->shape[1]; j-- > 0;) {
|
514
514
|
pos = rhs->stride[0]*(i + rhs->offset[0]) + rhs->stride[1]*(j + rhs->offset[1]);
|
515
|
-
if (i != j && rhs_elements[pos] != R_INIT)
|
515
|
+
if (i != j && rhs_elements[pos] != R_INIT) ++ndnz;
|
516
516
|
|
517
517
|
// move forward 1 position in dense matrix elements array
|
518
518
|
}
|