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>
226template <
typename T,
typename Alloc>
230 m_dimensions (
dim_vector (a.rows (), a.cols ()))
245template <
typename T,
typename Alloc>
248 : m_rep (nullptr), m_dimensions (dv)
250 if (dv.
ndims () != 2)
251 (*current_liboctave_error_handler)
252 (
"Sparse::Sparse (const dim_vector&): dimension mismatch");
257template <
typename T,
typename Alloc>
260 : m_rep (nullptr), m_dimensions (dv)
264 unsigned long long a_nel =
static_cast<unsigned long long> (a.
rows ()) *
265 static_cast<unsigned long long> (a.
cols ());
266 unsigned long long dv_nel =
static_cast<unsigned long long> (dv(0)) *
267 static_cast<unsigned long long> (dv(1));
270 (*current_liboctave_error_handler)
271 (
"Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch");
297 xcidx (k+1) = new_nzmax;
300template <
typename T,
typename Alloc>
303 const octave::idx_vector& r,
304 const octave::idx_vector& c,
307 : m_rep (nullptr), m_dimensions ()
311 else if (r.extent (nr) > nr)
312 (*current_liboctave_error_handler)
313 (
"sparse: row index %" OCTAVE_IDX_TYPE_FORMAT
"out of bound "
314 "%" OCTAVE_IDX_TYPE_FORMAT, r.extent (nr), nr);
318 else if (c.extent (nc) > nc)
320 (
"sparse: column index %" OCTAVE_IDX_TYPE_FORMAT
" out of bound "
321 "%" OCTAVE_IDX_TYPE_FORMAT, c.extent (nc), nc);
328 bool a_scalar = n == 1;
337 if ((rl != 1 && rl != n) || (cl != 1 && cl != n))
338 (*current_liboctave_error_handler) (
"sparse: dimension mismatch");
343 if (rl <= 1 && cl <= 1)
345 if (n == 1 && a(0) != T ())
350 std::fill_n (
xcidx () + c(0) + 1, nc - c(0), 1);
364 octave::idx_vector rs = r.sorted ();
372 new_nz += rd[i-1] != rd[i];
376 std::fill_n (
xcidx () + c(0) + 1, nc - c(0), new_nz);
418 octave::idx_vector rr = r;
419 octave::idx_vector cc = c;
441 sidx[ci[cd[i]+1]++] = rd[0];
443 sidx[ci[cd[i]+1]++] = rd[i];
449 std::sort (sidx + ci[j], sidx + ci[j+1]);
512 octave::idx_vector rs = r.sorted (rsi);
521 new_nz += rd[i-1] != rd[i];
525 std::fill_n (
xcidx () + c(0) + 1, nc - c(0), new_nz);
541 if (rd[i] != rd[i-1])
555 if (rd[i] != rd[i-1])
565 octave::idx_vector rr = r;
566 octave::idx_vector cc = c;
584 typedef std::pair<octave_idx_type, octave_idx_type> idx_pair;
589 idx_pair& p = spairs[ci[cd[i]+1]++];
601 std::sort (spairs + ci[j], spairs + ci[j+1]);
636 rrd[++jj] = a(spairs[i].second);
640 rrd[jj] += a(spairs[i].second);
654 rrd[jj] = a(spairs[i].second);
669template <
typename T,
typename Alloc>
672 : m_rep (nullptr), m_dimensions (a.dims ())
675 (*current_liboctave_error_handler)
676 (
"Sparse::Sparse (const Array<T>&): dimension mismatch");
695 if (a.
elem (i, j) != T ())
704template <
typename T,
typename Alloc>
708 if (--m_rep->m_count == 0)
712template <
typename T,
typename Alloc>
718 if (--m_rep->m_count == 0)
730template <
typename T,
typename Alloc>
738 (*current_liboctave_error_handler)
739 (
"Sparse<T, Alloc>::compute_index: invalid ra_idxing operation");
747 retval *= m_dimensions(n);
754template <
typename T,
typename Alloc>
759 (*current_liboctave_error_handler) (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
"): "
760 "range error", fcn, n);
763template <
typename T,
typename Alloc>
768 (*current_liboctave_error_handler) (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
"): "
769 "range error", fcn, n);
772template <
typename T,
typename Alloc>
778 (*current_liboctave_error_handler)
779 (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
", %" OCTAVE_IDX_TYPE_FORMAT
"): "
780 "range error", fcn, i, j);
783template <
typename T,
typename Alloc>
789 (*current_liboctave_error_handler)
790 (
"%s (%" OCTAVE_IDX_TYPE_FORMAT
", %" OCTAVE_IDX_TYPE_FORMAT
"): "
791 "range error", fcn, i, j);
794template <
typename T,
typename Alloc>
800 std::ostringstream buf;
812 buf <<
"): range error";
814 std::string buf_str = buf.str ();
816 (*current_liboctave_error_handler) (
"%s", buf_str.c_str ());
819template <
typename T,
typename Alloc>
825 std::ostringstream buf;
837 buf <<
"): range error";
839 std::string buf_str = buf.str ();
841 (*current_liboctave_error_handler) (
"%s", buf_str.c_str ());
844template <
typename T,
typename Alloc>
852 if (dims2.
ndims () > 2)
854 (*current_liboctave_warning_with_id_handler)
855 (
"Octave:reshape-smashes-dims",
856 "reshape: sparse reshape to N-D array smashes dims");
859 dims2(1) *= dims2(i);
864 if (m_dimensions != dims2)
866 if (m_dimensions.numel () == dims2.
numel ())
875 if (new_nr == 0 || new_nc == 0)
879 retval.
xcidx (0) = 0;
887 if (i_old_rm >= new_nr)
889 i_old_qu += i_old_rm / new_nr;
890 i_old_rm = i_old_rm % new_nr;
895 ii = (i_old_rm + ridx (j)) % new_nr;
896 jj = i_old_qu + (i_old_rm + ridx (j)) / new_nr;
902 retval.
xcidx (k+1) = j;
904 retval.
xdata (j) = data (j);
905 retval.
xridx (j) = ii;
909 retval.
xcidx (k+1) = new_nnz;
913 std::string dimensions_str = m_dimensions.str ();
914 std::string new_dims_str = new_dims.
str ();
916 (*current_liboctave_error_handler)
917 (
"reshape: can't reshape %s array to %s array",
918 dimensions_str.c_str (), new_dims_str.c_str ());
927template <
typename T,
typename Alloc>
937 if (perm_vec.
numel () == 2)
939 if (perm_vec(0) == 0 && perm_vec(1) == 1)
941 else if (perm_vec(0) == 1 && perm_vec(1) == 0)
950 (*current_liboctave_error_handler)
951 (
"permutation vector contains an invalid element");
953 return trans ? this->transpose () : *
this;
956template <
typename T,
typename Alloc>
965 resize (1, std::max (nc, n));
967 resize (nr, (n + nr - 1) / nr);
973 octave::err_invalid_resize ();
976template <
typename T,
typename Alloc>
984 (*current_liboctave_error_handler) (
"sparse array must be 2-D");
986 resize (dv(0), dv(1));
989template <
typename T,
typename Alloc>
995 (*current_liboctave_error_handler) (
"can't resize to negative dimension");
997 if (r == dim1 () && c == dim2 ())
1014 xdata (k) = xdata (i);
1015 xridx (k++) = xridx (i);
1021 m_rep->m_nrows = m_dimensions(0) = r;
1023 if (c != m_rep->m_ncols)
1026 std::copy_n (m_rep->m_cidx, std::min (c, m_rep->m_ncols) + 1, new_cidx);
1027 m_rep->idx_type_deallocate (m_rep->m_cidx, m_rep->m_ncols + 1);
1028 m_rep->m_cidx = new_cidx;
1030 if (c > m_rep->m_ncols)
1031 std::fill_n (m_rep->m_cidx + m_rep->m_ncols + 1, c - m_rep->m_ncols,
1032 m_rep->m_cidx[m_rep->m_ncols]);
1035 m_rep->m_ncols = m_dimensions(1) = c;
1037 m_rep->change_length (m_rep->nnz ());
1040template <
typename T,
typename Alloc>
1051 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ())
1052 (*current_liboctave_error_handler) (
"range error for insert");
1057 if (c + a_cols < nc)
1058 nel += cidx (nc) - cidx (c + a_cols);
1062 if (ridx (j) < r || ridx (j) >= r + a_rows)
1071 data (i) = tmp.
data (i);
1072 ridx (i) = tmp.
ridx (i);
1075 cidx (i) = tmp.
cidx (i);
1084 if (tmp.
ridx (j) < r)
1086 data (ii) = tmp.
data (j);
1087 ridx (ii++) = tmp.
ridx (j);
1094 data (ii) = a.
data (j);
1095 ridx (ii++) = r + a.
ridx (j);
1101 if (tmp.
ridx (j) >= r + a_rows)
1103 data (ii) = tmp.
data (j);
1104 ridx (ii++) = tmp.
ridx (j);
1114 data (ii) = tmp.
data (j);
1115 ridx (ii++) = tmp.
ridx (j);
1123template <
typename T,
typename Alloc>
1131 (*current_liboctave_error_handler) (
"range error for insert");
1136template <
typename T,
typename Alloc>
1149 retval.
xcidx (ridx (i) + 1)++;
1155 retval.
xcidx (i) = nz;
1164 retval.
xridx (q) = j;
1165 retval.
xdata (q) = data (k);
1185 for (l = 0; l < nr; l++)
1191 return std::lower_bound (ridx, ridx + nr, ri) - ridx;
1194template <
typename T,
typename Alloc>
1209 const dim_vector idx_dims = idx.orig_dimensions ();
1211 if (idx.extent (nel) > nel)
1212 octave::err_del_index_out_of_range (
true, idx.extent (nel), nel);
1221 if (idx.is_cont_range (nel, lb, ub))
1230 std::copy_n (tmp.
data (), li, data ());
1231 std::copy_n (tmp.
ridx (), li, xridx ());
1232 std::copy (tmp.
data () + ui, tmp.
data () + nz, xdata () + li);
1240 octave::idx_vector sidx = idx.sorted (
true);
1248 for (; j < sl && sj[j] < r; j++) ;
1249 if (j == sl || sj[j] > r)
1251 data_new[nz_new] = tmp.
data (i);
1252 ridx_new[nz_new++] = r - j;
1257 std::copy_n (ridx_new, nz_new, ridx ());
1258 std::copy_n (data_new, nz_new, xdata ());
1266 if (idx.is_cont_range (nc, lb, ub))
1273 std::copy_n (tmp.
data (), lbi, data ());
1274 std::copy (tmp.
data () + ubi, tmp.
data () + nz, xdata () + lbi);
1276 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
1281 *
this = index (idx.complement (nc));
1283 else if (idx.length (nel) != 0)
1285 if (idx.is_colon_equiv (nel))
1289 *
this = index (octave::idx_vector::colon);
1290 delete_elements (idx);
1291 *
this = transpose ();
1296template <
typename T,
typename Alloc>
1300 const octave::idx_vector& idx_j)
1308 if (idx_i.is_colon ())
1312 if (idx_j.extent (nc) > nc)
1313 octave::err_del_index_out_of_range (
false, idx_j.extent (nc), nc);
1314 else if (idx_j.is_cont_range (nc, lb, ub))
1316 if (lb == 0 && ub == nc)
1334 std::copy_n (tmp.
data (), lbi, data ());
1335 std::copy_n (tmp.
ridx (), lbi, ridx ());
1336 std::copy (tmp.
data () + ubi, tmp.
data () + nz, xdata () + lbi);
1337 std::copy (tmp.
ridx () + ubi, tmp.
ridx () + nz, xridx () + lbi);
1338 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
1340 tmp.
cidx () + ub + 1, ubi - lbi);
1344 *
this = index (idx_i, idx_j.complement (nc));
1346 else if (idx_j.is_colon ())
1350 if (idx_i.extent (nr) > nr)
1351 octave::err_del_index_out_of_range (
false, idx_i.extent (nr), nr);
1352 else if (idx_i.is_cont_range (nr, lb, ub))
1354 if (lb == 0 && ub == nr)
1370 tmpl.
nnz () + tmpu.
nnz ());
1376 xdata (k) = tmpl.
data (i);
1377 xridx (k++) = tmpl.
ridx (i);
1382 xdata (k) = tmpu.
data (i);
1383 xridx (k++) = tmpu.
ridx (i) + lb;
1408 bool empty_assignment
1409 = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0);
1411 if (! empty_assignment)
1412 (*current_liboctave_error_handler)
1413 (
"a null assignment can only have one non-colon index");
1417template <
typename T,
typename Alloc>
1423 delete_elements (idx, octave::idx_vector::colon);
1425 delete_elements (octave::idx_vector::colon, idx);
1430template <
typename T,
typename Alloc>
1447 if (idx.is_colon ())
1460 retval.
xdata (j) = data (j);
1461 retval.
xridx (j) = ridx (j) + i * nr;
1465 retval.
xcidx (0) = 0;
1466 retval.
xcidx (1) = nz;
1469 else if (idx.extent (nel) > nel)
1472 octave::err_index_out_of_range (1, 1, idx.extent (nel), nel, dims ());
1478 retval = tmp.
index (idx);
1480 else if (nr == 1 && nc == 1)
1486 retval = (
Sparse<T, Alloc> (idx_dims(0), idx_dims(1), nz ? data (0) : T ()));
1493 if (idx.is_scalar ())
1497 if (i < nz && ridx (i) == idx(0))
1498 retval =
Sparse (1, 1, data (i));
1502 else if (idx.is_cont_range (nel, lb, ub))
1511 std::copy_n (data () + li, nz_new, retval.
data ());
1513 retval.
xcidx (1) = nz_new;
1515 else if (idx.is_permutation (nel) && idx.isvector ())
1517 if (idx.is_range () && idx.increment () == -1)
1522 retval.
ridx (j) = nr - ridx (nz - j - 1) - 1;
1524 std::copy_n (cidx (), 2, retval.
cidx ());
1525 std::reverse_copy (data (), data () + nz, retval.
data ());
1530 tmp = tmp.
index (idx);
1553 lidx.
xelem (i) = lblookup (ridx (), nz, idxa(i));
1563 if (l < nz && ridx (l) == idxa(i, j))
1566 lidx.
xelem (i, j) = nz;
1581 retval.
data (k) = data (l);
1582 retval.
xridx (k++) = i;
1590 if (idx.is_scalar ())
1592 else if (idx.is_cont_range (nel, lb, ub))
1599 std::copy_n (data () + lbi, new_nz, retval.
data ());
1612 if (nr != 0 && idx.is_scalar ())
1620 retval = index (octave::idx_vector::colon).
index (idx);
1623 if (idx_dims(0) == 1 && idx_dims(1) != 1)
1631template <
typename T,
typename Alloc>
1635 const octave::idx_vector& idx_j,
1636 bool resize_ok)
const
1650 if (idx_i.extent (nr) > nr || idx_j.extent (nc) > nc)
1658 tmp.
resize (ext_i, ext_j);
1659 retval = tmp.
index (idx_i, idx_j);
1661 else if (idx_i.extent (nr) > nr)
1662 octave::err_index_out_of_range (2, 1, idx_i.extent (nr), nr, dims ());
1664 octave::err_index_out_of_range (2, 2, idx_j.extent (nc), nc, dims ());
1666 else if (nr == 1 && nc == 1)
1674 else if (idx_i.is_colon ())
1678 if (idx_j.is_colon ())
1680 else if (idx_j.is_cont_range (nc, lb, ub))
1687 std::copy_n (data () + lbi, new_nz, retval.
data ());
1688 std::copy_n (ridx () + lbi, new_nz, retval.
ridx ());
1698 retval.
xcidx (j+1) = retval.
xcidx (j) + (cidx (jj+1) - cidx (jj));
1710 std::copy_n (data () + ljj, nzj, retval.
data () + lj);
1711 std::copy_n (ridx () + ljj, nzj, retval.
ridx () + lj);
1715 else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())
1718 retval = index (idx_i);
1724 else if (idx_i.is_scalar ())
1738 if (i < nzj && ridx (i+lj) == ii)
1753 if (retval.
xcidx (j+1) > i)
1755 retval.
xridx (i) = 0;
1756 retval.
xdata (i) = data (ij[j]);
1760 else if (idx_i.is_cont_range (nr, lb, ub))
1774 li[j] = lij = lblookup (ridx () + lj, nzj, lb) + lj;
1775 ui[j] = uij = lblookup (ridx () + lj, nzj, ub) + lj;
1776 retval.
xcidx (j+1) = retval.
xcidx (j) + ui[j] - li[j];
1787 retval.
xdata (k) = data (i);
1788 retval.
xridx (k++) = ridx (i) - lb;
1792 else if (idx_i.is_permutation (nr))
1800 retval.
xcidx (j+1) = retval.
xcidx (j) + (cidx (jj+1) - cidx (jj));
1807 if (idx_i.is_range () && idx_i.increment () == -1)
1820 retval.
xdata (li + i) = data (uj - i);
1821 retval.
xridx (li + i) = nr - 1 - ridx (uj - i);
1828 octave::idx_vector idx_iinv = idx_i.inverse_permutation (nr);
1844 scb[rri[li + i] = iinv[ridx (lj + i)]] = data (lj + i);
1849 std::sort (rri + li, rri + li + nzj);
1853 retval.
xdata (li + i) = scb[rri[li + i]];
1858 else if (idx_j.is_colon ())
1863 retval = transpose ();
1864 retval = retval.
index (octave::idx_vector::colon, idx_i);
1870 retval = index (octave::idx_vector::colon, idx_j);
1871 retval = retval.
index (idx_i, octave::idx_vector::colon);
1877template <
typename T,
typename Alloc>
1895 if (idx.length (n) == rhl)
1911 if (idx.is_colon ())
1913 *
this = rhs.
reshape (m_dimensions);
1915 else if (nc == 1 && rhs.
cols () == 1)
1920 if (idx.is_cont_range (nr, lb, ub))
1929 if (new_nz >= nz && new_nz <= nzmax ())
1936 std::copy_backward (data () + ui, data () + nz,
1937 data () + nz + rnz);
1938 std::copy_backward (ridx () + ui, ridx () + nz,
1939 ridx () + nz + rnz);
1943 std::copy_n (rhs.
data (), rnz, data () + li);
1954 std::copy_n (tmp.
data (), li, data ());
1955 std::copy_n (tmp.
ridx (), li, ridx ());
1958 std::copy_n (rhs.
data (), rnz, data () + li);
1962 std::copy (tmp.
data () + ui, tmp.
data () + nz,
1963 data () + li + rnz);
1964 std::copy (tmp.
ridx () + ui, tmp.
ridx () + nz,
1965 ridx () + li + rnz);
1970 else if (idx.is_range () && idx.increment () == -1)
1973 assign (idx.sorted (), rhs.
index (octave::idx_vector (rhl - 1, 0, -1)));
1975 else if (idx.is_permutation (n))
1977 *
this = rhs.
index (idx.inverse_permutation (n));
1979 else if (rhs.
nnz () == 0)
1987 if (li != nz && ri[li] == iidx)
1991 maybe_compress (
true);
2000 std::copy_n (tmp.
ridx (), nz, new_ri.
rwdata ());
2001 std::copy_n (tmp.
data (), nz, new_data.
rwdata ());
2003 idx.copy_data (new_ri.
rwdata () + nz);
2012 *
this = index (octave::idx_vector::colon);
2013 assign (idx, rhs.
index (octave::idx_vector::colon));
2014 *
this = reshape (save_dims);
2019 rhl = idx.length (n);
2020 if (rhs.
nnz () != 0)
2026 octave::err_nonconformant (
"=",
dim_vector(idx.length (n), 1), rhs.
dims());
2029template <
typename T,
typename Alloc>
2041template <
typename T,
typename Alloc>
2045 const octave::idx_vector& idx_j,
2062 bool orig_zero_by_zero = (nr == 0 && nc == 0);
2064 if (orig_zero_by_zero || (idx_i.length (nr) == n && idx_j.length (nc) == m))
2069 if (orig_zero_by_zero)
2071 if (idx_i.is_colon ())
2075 if (idx_j.is_colon ())
2078 ncx = idx_j.extent (nc);
2080 else if (idx_j.is_colon ())
2082 nrx = idx_i.extent (nr);
2087 nrx = idx_i.extent (nr);
2088 ncx = idx_j.extent (nc);
2093 nrx = idx_i.extent (nr);
2094 ncx = idx_j.extent (nc);
2098 if (nrx != nr || ncx != nc)
2106 if (n == 0 || m == 0)
2109 if (idx_i.is_colon ())
2114 if (idx_j.is_colon ())
2116 else if (idx_j.is_cont_range (nc, lb, ub))
2124 if (new_nz >= nz && new_nz <= nzmax ())
2131 std::copy_backward (data () + ui, data () + nz,
2133 std::copy_backward (ridx () + ui, ridx () + nz,
2139 std::copy_n (rhs.
data (), rnz, data () + li);
2140 std::copy_n (rhs.
ridx (), rnz, ridx () + li);
2154 std::copy_n (tmp.
data (), li, data ());
2155 std::copy_n (tmp.
ridx (), li, ridx ());
2156 std::copy_n (tmp.
cidx () + 1, lb, cidx () + 1);
2159 std::copy_n (rhs.
data (), rnz, data () + li);
2160 std::copy_n (rhs.
ridx (), rnz, ridx () + li);
2165 std::copy (tmp.
data () + ui, tmp.
data () + nz,
2166 data () + li + rnz);
2167 std::copy (tmp.
ridx () + ui, tmp.
ridx () + nz,
2168 ridx () + li + rnz);
2170 tmp.
cidx () + ub + 1, new_nz - nz);
2175 else if (idx_j.is_range () && idx_j.increment () == -1)
2178 assign (idx_i, idx_j.sorted (),
2179 rhs.
index (idx_i, octave::idx_vector (m - 1, 0, -1)));
2181 else if (idx_j.is_permutation (nc))
2183 *
this = rhs.
index (idx_i, idx_j.inverse_permutation (nc));
2193 xcidx (i+1) = tmp.
cidx (i+1) - tmp.
cidx (i);
2199 xcidx (j+1) = rhs.
cidx (i+1) - rhs.
cidx (i);
2204 xcidx (i+1) += xcidx (i);
2206 change_capacity (nnz ());
2218 std::copy_n (rhs.
data () + k, u - l, xdata () + l);
2219 std::copy_n (rhs.
ridx () + k, u - l, xridx () + l);
2225 std::copy_n (tmp.
data () + k, u - l, xdata () + l);
2226 std::copy_n (tmp.
ridx () + k, u - l, xridx () + l);
2232 else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.isvector ())
2235 assign (idx_i, rhs);
2237 else if (idx_j.is_colon ())
2239 if (idx_i.is_permutation (nr))
2241 *
this = rhs.
index (idx_i.inverse_permutation (nr), idx_j);
2249 *
this = transpose ();
2250 assign (octave::idx_vector::colon, idx_i, rhs.
transpose ());
2251 *
this = transpose ();
2258 tmp.
assign (idx_i, octave::idx_vector::colon, rhs);
2259 assign (octave::idx_vector::colon, idx_j, tmp);
2262 else if (m == 1 && n == 1)
2264 n = idx_i.length (nr);
2265 m = idx_j.length (nc);
2266 if (rhs.
nnz () != 0)
2271 else if (idx_i.length (nr) == m && idx_j.length (nc) == n
2272 && (n == 1 || m == 1))
2274 assign (idx_i, idx_j, rhs.
transpose ());
2277 octave::err_nonconformant (
"=", idx_i.length (nr), idx_j.length (nc), n, m);
2280template <
typename T,
typename Alloc>
2284 const octave::idx_vector& idx_j,
2296template <
typename T>
2305template <
typename T>
2314template <
typename T,
typename Alloc>
2324 if (m.
numel () < 1 || dim > 1)
2327 bool sort_by_column = (dim > 0);
2342 (
"Sparse<T, Alloc>::sort: invalid MODE");
2356 for (i = 0; i < ns; i++)
2357 if (sparse_ascending_compare<T> (
static_cast<T
> (0), v[i]))
2362 for (i = 0; i < ns; i++)
2363 if (sparse_descending_compare<T> (
static_cast<T
> (0), v[i]))
2369 mridx[k] = k - ns + nr;
2381template <
typename T,
typename Alloc>
2392 if (m.
numel () < 1 || dim > 1)
2398 bool sort_by_column = (dim > 0);
2408 indexed_sort.
set_compare (sparse_ascending_compare<T>);
2410 indexed_sort.
set_compare (sparse_descending_compare<T>);
2413 (
"Sparse<T, Alloc>::sort: invalid MODE");
2430 sidx(offset + k) = k;
2437 indexed_sort.
sort (v, vi, ns);
2442 for (i = 0; i < ns; i++)
2443 if (sparse_ascending_compare<T> (
static_cast<T
> (0), v[i]))
2448 for (i = 0; i < ns; i++)
2449 if (sparse_descending_compare<T> (
static_cast<T
> (0), v[i]))
2457 if (ii < ns && mridx[ii] == k)
2460 sidx(offset + jj++) = k;
2465 sidx(k + offset) = vi[k];
2471 sidx(k - ns + nr + offset) = vi[k];
2472 mridx[k] = k - ns + nr;
2489template <
typename T,
typename Alloc>
2498 if (nnr == 0 || nnc == 0)
2500 else if (nnr != 1 && nnc != 1)
2507 if (nnr > 0 && nnc > 0)
2516 if (elem (i, i+k) != 0.)
2522 if (elem (i-k, i) != 0.)
2528 if (elem (i, i) != 0.)
2541 T tmp = elem (i, i+k);
2553 T tmp = elem (i-k, i);
2565 T tmp = elem (i, i);
2616 d.xdata (i) = data (i);
2617 d.xridx (i) = j + roff;
2619 d.xcidx (j + coff + 1) = cidx (j+1);
2645 d.xdata (ii) = data (ii);
2646 d.xridx (ii++) = ir + roff;
2651 d.xcidx (i + coff + 1) = ii;
2663template <
typename T,
typename Alloc>
2672 if (dim == -1 || dim == -2)
2678 (*current_liboctave_error_handler) (
"cat: invalid dimension");
2682 if (dim != 0 && dim != 1)
2683 (*current_liboctave_error_handler)
2684 (
"cat: invalid dimension for sparse concatenation");
2687 return sparse_list[0];
2691 if (! (dv.*concat_rule) (sparse_list[i].
dims (), dim))
2692 (*current_liboctave_error_handler) (
"cat: dimension mismatch");
2694 total_nz += sparse_list[i].
nnz ();
2729 rcum += spi.
rows ();
2732 retval.
xcidx (j+1) = l;
2745 if (sparse_list[i].isempty ())
2749 retval.
assign (octave::idx_vector::colon, octave::idx_vector (l, u),
2757 (*current_liboctave_error_handler) (
"Sparse<T, Alloc>::cat: invalid dimension = %d - please report this bug", dim);
2763template <
typename T,
typename Alloc>
2775 retval.
xelem (j) = data (i++);
2782 retval.
xelem (ridx (i), j) = data (i);
2788template <
typename T>
2792 T (*read_fcn) (std::istream&))
2798 if (nr > 0 && nc > 0)
2820 std::string err_field;
2822 (*current_liboctave_error_handler)
2823 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2824 "Symbols '%s' is not an integer format",
2825 i+1, err_field.c_str ());
2828 if (itmp < 0 || itmp >= nr)
2830 is.setstate (std::ios::failbit);
2832 (*current_liboctave_error_handler)
2833 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2834 "row index = %" OCTAVE_IDX_TYPE_FORMAT
" out of range",
2838 if (jtmp < 0 || jtmp >= nc)
2840 is.setstate (std::ios::failbit);
2842 (*current_liboctave_error_handler)
2843 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2844 "column index = %" OCTAVE_IDX_TYPE_FORMAT
" out of range",
2850 is.setstate (std::ios::failbit);
2852 (*current_liboctave_error_handler)
2853 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
":"
2854 "column indices must appear in ascending order "
2855 "(%" OCTAVE_IDX_TYPE_FORMAT
" < %" OCTAVE_IDX_TYPE_FORMAT
")",
2858 else if (jtmp > jold)
2863 else if (itmp < iold)
2865 is.setstate (std::ios::failbit);
2867 (*current_liboctave_error_handler)
2868 (
"invalid sparse matrix: element %" OCTAVE_IDX_TYPE_FORMAT
": "
2869 "row indices must appear in ascending order in each column "
2870 "(%" OCTAVE_IDX_TYPE_FORMAT
" < %" OCTAVE_IDX_TYPE_FORMAT
")",
2877 tmp = read_fcn (is);
2883 a.
ridx (ii++) = itmp;
3091template <
typename T,
typename Alloc>
3096 os << prefix <<
"m_rep address: " << m_rep <<
"\n"
3097 << prefix <<
"m_rep->m_nzmax: " << m_rep->m_nzmax <<
"\n"
3098 << prefix <<
"m_rep->m_nrows: " << m_rep->m_nrows <<
"\n"
3099 << prefix <<
"m_rep->m_ncols: " << m_rep->m_ncols <<
"\n"
3100 << prefix <<
"m_rep->m_data: " << m_rep->m_data <<
"\n"
3101 << prefix <<
"m_rep->m_ridx: " << m_rep->m_ridx <<
"\n"
3102 << prefix <<
"m_rep->m_cidx: " << m_rep->m_cidx <<
"\n"
3103 << prefix <<
"m_rep->m_count: " << m_rep->m_count <<
"\n";
3106#if defined (__clang__)
3107# define INSTANTIATE_SPARSE(T) \
3108 template class OCTAVE_API Sparse<T>; \
3109 template OCTAVE_API std::istream& \
3110 read_sparse_matrix<T> (std::istream& is, Sparse<T>& a, \
3111 T (*read_fcn) (std::istream&));
3113# define INSTANTIATE_SPARSE(T) \
3114 template class Sparse<T>; \
3115 template OCTAVE_API std::istream& \
3116 read_sparse_matrix<T> (std::istream& is, Sparse<T>& a, \
3117 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
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 > maybe_compress(bool remove_zeros=false)
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
#define liboctave_panic_unless(cond)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
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 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
bool sparse_indices_ok(octave_idx_type *r, octave_idx_type *c, octave_idx_type nrows, octave_idx_type ncols, octave_idx_type nnz)