nmatrix 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|