54template <
typename T,
typename Alloc>
62template <
typename T,
typename Alloc>
70 (*current_liboctave_error_handler)
71 (
"Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled");
82 (*current_liboctave_error_handler)
83 (
"Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled");
104template <
typename T,
typename Alloc>
116template <
typename T,
typename Alloc>
129 if (m_data[i] != T ())
131 m_data[k] = m_data[i];
132 m_ridx[k++] = m_ridx[i];
138 change_length (m_cidx[m_ncols]);
141template <
typename T,
typename Alloc>
150 nz = (nz > 0 ? nz : 1);
153 static const int FRAC = 5;
154 if (nz > m_nzmax || nz < m_nzmax - m_nzmax/FRAC)
160 std::copy_n (m_ridx, min_nzmax, new_ridx);
162 idx_type_deallocate (m_ridx, m_nzmax);
165 T *new_data = T_allocate (nz);
166 std::copy_n (m_data, min_nzmax, new_data);
168 T_deallocate (m_data, m_nzmax);
175template <
typename T,
typename Alloc>
183template <
typename T,
typename Alloc>
191 if (octave::math::isnan (m_data[i]))
197template <
typename T,
typename Alloc>
205 if (octave::math::isinf (m_data[i]) || octave::math::isnan (m_data[i]))
211template <
typename T,
typename Alloc>
240template <
typename T,
typename Alloc>
244 m_dimensions (
dim_vector (a.rows (), a.cols ()))
259template <
typename T,
typename Alloc>
262 : m_rep (nullptr), m_dimensions (dv)
264 if (dv.
ndims () != 2)
265 (*current_liboctave_error_handler)
266 (
"Sparse::Sparse (const dim_vector&): dimension mismatch");
271template <
typename T,
typename Alloc>
274 : m_rep (nullptr), m_dimensions (dv)
278 unsigned long long a_nel =
static_cast<unsigned long long> (a.
rows ()) *
279 static_cast<unsigned long long> (a.
cols ());
280 unsigned long long dv_nel =
static_cast<unsigned long long> (dv(0)) *
281 static_cast<unsigned long long> (dv(1));
284 (*current_liboctave_error_handler)
285 (
"Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch");
311 xcidx (k+1) = new_nzmax;
314template <
typename T,
typename Alloc>
317 const octave::idx_vector& r,
318 const octave::idx_vector& c,
321 : m_rep (nullptr), m_dimensions ()
325 else if (r.extent (nr) > nr)
326 (*current_liboctave_error_handler)
327 (
"sparse: row index %" OCTAVE_IDX_TYPE_FORMAT
"out of bound "
328 "%" OCTAVE_IDX_TYPE_FORMAT, r.extent (nr), nr);
332 else if (c.extent (nc) > nc)
334 (
"sparse: column index %" OCTAVE_IDX_TYPE_FORMAT
" out of bound "
335 "%" OCTAVE_IDX_TYPE_FORMAT, c.extent (nc), nc);
342 bool a_scalar = n == 1;
351 if ((rl != 1 && rl != n) || (cl != 1 && cl != n))
352 (*current_liboctave_error_handler) (
"sparse: dimension mismatch");
357 if (rl <= 1 && cl <= 1)
359 if (n == 1 && a(0) != T ())
361 change_capacity (std::max<octave_idx_type> (nzm, 1));
364 std::fill_n (xcidx () + c(0) + 1, nc - c(0), 1);
378 octave::idx_vector rs = r.sorted ();
386 new_nz += rd[i-1] != rd[i];
389 change_capacity (std::max (nzm, new_nz));
390 std::fill_n (xcidx () + c(0) + 1, nc - c(0), new_nz);
432 octave::idx_vector rr = r;
433 octave::idx_vector cc = c;
455 sidx[ci[cd[i]+1]++] = rd[0];
457 sidx[ci[cd[i]+1]++] = rd[i];
463 std::sort (sidx + ci[j], sidx + ci[j+1]);
477 xcidx (j+1) = xcidx (j) + nzj;
480 change_capacity (std::max (nzm, xcidx (nc)));
526 octave::idx_vector rs = r.sorted (rsi);
535 new_nz += rd[i-1] != rd[i];
538 change_capacity (std::max (nzm, new_nz));
539 std::fill_n (xcidx () + c(0) + 1, nc - c(0), new_nz);
555 if (rd[i] != rd[i-1])
569 if (rd[i] != rd[i-1])
575 maybe_compress (
true);
579 octave::idx_vector rr = r;
580 octave::idx_vector cc = c;
598 typedef std::pair<octave_idx_type, octave_idx_type> idx_pair;
603 idx_pair& p = spairs[ci[cd[i]+1]++];
615 std::sort (spairs + ci[j], spairs + ci[j+1]);
629 xcidx (j+1) = xcidx (j) + nzj;
632 change_capacity (std::max (nzm, xcidx (nc)));
650 rrd[++jj] = a(spairs[i].second);
654 rrd[jj] += a(spairs[i].second);
668 rrd[jj] = a(spairs[i].second);
673 maybe_compress (
true);
683template <
typename T,
typename Alloc>
686 : m_rep (nullptr), m_dimensions (a.dims ())
689 (*current_liboctave_error_handler)
690 (
"Sparse::Sparse (const Array<T>&): dimension mismatch");
709 if (a.
elem (i, j) != T ())
718template <
typename T,
typename Alloc>
722 if (--m_rep->m_count == 0)
726template <
typename T,
typename Alloc>
732 if (--m_rep->m_count == 0)
744template <
typename T,
typename Alloc>
752 (*current_liboctave_error_handler)
753 (
"Sparse<T, Alloc>::compute_index: invalid ra_idxing operation");
761 retval *= m_dimensions(n);
768template <
typename T,
typename Alloc>
773 (*current_liboctave_error_handler) (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
"): "
774 "range error", fcn, n);
777template <
typename T,
typename Alloc>
782 (*current_liboctave_error_handler) (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
"): "
783 "range error", fcn, n);
786template <
typename T,
typename Alloc>
792 (*current_liboctave_error_handler)
793 (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
", %" OCTAVE_IDX_TYPE_FORMAT
"): "
794 "range error", fcn, i, j);
797template <
typename T,
typename Alloc>
803 (*current_liboctave_error_handler)
804 (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
", %" OCTAVE_IDX_TYPE_FORMAT
"): "
805 "range error", fcn, i, j);
808template <
typename T,
typename Alloc>
814 std::ostringstream buf;
826 buf <<
"): range error";
828 std::string buf_str = buf.str ();
830 (*current_liboctave_error_handler) (
"%s", buf_str.c_str ());
833template <
typename T,
typename Alloc>
839 std::ostringstream buf;
851 buf <<
"): range error";
853 std::string buf_str = buf.str ();
855 (*current_liboctave_error_handler) (
"%s", buf_str.c_str ());
858template <
typename T,
typename Alloc>
866 if (dims2.
ndims () > 2)
868 (*current_liboctave_warning_with_id_handler)
869 (
"Octave:reshape-smashes-dims",
870 "reshape: sparse reshape to N-D array smashes dims");
873 dims2(1) *= dims2(i);
878 if (m_dimensions != dims2)
880 if (m_dimensions.numel () == dims2.
numel ())
889 if (new_nr == 0 || new_nc == 0)
893 retval.
xcidx (0) = 0;
901 if (i_old_rm >= new_nr)
903 i_old_qu += i_old_rm / new_nr;
904 i_old_rm = i_old_rm % new_nr;
909 ii = (i_old_rm + ridx (j)) % new_nr;
910 jj = i_old_qu + (i_old_rm + ridx (j)) / new_nr;
916 retval.
xcidx (k+1) = j;
918 retval.
xdata (j) = data (j);
919 retval.
xridx (j) = ii;
923 retval.
xcidx (k+1) = new_nnz;
927 std::string dimensions_str = m_dimensions.str ();
928 std::string new_dims_str = new_dims.
str ();
930 (*current_liboctave_error_handler)
931 (
"reshape: can't reshape %s array to %s array",
932 dimensions_str.c_str (), new_dims_str.c_str ());
941template <
typename T,
typename Alloc>
951 if (perm_vec.
numel () == 2)
953 if (perm_vec(0) == 0 && perm_vec(1) == 1)
955 else if (perm_vec(0) == 1 && perm_vec(1) == 0)
964 (*current_liboctave_error_handler)
965 (
"permutation vector contains an invalid element");
967 return trans ? this->transpose () : *
this;
970template <
typename T,
typename Alloc>
979 resize (1, std::max (nc, n));
981 resize (nr, (n + nr - 1) / nr);
987 octave::err_invalid_resize ();
990template <
typename T,
typename Alloc>
998 (*current_liboctave_error_handler) (
"sparse array must be 2-D");
1000 resize (dv(0), dv(1));
1003template <
typename T,
typename Alloc>
1009 (*current_liboctave_error_handler) (
"can't resize to negative dimension");
1011 if (r == dim1 () && c == dim2 ())
1028 xdata (k) = xdata (i);
1029 xridx (k++) = xridx (i);
1035 m_rep->m_nrows = m_dimensions(0) = r;
1037 if (c != m_rep->m_ncols)
1040 std::copy_n (m_rep->m_cidx, std::min (c, m_rep->m_ncols) + 1, new_cidx);
1041 m_rep->idx_type_deallocate (m_rep->m_cidx, m_rep->m_ncols + 1);
1042 m_rep->m_cidx = new_cidx;
1044 if (c > m_rep->m_ncols)
1045 std::fill_n (m_rep->m_cidx + m_rep->m_ncols + 1, c - m_rep->m_ncols,
1046 m_rep->m_cidx[m_rep->m_ncols]);
1049 m_rep->m_ncols = m_dimensions(1) = c;
1051 m_rep->change_length (m_rep->nnz ());
1054template <
typename T,
typename Alloc>
1065 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ())
1066 (*current_liboctave_error_handler) (
"range error for insert");
1071 if (c + a_cols < nc)
1072 nel += cidx (nc) - cidx (c + a_cols);
1076 if (ridx (j) < r || ridx (j) >= r + a_rows)
1085 data (i) = tmp.
data (i);
1086 ridx (i) = tmp.
ridx (i);
1089 cidx (i) = tmp.
cidx (i);
1098 if (tmp.
ridx (j) < r)
1100 data (ii) = tmp.
data (j);
1101 ridx (ii++) = tmp.
ridx (j);
1108 data (ii) = a.
data (j);
1109 ridx (ii++) = r + a.
ridx (j);
1115 if (tmp.
ridx (j) >= r + a_rows)
1117 data (ii) = tmp.
data (j);
1118 ridx (ii++) = tmp.
ridx (j);
1128 data (ii) = tmp.
data (j);
1129 ridx (ii++) = tmp.
ridx (j);
1137template <
typename T,
typename Alloc>
1145 (*current_liboctave_error_handler) (
"range error for insert");
1150template <
typename T,
typename Alloc>
1163 retval.
xcidx (ridx (i) + 1)++;
1169 retval.
xcidx (i) = nz;
1178 retval.
xridx (q) = j;
1179 retval.
xdata (q) = data (k);
1199 for (l = 0; l < nr; l++)
1205 return std::lower_bound (ridx, ridx + nr, ri) - ridx;
1208template <
typename T,
typename Alloc>
1223 const dim_vector idx_dims = idx.orig_dimensions ();
1225 if (idx.extent (nel) > nel)
1226 octave::err_del_index_out_of_range (
true, idx.extent (nel), nel);
1235 if (idx.is_cont_range (nel, lb, ub))
1244 std::copy_n (tmp.
data (), li, data ());
1245 std::copy_n (tmp.
ridx (), li, xridx ());
1246 std::copy (tmp.
data () + ui, tmp.
data () + nz, xdata () + li);
1254 octave::idx_vector sidx = idx.sorted (
true);
1262 for (; j < sl && sj[j] < r; j++) ;
1263 if (j == sl || sj[j] > r)
1265 data_new[nz_new] = tmp.
data (i);
1266 ridx_new[nz_new++] = r - j;
1271 std::copy_n (ridx_new, nz_new, ridx ());
1272 std::copy_n (data_new, nz_new, xdata ());
1280 if (idx.is_cont_range (nc, lb, ub))
1287 std::copy_n (tmp.
data (), lbi, data ());
1288 std::copy (tmp.
data () + ubi, tmp.
data () + nz, xdata () + lbi);
1290 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
1295 *
this = index (idx.complement (nc));
1297 else if (idx.length (nel) != 0)
1299 if (idx.is_colon_equiv (nel))
1303 *
this = index (octave::idx_vector::colon);
1304 delete_elements (idx);
1305 *
this = transpose ();
1310template <
typename T,
typename Alloc>
1314 const octave::idx_vector& idx_j)
1322 if (idx_i.is_colon ())
1326 if (idx_j.extent (nc) > nc)
1327 octave::err_del_index_out_of_range (
false, idx_j.extent (nc), nc);
1328 else if (idx_j.is_cont_range (nc, lb, ub))
1330 if (lb == 0 && ub == nc)
1348 std::copy_n (tmp.
data (), lbi, data ());
1349 std::copy_n (tmp.
ridx (), lbi, ridx ());
1350 std::copy (tmp.
data () + ubi, tmp.
data () + nz, xdata () + lbi);
1351 std::copy (tmp.
ridx () + ubi, tmp.
ridx () + nz, xridx () + lbi);
1352 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
1354 tmp.
cidx () + ub + 1, ubi - lbi);
1358 *
this = index (idx_i, idx_j.complement (nc));
1360 else if (idx_j.is_colon ())
1364 if (idx_i.extent (nr) > nr)
1365 octave::err_del_index_out_of_range (
false, idx_i.extent (nr), nr);
1366 else if (idx_i.is_cont_range (nr, lb, ub))
1368 if (lb == 0 && ub == nr)
1384 tmpl.
nnz () + tmpu.
nnz ());
1390 xdata (k) = tmpl.
data (i);
1391 xridx (k++) = tmpl.
ridx (i);
1396 xdata (k) = tmpu.
data (i);
1397 xridx (k++) = tmpu.
ridx (i) + lb;
1422 bool empty_assignment
1423 = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0);
1425 if (! empty_assignment)
1426 (*current_liboctave_error_handler)
1427 (
"a null assignment can only have one non-colon index");
1431template <
typename T,
typename Alloc>
1437 delete_elements (idx, octave::idx_vector::colon);
1439 delete_elements (octave::idx_vector::colon, idx);
1444template <
typename T,
typename Alloc>
1461 if (idx.is_colon ())
1474 retval.
xdata (j) = data (j);
1475 retval.
xridx (j) = ridx (j) + i * nr;
1479 retval.
xcidx (0) = 0;
1480 retval.
xcidx (1) = nz;
1483 else if (idx.extent (nel) > nel)
1486 octave::err_index_out_of_range (1, 1, idx.extent (nel), nel, dims ());
1492 retval = tmp.
index (idx);
1494 else if (nr == 1 && nc == 1)
1500 retval = (
Sparse<T, Alloc> (idx_dims(0), idx_dims(1), nz ? data (0) : T ()));
1507 if (idx.is_scalar ())
1511 if (i < nz && ridx (i) == idx(0))
1512 retval =
Sparse (1, 1, data (i));
1516 else if (idx.is_cont_range (nel, lb, ub))
1525 std::copy_n (data () + li, nz_new, retval.
data ());
1527 retval.
xcidx (1) = nz_new;
1529 else if (idx.is_permutation (nel) && idx.isvector ())
1531 if (idx.is_range () && idx.increment () == -1)
1536 retval.
ridx (j) = nr - ridx (nz - j - 1) - 1;
1538 std::copy_n (cidx (), 2, retval.
cidx ());
1539 std::reverse_copy (data (), data () + nz, retval.
data ());
1544 tmp = tmp.
index (idx);
1567 lidx.
xelem (i) = lblookup (ridx (), nz, idxa(i));
1577 if (l < nz && ridx (l) == idxa(i, j))
1580 lidx.
xelem (i, j) = nz;
1595 retval.
data (k) = data (l);
1596 retval.
xridx (k++) = i;
1604 if (idx.is_scalar ())
1606 else if (idx.is_cont_range (nel, lb, ub))
1613 std::copy_n (data () + lbi, new_nz, retval.
data ());
1626 if (nr != 0 && idx.is_scalar ())
1634 retval = index (octave::idx_vector::colon).
index (idx);
1637 if (idx_dims(0) == 1 && idx_dims(1) != 1)
1645template <
typename T,
typename Alloc>
1649 const octave::idx_vector& idx_j,
1650 bool resize_ok)
const
1664 if (idx_i.extent (nr) > nr || idx_j.extent (nc) > nc)
1672 tmp.
resize (ext_i, ext_j);
1673 retval = tmp.
index (idx_i, idx_j);
1675 else if (idx_i.extent (nr) > nr)
1676 octave::err_index_out_of_range (2, 1, idx_i.extent (nr), nr, dims ());
1678 octave::err_index_out_of_range (2, 2, idx_j.extent (nc), nc, dims ());
1680 else if (nr == 1 && nc == 1)
1688 else if (idx_i.is_colon ())
1692 if (idx_j.is_colon ())
1694 else if (idx_j.is_cont_range (nc, lb, ub))
1701 std::copy_n (data () + lbi, new_nz, retval.
data ());
1702 std::copy_n (ridx () + lbi, new_nz, retval.
ridx ());
1712 retval.
xcidx (j+1) = retval.
xcidx (j) + (cidx (jj+1) - cidx (jj));
1724 std::copy_n (data () + ljj, nzj, retval.
data () + lj);
1725 std::copy_n (ridx () + ljj, nzj, retval.
ridx () + lj);
1729 else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())
1732 retval = index (idx_i);
1738 else if (idx_i.is_scalar ())
1752 if (i < nzj && ridx (i+lj) == ii)
1767 if (retval.
xcidx (j+1) > i)
1769 retval.
xridx (i) = 0;
1770 retval.
xdata (i) = data (ij[j]);
1774 else if (idx_i.is_cont_range (nr, lb, ub))
1788 li[j] = lij = lblookup (ridx () + lj, nzj, lb) + lj;
1789 ui[j] = uij = lblookup (ridx () + lj, nzj, ub) + lj;
1790 retval.
xcidx (j+1) = retval.
xcidx (j) + ui[j] - li[j];
1801 retval.
xdata (k) = data (i);
1802 retval.
xridx (k++) = ridx (i) - lb;
1806 else if (idx_i.is_permutation (nr))
1814 retval.
xcidx (j+1) = retval.
xcidx (j) + (cidx (jj+1) - cidx (jj));
1821 if (idx_i.is_range () && idx_i.increment () == -1)
1834 retval.
xdata (li + i) = data (uj - i);
1835 retval.
xridx (li + i) = nr - 1 - ridx (uj - i);
1842 octave::idx_vector idx_iinv = idx_i.inverse_permutation (nr);
1858 scb[rri[li + i] = iinv[ridx (lj + i)]] = data (lj + i);
1863 std::sort (rri + li, rri + li + nzj);
1867 retval.
xdata (li + i) = scb[rri[li + i]];
1872 else if (idx_j.is_colon ())
1877 retval = transpose ();
1878 retval = retval.
index (octave::idx_vector::colon, idx_i);
1884 retval = index (octave::idx_vector::colon, idx_j);
1885 retval = retval.
index (idx_i, octave::idx_vector::colon);
1891template <
typename T,
typename Alloc>
1909 if (idx.length (n) == rhl)
1925 if (idx.is_colon ())
1927 *
this = rhs.
reshape (m_dimensions);
1929 else if (nc == 1 && rhs.
cols () == 1)
1934 if (idx.is_cont_range (nr, lb, ub))
1943 if (new_nz >= nz && new_nz <= nzmax ())
1950 std::copy_backward (data () + ui, data () + nz,
1951 data () + nz + rnz);
1952 std::copy_backward (ridx () + ui, ridx () + nz,
1953 ridx () + nz + rnz);
1957 std::copy_n (rhs.
data (), rnz, data () + li);
1968 std::copy_n (tmp.
data (), li, data ());
1969 std::copy_n (tmp.
ridx (), li, ridx ());
1972 std::copy_n (rhs.
data (), rnz, data () + li);
1976 std::copy (tmp.
data () + ui, tmp.
data () + nz,
1977 data () + li + rnz);
1978 std::copy (tmp.
ridx () + ui, tmp.
ridx () + nz,
1979 ridx () + li + rnz);
1984 else if (idx.is_range () && idx.increment () == -1)
1987 assign (idx.sorted (), rhs.
index (octave::idx_vector (rhl - 1, -1, -1)));
1989 else if (idx.is_permutation (n))
1991 *
this = rhs.
index (idx.inverse_permutation (n));
1993 else if (rhs.
nnz () == 0)
2001 if (li != nz && ri[li] == iidx)
2005 maybe_compress (
true);
2014 std::copy_n (tmp.
ridx (), nz, new_ri.
rwdata ());
2015 std::copy_n (tmp.
data (), nz, new_data.
rwdata ());
2017 idx.copy_data (new_ri.
rwdata () + nz);
2026 *
this = index (octave::idx_vector::colon);
2027 assign (idx, rhs.
index (octave::idx_vector::colon));
2028 *
this = reshape (save_dims);
2033 rhl = idx.length (n);
2034 if (rhs.
nnz () != 0)
2040 octave::err_nonconformant (
"=",
dim_vector(idx.length (n), 1), rhs.
dims());
2043template <
typename T,
typename Alloc>
2055template <
typename T,
typename Alloc>
2059 const octave::idx_vector& idx_j,
2076 bool orig_zero_by_zero = (nr == 0 && nc == 0);
2078 if (orig_zero_by_zero || (idx_i.length (nr) == n && idx_j.length (nc) == m))
2083 if (orig_zero_by_zero)
2085 if (idx_i.is_colon ())
2089 if (idx_j.is_colon ())
2092 ncx = idx_j.extent (nc);
2094 else if (idx_j.is_colon ())
2096 nrx = idx_i.extent (nr);
2101 nrx = idx_i.extent (nr);
2102 ncx = idx_j.extent (nc);
2107 nrx = idx_i.extent (nr);
2108 ncx = idx_j.extent (nc);
2112 if (nrx != nr || ncx != nc)
2120 if (n == 0 || m == 0)
2123 if (idx_i.is_colon ())
2128 if (idx_j.is_colon ())
2130 else if (idx_j.is_cont_range (nc, lb, ub))
2138 if (new_nz >= nz && new_nz <= nzmax ())
2145 std::copy_backward (data () + ui, data () + nz,
2147 std::copy_backward (ridx () + ui, ridx () + nz,
2153 std::copy_n (rhs.
data (), rnz, data () + li);
2154 std::copy_n (rhs.
ridx (), rnz, ridx () + li);
2168 std::copy_n (tmp.
data (), li, data ());
2169 std::copy_n (tmp.
ridx (), li, ridx ());
2170 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
2173 std::copy_n (rhs.
data (), rnz, data () + li);
2174 std::copy_n (rhs.
ridx (), rnz, ridx () + li);
2179 std::copy (tmp.
data () + ui, tmp.
data () + nz,
2180 data () + li + rnz);
2181 std::copy (tmp.
ridx () + ui, tmp.
ridx () + nz,
2182 ridx () + li + rnz);
2184 tmp.
cidx () + ub + 1, new_nz - nz);
2189 else if (idx_j.is_range () && idx_j.increment () == -1)
2192 assign (idx_i, idx_j.sorted (),
2193 rhs.
index (idx_i, octave::idx_vector (m - 1, -1, -1)));
2195 else if (idx_j.is_permutation (nc))
2197 *
this = rhs.
index (idx_i, idx_j.inverse_permutation (nc));
2207 xcidx (i+1) = tmp.
cidx (i+1) - tmp.
cidx (i);
2213 xcidx (j+1) = rhs.
cidx (i+1) - rhs.
cidx (i);
2218 xcidx (i+1) += xcidx (i);
2220 change_capacity (nnz ());
2232 std::copy_n (rhs.
data () + k, u - l, xdata () + l);
2233 std::copy_n (rhs.
ridx () + k, u - l, xridx () + l);
2239 std::copy_n (tmp.
data () + k, u - l, xdata () + l);
2240 std::copy_n (tmp.
ridx () + k, u - l, xridx () + l);
2246 else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())
2249 assign (idx_i, rhs);
2251 else if (idx_j.is_colon ())
2253 if (idx_i.is_permutation (nr))
2255 *
this = rhs.
index (idx_i.inverse_permutation (nr), idx_j);
2263 *
this = transpose ();
2264 assign (octave::idx_vector::colon, idx_i, rhs.
transpose ());
2265 *
this = transpose ();
2272 tmp.
assign (idx_i, octave::idx_vector::colon, rhs);
2273 assign (octave::idx_vector::colon, idx_j, tmp);
2276 else if (m == 1 && n == 1)
2278 n = idx_i.length (nr);
2279 m = idx_j.length (nc);
2280 if (rhs.
nnz () != 0)
2285 else if (idx_i.length (nr) == m && idx_j.length (nc) == n
2286 && (n == 1 || m == 1))
2288 assign (idx_i, idx_j, rhs.
transpose ());
2291 octave::err_nonconformant (
"=", idx_i.length (nr), idx_j.length (nc), n, m);
2294template <
typename T,
typename Alloc>
2298 const octave::idx_vector& idx_j,
2310template <
typename T>
2319template <
typename T>
2328template <
typename T,
typename Alloc>
2338 if (m.
numel () < 1 || dim > 1)
2341 bool sort_by_column = (dim > 0);
2356 (
"Sparse<T, Alloc>::sort: invalid MODE");
2370 for (i = 0; i < ns; i++)
2371 if (sparse_ascending_compare<T> (
static_cast<T
> (0), v[i]))
2376 for (i = 0; i < ns; i++)
2377 if (sparse_descending_compare<T> (
static_cast<T
> (0), v[i]))
2383 mridx[k] = k - ns + nr;
2395template <
typename T,
typename Alloc>
2406 if (m.
numel () < 1 || dim > 1)
2412 bool sort_by_column = (dim > 0);
2422 indexed_sort.
set_compare (sparse_ascending_compare<T>);
2424 indexed_sort.
set_compare (sparse_descending_compare<T>);
2427 (
"Sparse<T, Alloc>::sort: invalid MODE");
2444 sidx(offset + k) = k;
2451 indexed_sort.
sort (v, vi, ns);
2456 for (i = 0; i < ns; i++)
2457 if (sparse_ascending_compare<T> (
static_cast<T
> (0), v[i]))
2462 for (i = 0; i < ns; i++)
2463 if (sparse_descending_compare<T> (
static_cast<T
> (0), v[i]))
2471 if (ii < ns && mridx[ii] == k)
2474 sidx(offset + jj++) = k;
2479 sidx(k + offset) = vi[k];
2485 sidx(k - ns + nr + offset) = vi[k];
2486 mridx[k] = k - ns + nr;
2503template <
typename T,
typename Alloc>
2512 if (nnr == 0 || nnc == 0)
2514 else if (nnr != 1 && nnc != 1)
2521 if (nnr > 0 && nnc > 0)
2530 if (elem (i, i+k) != 0.)
2536 if (elem (i-k, i) != 0.)
2542 if (elem (i, i) != 0.)
2555 T tmp = elem (i, i+k);
2567 T tmp = elem (i-k, i);
2579 T tmp = elem (i, i);
2630 d.xdata (i) = data (i);
2631 d.xridx (i) = j + roff;
2633 d.xcidx (j + coff + 1) = cidx (j+1);
2659 d.xdata (ii) = data (ii);
2660 d.xridx (ii++) = ir + roff;
2665 d.xcidx (i + coff + 1) = ii;
2677template <
typename T,
typename Alloc>
2686 if (dim == -1 || dim == -2)
2692 (*current_liboctave_error_handler) (
"cat: invalid dimension");
2696 if (dim != 0 && dim != 1)
2697 (*current_liboctave_error_handler)
2698 (
"cat: invalid dimension for sparse concatenation");
2701 return sparse_list[0];
2705 if (! (dv.*concat_rule) (sparse_list[i].
dims (), dim))
2706 (*current_liboctave_error_handler) (
"cat: dimension mismatch");
2708 total_nz += sparse_list[i].
nnz ();
2743 rcum += spi.
rows ();
2746 retval.
xcidx (j+1) = l;
2759 if (sparse_list[i].isempty ())
2763 retval.
assign (octave::idx_vector::colon, octave::idx_vector (l, u),
2771 (*current_liboctave_error_handler) (
"Sparse<T, Alloc>::cat: invalid dimension = %d - please report this bug", dim);
2777template <
typename T,
typename Alloc>
2789 retval.
xelem (j) = data (i++);
2796 retval.
xelem (ridx (i), j) = data (i);
2802template <
typename T>
2806 T (*read_fcn) (std::istream&))
2812 if (nr > 0 && nc > 0)
2834 std::string err_field;
2836 (*current_liboctave_error_handler)
2837 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2838 "Symbols '%s' is not an integer format",
2839 i+1, err_field.c_str ());
2842 if (itmp < 0 || itmp >= nr)
2844 is.setstate (std::ios::failbit);
2846 (*current_liboctave_error_handler)
2847 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2848 "row index = %" OCTAVE_IDX_TYPE_FORMAT
" out of range",
2852 if (jtmp < 0 || jtmp >= nc)
2854 is.setstate (std::ios::failbit);
2856 (*current_liboctave_error_handler)
2857 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2858 "column index = %" OCTAVE_IDX_TYPE_FORMAT
" out of range",
2864 is.setstate (std::ios::failbit);
2866 (*current_liboctave_error_handler)
2867 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
":"
2868 "column indices must appear in ascending order "
2869 "(%" OCTAVE_IDX_TYPE_FORMAT
" < %" OCTAVE_IDX_TYPE_FORMAT
")",
2872 else if (jtmp > jold)
2877 else if (itmp < iold)
2879 is.setstate (std::ios::failbit);
2881 (*current_liboctave_error_handler)
2882 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2883 "row indices must appear in ascending order in each column "
2884 "(%" OCTAVE_IDX_TYPE_FORMAT
" < %" OCTAVE_IDX_TYPE_FORMAT
")",
2891 tmp = read_fcn (is);
2897 a.
ridx (ii++) = itmp;
3105template <
typename T,
typename Alloc>
3110 os << prefix <<
"m_rep address: " << m_rep <<
"\n"
3111 << prefix <<
"m_rep->m_nzmax: " << m_rep->m_nzmax <<
"\n"
3112 << prefix <<
"m_rep->m_nrows: " << m_rep->m_nrows <<
"\n"
3113 << prefix <<
"m_rep->m_ncols: " << m_rep->m_ncols <<
"\n"
3114 << prefix <<
"m_rep->m_data: " << m_rep->m_data <<
"\n"
3115 << prefix <<
"m_rep->m_ridx: " << m_rep->m_ridx <<
"\n"
3116 << prefix <<
"m_rep->m_cidx: " << m_rep->m_cidx <<
"\n"
3117 << prefix <<
"m_rep->m_count: " << m_rep->m_count <<
"\n";
3120#if defined (__clang__)
3121# define INSTANTIATE_SPARSE(T) \
3122 template class OCTAVE_API Sparse<T>; \
3123 template OCTAVE_API std::istream& \
3124 read_sparse_matrix<T> (std::istream& is, Sparse<T>& a, \
3125 T (*read_fcn) (std::istream&));
3127# define INSTANTIATE_SPARSE(T) \
3128 template class Sparse<T>; \
3129 template OCTAVE_API std::istream& \
3130 read_sparse_matrix<T> (std::istream& is, Sparse<T>& a, \
3131 T (*read_fcn) (std::istream&));
std::istream & read_sparse_matrix(std::istream &is, Sparse< T > &a, T(*read_fcn)(std::istream &))
bool sparse_descending_compare(typename ref_param< T >::type a, typename ref_param< T >::type b)
bool sparse_ascending_compare(typename ref_param< T >::type a, typename ref_param< T >::type b)
N Dimensional Array with copy-on-write semantics.
T & xelem(octave_idx_type n)
Size of the specified dimension.
Array< T, Alloc > index(const octave::idx_vector &i) const
Indexing without resizing.
void assign(const octave::idx_vector &i, const Array< T, Alloc > &rhs, const T &rfv)
Indexed assignment (always with resize & fill).
Array< T, Alloc > transpose() const
Size of the specified dimension.
T & elem(octave_idx_type n)
Size of the specified dimension.
octave_idx_type rows() const
octave_idx_type cols() const
Array< T, Alloc > as_matrix() const
Return the array as a matrix.
const T * data() const
Size of the specified dimension.
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
octave_idx_type rows() const
const Array< octave_idx_type > & col_perm_vec() const
bool any_element_is_nan() const
void change_length(octave_idx_type nz)
octave::refcount< octave_idx_type > m_count
void maybe_compress(bool remove_zeros)
T & elem(octave_idx_type r, octave_idx_type c)
T celem(octave_idx_type r, octave_idx_type c) const
bool any_element_is_inf_or_nan() const
octave_idx_type cols() const
Sparse< T, Alloc > diag(octave_idx_type k=0) const
Sparse< T, Alloc > permute(const Array< octave_idx_type > &vec, bool inv=false) const
octave_idx_type nzmax() const
Amount of storage for nonzero elements.
Array< T > array_value() const
void delete_elements(const octave::idx_vector &i)
Sparse< T, Alloc > index(const octave::idx_vector &i, bool resize_ok=false) const
void print_info(std::ostream &os, const std::string &prefix) const
octave_idx_type columns() const
void assign(const octave::idx_vector &i, const Sparse< T, Alloc > &rhs)
void resize(octave_idx_type r, octave_idx_type c)
Sparse< T, Alloc > sort(octave_idx_type dim=0, sortmode mode=ASCENDING) const
Sparse< T, Alloc > & insert(const Sparse< T, Alloc > &a, octave_idx_type r, octave_idx_type c)
void resize1(octave_idx_type n)
OCTAVE_NORETURN T range_error(const char *fcn, octave_idx_type n) const
octave_idx_type numel() const
static Sparse< T, Alloc > cat(int dim, octave_idx_type n, const Sparse< T, Alloc > *sparse_list)
Sparse< T, Alloc > & operator=(const Sparse< T, Alloc > &a)
octave_idx_type nnz() const
Actual number of nonzero terms.
octave_idx_type rows() const
void change_capacity(octave_idx_type nz)
Sparse< T, Alloc > transpose() const
octave_idx_type compute_index(const Array< octave_idx_type > &ra_idx) const
Sparse< T, Alloc >::SparseRep * m_rep
Sparse< T, Alloc > reshape(const dim_vector &new_dims) const
octave_idx_type * xcidx()
octave_idx_type * xridx()
Vector representing the dimensions (size) of an Array.
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
octave_idx_type safe_numel() const
The following function will throw a std::bad_alloc () exception if the requested size is larger than ...
std::string str(char sep='x') const
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
void resize(int n, int fill_value=0)
octave_idx_type ndims() const
Number of dimensions.
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
virtual octave_idx_type numel() const
void set_compare(const compare_fcn_type &comp)
void sort(T *data, octave_idx_type nel)
if_then_else< is_class_type< T >::no, T, Tconst & >::result type
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
void mx_inline_add2(std::size_t n, R *r, const X *x)
void mx_inline_sub(std::size_t n, R *r, const X *x, const Y *y)
void mx_inline_add(std::size_t n, R *r, const X *x, const Y *y)
#define liboctave_panic_unless(cond)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)
T::size_type numel(const T &str)
const octave_base_value const Array< octave_idx_type > & ra_idx
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
bool sparse_indices_ok(octave_idx_type *r, octave_idx_type *c, octave_idx_type nrows, octave_idx_type ncols, octave_idx_type nnz)