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

yale_a → Array click to toggle source
yale_d(index) → ...

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;
  }
}
yale_d → Array click to toggle source
yale_d(index) → ...

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;
  }
}
yale_ia → Array click to toggle source

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);
}
yale_ija → Array click to toggle source
yale_ija(index) → ...

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]);
  }
}
yale_ja → Array click to toggle source

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;
}
yale_ja_at(i) → Array click to toggle source

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
Also aliased as: yale_nd_row_as_array
yale_ja_d_keys_at(i) → Array click to toggle source

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
Also aliased as: yale_row_as_array
yale_ja_d_keys_set_at(i) → Set click to toggle source

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
Also aliased as: yale_row_as_set
yale_ja_d_keys_sorted_set_at(i) → SortedSet click to toggle source

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
Also aliased as: yale_row_as_sorted_set
yale_ja_set_at(i) → Set click to toggle source

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
Also aliased as: yale_nd_row_as_set
yale_ja_sorted_set_at → SortedSet click to toggle source

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
Also aliased as: yale_nd_row_as_sorted_set
yale_lu → Array click to toggle source

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;
}
yale_nd_row → ... click to toggle source

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;
}
yale_nd_row_as_array(i)
Alias for: yale_ja_at
yale_nd_row_as_hash(i) → Hash click to toggle source

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
yale_nd_row_as_set(i)
Alias for: yale_ja_set_at
yale_nd_row_as_sorted_set(i)
yale_nd_row_size(i) → Fixnum click to toggle source

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
yale_row_as_array(i)
Alias for: yale_ja_d_keys_at
yale_row_as_hash(i) → Hash click to toggle source

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
yale_row_as_set(i)
yale_row_as_sorted_set(i)
yale_row_keys_intersection(i, m2, i2) → Array click to toggle source

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;
}
yale_size → Integer click to toggle source

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;
}