module NMatrix::YaleFunctions
This module stores methods that are useful for debugging Yale matrices,
i.e. the ones with :yale
stype.
Constants
- YALE_GROWTH_CONSTANT
Defines the growth rate of the sparse NMatrix's size. Default is 1.5.
Public Instance Methods
Get the A array of a Yale matrix (which stores the diagonal and the LU portions of the matrix).
static VALUE nm_a(int argc, VALUE* argv, VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); VALUE idx; rb_scan_args(argc, argv, "01", &idx); NM_CONSERVATIVE(nm_register_value(&idx)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); size_t size = nm_yale_storage_get_size(s); if (idx == Qnil) { VALUE* vals = NM_ALLOCA_N(VALUE, size); nm_register_values(vals, size); if (NM_DTYPE(self) == nm::RUBYOBJ) { for (size_t i = 0; i < size; ++i) { vals[i] = reinterpret_cast<VALUE*>(s->a)[i]; } } else { for (size_t i = 0; i < size; ++i) { vals[i] = rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype]*i, s->dtype).rval; } } VALUE ary = rb_ary_new4(size, vals); for (size_t i = size; i < s->capacity; ++i) rb_ary_push(ary, Qnil); nm_unregister_values(vals, size); NM_CONSERVATIVE(nm_unregister_value(&idx)); NM_CONSERVATIVE(nm_unregister_value(&self)); return ary; } else { size_t index = FIX2INT(idx); NM_CONSERVATIVE(nm_unregister_value(&idx)); NM_CONSERVATIVE(nm_unregister_value(&self)); if (index >= size) rb_raise(rb_eRangeError, "out of range"); return rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype] * index, s->dtype).rval; } }
Get the diagonal (“D”) portion of the A array of a Yale matrix.
static VALUE nm_d(int argc, VALUE* argv, VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); VALUE idx; rb_scan_args(argc, argv, "01", &idx); NM_CONSERVATIVE(nm_register_value(&idx)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); if (idx == Qnil) { VALUE* vals = NM_ALLOCA_N(VALUE, s->shape[0]); nm_register_values(vals, s->shape[0]); if (NM_DTYPE(self) == nm::RUBYOBJ) { for (size_t i = 0; i < s->shape[0]; ++i) { vals[i] = reinterpret_cast<VALUE*>(s->a)[i]; } } else { for (size_t i = 0; i < s->shape[0]; ++i) { vals[i] = rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype]*i, s->dtype).rval; } } nm_unregister_values(vals, s->shape[0]); NM_CONSERVATIVE(nm_unregister_value(&idx)); NM_CONSERVATIVE(nm_unregister_value(&self)); return rb_ary_new4(s->shape[0], vals); } else { size_t index = FIX2INT(idx); NM_CONSERVATIVE(nm_unregister_value(&idx)); NM_CONSERVATIVE(nm_unregister_value(&self)); if (index >= s->shape[0]) rb_raise(rb_eRangeError, "out of range"); return rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype] * index, s->dtype).rval; } }
Get the IA portion of the IJA array of a Yale matrix. This gives the start and end positions of rows in the JA and LU portions of the IJA and A arrays, respectively.
static VALUE nm_ia(VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); VALUE* vals = NM_ALLOCA_N(VALUE, s->shape[0] + 1); for (size_t i = 0; i < s->shape[0] + 1; ++i) { vals[i] = INT2FIX(s->ija[i]); } NM_CONSERVATIVE(nm_unregister_value(&self)); return rb_ary_new4(s->shape[0]+1, vals); }
Get the IJA array of a Yale matrix (or a component of the IJA array).
static VALUE nm_ija(int argc, VALUE* argv, VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); VALUE idx; rb_scan_args(argc, argv, "01", &idx); NM_CONSERVATIVE(nm_register_value(&idx)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); size_t size = nm_yale_storage_get_size(s); if (idx == Qnil) { VALUE* vals = NM_ALLOCA_N(VALUE, size); nm_register_values(vals, size); for (size_t i = 0; i < size; ++i) { vals[i] = INT2FIX(s->ija[i]); } VALUE ary = rb_ary_new4(size, vals); for (size_t i = size; i < s->capacity; ++i) rb_ary_push(ary, Qnil); nm_unregister_values(vals, size); NM_CONSERVATIVE(nm_unregister_value(&idx)); NM_CONSERVATIVE(nm_unregister_value(&self)); return ary; } else { size_t index = FIX2INT(idx); if (index >= size) rb_raise(rb_eRangeError, "out of range"); NM_CONSERVATIVE(nm_unregister_value(&self)); NM_CONSERVATIVE(nm_unregister_value(&idx)); return INT2FIX(s->ija[index]); } }
Get the JA portion of the IJA array of a Yale matrix. This gives the column indices for entries in corresponding positions in the LU portion of the A array.
static VALUE nm_ja(VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); size_t size = nm_yale_storage_get_size(s); VALUE* vals = NM_ALLOCA_N(VALUE, size - s->shape[0] - 1); nm_register_values(vals, size - s->shape[0] - 1); for (size_t i = 0; i < size - s->shape[0] - 1; ++i) { vals[i] = INT2FIX(s->ija[s->shape[0] + 1 + i]); } VALUE ary = rb_ary_new4(size - s->shape[0] - 1, vals); for (size_t i = size; i < s->capacity; ++i) rb_ary_push(ary, Qnil); nm_unregister_values(vals, size - s->shape[0] - 1); NM_CONSERVATIVE(nm_unregister_value(&self)); return ary; }
Returns the non-diagonal column indices which are stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 45 def yale_ja_at i yale_nd_row(i, :keys) end
Returns the diagonal and non-digonal column indices stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 82 def yale_ja_d_keys_at i ary = yale_nd_row(i, :keys) return ary if i >= self.shape[1] || self[i,i] == self.default_value ary << i end
Returns the diagonal and non-diagonal column indices stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 93 def yale_ja_d_keys_set_at i require 'set' yale_ja_d_keys_at(i).to_set end
Returns the diagonal and non-diagonal column indices stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 103 def yale_ja_d_keys_sorted_set_at i require 'set' SortedSet.new(yale_row_as_array(i)) end
Returns the non-diagonal column indices which are stored in a given row, as a Set.
# File lib/nmatrix/yale_functions.rb, line 54 def yale_ja_set_at i require 'set' yale_nd_row(i, :keys).to_set end
Returns the non-diagonal column indices which are stored in a given row, as a Set.
# File lib/nmatrix/yale_functions.rb, line 64 def yale_ja_sorted_set_at i require 'set' SortedSet.new(yale_nd_row(i, :keys)) end
Get the non-diagonal (“LU”) portion of the A array of a Yale matrix.
static VALUE nm_lu(VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); YALE_STORAGE* s = reinterpret_cast<YALE_STORAGE*>(NM_SRC(self)); size_t size = nm_yale_storage_get_size(s); VALUE* vals = NM_ALLOCA_N(VALUE, size - s->shape[0] - 1); nm_register_values(vals, size - s->shape[0] - 1); if (NM_DTYPE(self) == nm::RUBYOBJ) { for (size_t i = 0; i < size - s->shape[0] - 1; ++i) { vals[i] = reinterpret_cast<VALUE*>(s->a)[s->shape[0] + 1 + i]; } } else { for (size_t i = 0; i < size - s->shape[0] - 1; ++i) { vals[i] = rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype]*(s->shape[0] + 1 + i), s->dtype).rval; } } VALUE ary = rb_ary_new4(size - s->shape[0] - 1, vals); for (size_t i = size; i < s->capacity; ++i) rb_ary_push(ary, Qnil); nm_unregister_values(vals, size - s->shape[0] - 1); NM_CONSERVATIVE(nm_unregister_value(&self)); return ary; }
This function gets the non-diagonal contents of a Yale matrix row. The first argument should be the row index. The optional second argument may be :hash or :keys, but defaults to :hash. If :keys is given, it will only return the Hash keys (the column indices).
This function is meant to accomplish its purpose as efficiently as possible. It does not check for appropriate range.
static VALUE nm_nd_row(int argc, VALUE* argv, VALUE self) { NM_CONSERVATIVE(nm_register_value(&self)); if (NM_SRC(self) != NM_STORAGE(self)) { NM_CONSERVATIVE(nm_unregister_value(&self)); rb_raise(rb_eNotImpError, "must be called on a real matrix and not a slice"); } VALUE i_, as; rb_scan_args(argc, argv, "11", &i_, &as); NM_CONSERVATIVE(nm_register_value(&as)); NM_CONSERVATIVE(nm_register_value(&i_)); bool keys = false; if (as != Qnil && rb_to_id(as) != nm_rb_hash) keys = true; size_t i = FIX2INT(i_); YALE_STORAGE* s = NM_STORAGE_YALE(self); //nm::dtype_t dtype = NM_DTYPE(self); if (i >= s->shape[0]) { NM_CONSERVATIVE(nm_unregister_value(&self)); NM_CONSERVATIVE(nm_unregister_value(&as)); NM_CONSERVATIVE(nm_unregister_value(&i_)); rb_raise(rb_eRangeError, "out of range (%lu >= %lu)", i, s->shape[0]); } size_t pos = s->ija[i]; size_t nextpos = s->ija[i+1]; size_t diff = nextpos - pos; VALUE ret; if (keys) { ret = rb_ary_new3(diff); for (size_t idx = pos; idx < nextpos; ++idx) { rb_ary_store(ret, idx - pos, INT2FIX(s->ija[idx])); } } else { ret = rb_hash_new(); for (size_t idx = pos; idx < nextpos; ++idx) { rb_hash_aset(ret, INT2FIX(s->ija[idx]), rubyobj_from_cval((char*)(s->a) + DTYPE_SIZES[s->dtype]*idx, s->dtype).rval); } } NM_CONSERVATIVE(nm_unregister_value(&as)); NM_CONSERVATIVE(nm_unregister_value(&i_)); NM_CONSERVATIVE(nm_unregister_value(&self)); return ret; }
Returns the non-diagonal column indices and entries stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 74 def yale_nd_row_as_hash i yale_nd_row(i, :hash) end
Returns the size of a given non-diagonal row.
# File lib/nmatrix/yale_functions.rb, line 37 def yale_nd_row_size i yale_ija(i+1) - yale_ija(i) end
Returns the diagonal and non-diagonal column indices and entries stored in a given row.
# File lib/nmatrix/yale_functions.rb, line 113 def yale_row_as_hash i h = yale_nd_row(i, :hash) return h if i >= self.shape[1] || self[i,i] == self.default_value h[i] = self[i,i] end
This function is experimental.
It finds the intersection of row i of the current matrix with row i2 of matrix m2. Both matrices must be Yale. They may not be slices.
Only checks the stored indices; does not care about matrix default value.
static VALUE nm_row_keys_intersection(VALUE m1, VALUE ii1, VALUE m2, VALUE ii2) { NM_CONSERVATIVE(nm_register_value(&m1)); NM_CONSERVATIVE(nm_register_value(&m2)); if (NM_SRC(m1) != NM_STORAGE(m1) || NM_SRC(m2) != NM_STORAGE(m2)) { NM_CONSERVATIVE(nm_unregister_value(&m2)); NM_CONSERVATIVE(nm_unregister_value(&m1)); rb_raise(rb_eNotImpError, "must be called on a real matrix and not a slice"); } size_t i1 = FIX2INT(ii1), i2 = FIX2INT(ii2); YALE_STORAGE *s = NM_STORAGE_YALE(m1), *t = NM_STORAGE_YALE(m2); size_t pos1 = s->ija[i1], pos2 = t->ija[i2]; size_t nextpos1 = s->ija[i1+1], nextpos2 = t->ija[i2+1]; size_t diff1 = nextpos1 - pos1, diff2 = nextpos2 - pos2; // Does the diagonal have a nonzero in it? bool diag1 = i1 < s->shape[0] && !is_pos_default_value(s, i1), diag2 = i2 < t->shape[0] && !is_pos_default_value(t, i2); // Reserve max(diff1,diff2) space -- that's the max intersection possible. VALUE ret = rb_ary_new2(std::max(diff1,diff2)+1); nm_register_value(&ret); // Handle once the special case where both have the diagonal in exactly // the same place. if (diag1 && diag2 && i1 == i2) { rb_ary_push(ret, INT2FIX(i1)); diag1 = false; diag2 = false; // no need to deal with diagonals anymore. } // Now find the intersection. size_t idx1 = pos1, idx2 = pos2; while (idx1 < nextpos1 && idx2 < nextpos2) { if (s->ija[idx1] == t->ija[idx2]) { rb_ary_push(ret, INT2FIX(s->ija[idx1])); ++idx1; ++idx2; } else if (diag1 && i1 == t->ija[idx2]) { rb_ary_push(ret, INT2FIX(i1)); diag1 = false; ++idx2; } else if (diag2 && i2 == s->ija[idx1]) { rb_ary_push(ret, INT2FIX(i2)); diag2 = false; ++idx1; } else if (s->ija[idx1] < t->ija[idx2]) { ++idx1; } else { // s->ija[idx1] > t->ija[idx2] ++idx2; } } // Past the end of row i2's stored entries; need to try to find diagonal if (diag2 && idx1 < nextpos1) { idx1 = nm::yale_storage::binary_search_left_boundary(s, idx1, nextpos1, i2); if (s->ija[idx1] == i2) rb_ary_push(ret, INT2FIX(i2)); } // Find the diagonal, if possible, in the other one. if (diag1 && idx2 < nextpos2) { idx2 = nm::yale_storage::binary_search_left_boundary(t, idx2, nextpos2, i1); if (t->ija[idx2] == i1) rb_ary_push(ret, INT2FIX(i1)); } nm_unregister_value(&ret); NM_CONSERVATIVE(nm_unregister_value(&m1)); NM_CONSERVATIVE(nm_unregister_value(&m2)); return ret; }
Get the size of a Yale matrix (the number of elements actually stored).
For capacity (the maximum number of elements that can be stored without a resize), use capacity instead.
static VALUE nm_size(VALUE self) { YALE_STORAGE* s = (YALE_STORAGE*)(NM_SRC(self)); VALUE to_return = INT2FIX(nm::yale_storage::IJA(s)[s->shape[0]]); return to_return; }