const Sparse<T> operator-(const Sparse<T> &s) { Vector<T> data(s.priv_data().size()); std::transform(s.priv_data().begin(), s.priv_data().end(), data.begin(), std::negate<T>()); return Sparse<T>(s.dimensions(), s.priv_row_start(), s.priv_column(), data); }
const Sparse<T> operator/(const Sparse<T> &s, T b) { Vector<T> data(s.priv_data().size()); std::transform(s.priv_data().begin(), s.priv_data().end(), data.begin(), divided_constant<T,T>(b)); return Sparse<T>(s.dimensions(), s.priv_row_start(), s.priv_column(), data); }
static const Sparse<elt_t> do_kron(const Sparse<elt_t> &s2, const Sparse<elt_t> &s1) { index rows1 = s1.rows(); index cols1 = s1.columns(); index rows2 = s2.rows(); index cols2 = s2.columns(); index number_nonzero = s1.length() * s2.length(); index total_rows = rows1 * rows2; index total_cols = cols1 * cols2; if (number_nonzero == 0) return Sparse<elt_t>(total_rows, total_cols); Tensor<elt_t> output_data(number_nonzero); Indices output_column(number_nonzero); Indices output_row_start(total_rows+1); Indices output_dims(igen << total_rows << total_cols); typename Tensor<elt_t>::iterator out_data = output_data.begin(); typename Indices::iterator out_column = output_column.begin(); typename Indices::iterator out_begin = out_column; typename Indices::iterator out_row_start = output_row_start.begin(); // C([i,j],[k,l]) = s1(i,k) s2(j,l) *(out_row_start++) = 0; for (index l = 0; l < rows2; l++) { for (index k = 0; k < rows1; k++) { for (index j = s2.priv_row_start()[l]; j < s2.priv_row_start()[l+1]; j++) { for (index i = s1.priv_row_start()[k]; i < s1.priv_row_start()[k+1]; i++) { *(out_data++) = s1.priv_data()[i] * s2.priv_data()[j]; *(out_column++) = s1.priv_column()[i] + cols1 * s2.priv_column()[j]; } } *(out_row_start++) = out_column - out_begin; } } return Sparse<elt_t>(output_dims, output_row_start, output_column, output_data); }
const Sparse<T> sparse_binop(const Sparse<T> &m1, const Sparse<T> &m2, binop op) { size_t rows = m1.rows(); size_t cols = m1.columns(); assert(rows == m2.rows() && cols == m2.columns()); if (rows == 0 || cols == 0) return m1; index max_size = m1.priv_data().size() + m2.priv_data().size(); Vector<T> data(max_size); Indices column(max_size); Indices row_start(rows + 1); typename Vector<T>::iterator out_data = data.begin(); typename Indices::iterator out_column = column.begin(); typename Indices::iterator out_row_start = row_start.begin(); typename Vector<T>::iterator out_begin = out_data; typename Vector<T>::const_iterator m1_data = m1.priv_data().begin(); typename Indices::const_iterator m1_row_start = m1.priv_row_start().begin(); typename Indices::const_iterator m1_column = m1.priv_column().begin(); typename Vector<T>::const_iterator m2_data = m2.priv_data().begin(); typename Indices::const_iterator m2_row_start = m2.priv_row_start().begin(); typename Indices::const_iterator m2_column = m2.priv_column().begin(); index j1 = *(m1_row_start++); // data start for this row in M1 index l1 = (*m1_row_start) - j1; // # elements in this row in M1 index j2 = *(m2_row_start++); // data start for this row in M2 index l2 = (*m2_row_start) - j2; // # elements in this row in M2 *out_row_start = 0; while (1) { // We look for the next unprocessed matrix element on this row, // for both matrices. c1 and c2 are the columns associated to // each element on each matrix. index c1 = l1 ? *m1_column : cols; index c2 = l2 ? *m2_column : cols; T value; index c; if (c1 < c2) { // There is an element a column c1 on matrix m1, but the // same element at m2 is zero value = op(*m1_data, number_zero<T>()); c = c1; l1--; m1_column++; m1_data++; } else if (c2 < c1) { // There is an element a column c2 on matrix m2, but the // same element at m1 is zero value = op(number_zero<T>(), *m2_data); c = c2; l2--; m2_column++; m2_data++; } else if (c2 < cols) { // Both elements in m1 and m2 are nonzero. value = op(*m1_data, *m2_data); c = c1; l1--; l2--; m1_column++; m1_data++; m2_column++; m2_data++; } else { // We have processed all elements in this row. out_row_start++; *out_row_start = out_data - out_begin; if (--rows == 0) { break; } j1 = *m1_row_start; m1_row_start++; l1 = (*m1_row_start) - j1; j2 = *m2_row_start; m2_row_start++; l2 = (*m2_row_start) - j2; continue; } if (!(value == number_zero<T>())) { *(out_data++) = value; *(out_column++) = c; } } index j = out_data - out_begin; Indices the_column(j); std::copy(column.begin(), column.begin() + j, the_column.begin()); Vector<T> the_data(j); std::copy(data.begin(), data.begin() + j, the_data.begin()); return Sparse<T>(m1.dimensions(), row_start, the_column, the_data); }