45template <
typename T,
typename Alloc>
55template <
typename T,
typename Alloc>
57 : m_dimensions (dv), m_rep (a.m_rep),
58 m_slice_data (a.m_slice_data), m_slice_len (a.m_slice_len)
60 bool invalid_size =
false;
73 catch (
const std::bad_alloc&)
78 if (invalid_size || new_numel != a.
numel ())
83 (*current_liboctave_error_handler)
84 (
"reshape: can't reshape %s array to %s array",
85 dimensions_str.c_str (), new_dims_str.c_str ());
94template <
typename T,
typename Alloc>
98 if (m_rep->m_count > 1)
102 m_slice_data = m_rep->m_data;
105 std::fill_n (m_slice_data, m_slice_len, val);
108template <
typename T,
typename Alloc>
112 if (--m_rep->m_count == 0)
117 m_slice_data = m_rep->m_data;
118 m_slice_len = m_rep->m_len;
123template <
typename T,
typename Alloc>
127 if (--m_rep->m_count == 0)
131 m_slice_data = m_rep->m_data;
132 m_slice_len = m_rep->m_len;
138template <
typename T,
typename Alloc>
146 bool dims_changed =
false;
152 for (
int i = 0; i < ndims (); i++)
154 if (m_dimensions(i) == 1)
157 new_dimensions(k++) = m_dimensions(i);
172 new_dimensions.
resize (2);
174 new_dimensions(0) = tmp;
175 new_dimensions(1) = 1;
180 new_dimensions.
resize (k);
191template <
typename T,
typename Alloc>
195 return ::compute_index (i, j, m_dimensions);
198template <
typename T,
typename Alloc>
203 return ::compute_index (i, j, k, m_dimensions);
206template <
typename T,
typename Alloc>
210 return ::compute_index (
ra_idx, m_dimensions);
213template <
typename T,
typename Alloc>
220template <
typename T,
typename Alloc>
226 octave::err_invalid_index (n);
227 if (n >= m_slice_len)
228 octave::err_index_out_of_range (1, 1, n+1, m_slice_len, m_dimensions);
233template <
typename T,
typename Alloc>
240template <
typename T,
typename Alloc>
247template <
typename T,
typename Alloc>
254template <
typename T,
typename Alloc>
260 octave::err_invalid_index (n);
261 if (n >= m_slice_len)
262 octave::err_index_out_of_range (1, 1, n+1, m_slice_len, m_dimensions);
267template <
typename T,
typename Alloc>
274template <
typename T,
typename Alloc>
282template <
typename T,
typename Alloc>
289template <
typename T,
typename Alloc>
298template <
typename T,
typename Alloc>
309template <
typename T,
typename Alloc>
320class rec_permute_helper
327 m_stride (m_dim + m_n), m_use_blk (false)
334 for (
int i = 1; i < m_n+1; i++) cdim[i] = cdim[i-1] * dv(i-1);
337 for (
int k = 0; k < m_n; k++)
341 m_stride[k] = cdim[kk];
345 for (
int k = 1; k < m_n; k++)
347 if (m_stride[k] == m_stride[m_top]*m_dim[m_top])
348 m_dim[m_top] *= m_dim[k];
352 m_dim[m_top] = m_dim[k];
353 m_stride[m_top] = m_stride[k];
358 m_use_blk = m_top >= 1 && m_stride[1] == 1 && m_stride[0] == m_dim[1];
362 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_permute_helper)
364 ~rec_permute_helper () {
delete [] m_dim; }
366 template <
typename T>
367 void permute (
const T *src, T *dest)
const { do_permute (src, dest, m_top); }
370 template <
typename T>
381 if (lr == m && lc == m)
383 const T *ss = src + kc * nr + kr;
386 blk[j*m+i] = ss[j*nr + i];
387 T *dd = dest + kr * nc + kc;
390 dd[j*nc+i] = blk[i*m+j];
394 const T *ss = src + kc * nr + kr;
397 blk[j*m+i] = ss[j*nr + i];
398 T *dd = dest + kr * nc + kc;
401 dd[j*nc+i] = blk[i*m+j];
411 template <
typename T>
412 T * do_permute (
const T *src, T *dest,
int lev)
const
420 std::copy_n (src,
len, dest);
431 else if (m_use_blk && lev == 1)
432 dest = blk_trans (src, dest, m_dim[1], m_dim[0]);
438 dest = do_permute (src + i * step, dest, lev-1);
456template <
typename T,
typename Alloc>
466 int perm_vec_len = perm_vec_arg.
numel ();
468 if (perm_vec_len < dv.
ndims ())
469 (*current_liboctave_error_handler)
470 (
"%s: invalid permutation vector", inv ?
"ipermute" :
"permute");
475 dv.
resize (perm_vec_len, 1);
480 bool identity =
true;
483 for (
int i = 0; i < perm_vec_len; i++)
486 if (perm_elt >= perm_vec_len || perm_elt < 0)
487 (*current_liboctave_error_handler)
488 (
"%s: permutation vector contains an invalid element",
489 inv ?
"ipermute" :
"permute");
491 if (checked[perm_elt])
492 (*current_liboctave_error_handler)
493 (
"%s: permutation vector cannot contain identical elements",
494 inv ?
"ipermute" :
"permute");
497 checked[perm_elt] =
true;
498 identity = identity && perm_elt == i;
507 for (
int i = 0; i < perm_vec_len; i++)
508 perm_vec(perm_vec_arg(i)) = i;
511 for (
int i = 0; i < perm_vec_len; i++)
512 dv_new(i) = dv(perm_vec(i));
518 rec_permute_helper rh (dv, perm_vec);
519 rh.permute (data (), retval.
rwdata ());
531class rec_index_helper
537 m_cdim (m_dim + m_n), m_idx (
new octave::idx_vector [m_n])
548 if (m_idx[m_top].maybe_reduce (m_dim[m_top], ia(i), dv(i)))
551 m_dim[m_top] *= dv(i);
557 m_idx[m_top] = ia(i);
558 m_dim[m_top] = dv(i);
559 m_cdim[m_top] = m_cdim[m_top-1] * m_dim[m_top-1];
564 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_index_helper)
566 ~rec_index_helper () {
delete [] m_idx;
delete [] m_dim; }
568 template <
typename T>
569 void index (
const T *src, T *dest)
const { do_index (src, dest, m_top); }
571 template <
typename T>
572 void assign (
const T *src, T *dest)
const { do_assign (src, dest, m_top); }
574 template <
typename T>
575 void fill (
const T& val, T *dest)
const { do_fill (val, dest, m_top); }
579 return m_top == 0 && m_idx[0].is_cont_range (m_dim[0], l, u);
585 template <
typename T>
589 dest += m_idx[0].index (src, m_dim[0], dest);
595 dest = do_index (src +
d*m_idx[lev].xelem (i), dest, lev-1);
602 template <
typename T>
606 src += m_idx[0].assign (src, m_dim[0], dest);
612 src = do_assign (src, dest +
d*m_idx[lev].xelem (i), lev-1);
619 template <
typename T>
623 m_idx[0].fill (val, m_dim[0], dest);
629 do_fill (val, dest +
d*m_idx[lev].xelem (i), lev-1);
642 octave::idx_vector *m_idx;
648class rec_resize_helper
653 : m_cext (
nullptr), m_sext (
nullptr), m_dext (
nullptr), m_n (0)
655 int l = ndv.
ndims ();
659 for (; i < l-1 && ndv(i) == odv(i); i++) ld *= ndv(i);
663 m_sext = m_cext + m_n;
664 m_dext = m_sext + m_n;
668 for (
int j = 0; j < m_n; j++)
670 m_cext[j] = std::min (ndv(i+j), odv(i+j));
671 m_sext[j] = sld *= odv(i+j);
672 m_dext[j] = dld *= ndv(i+j);
677 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_resize_helper)
679 ~rec_resize_helper () {
delete [] m_cext; }
681 template <
typename T>
682 void resize_fill (
const T *src, T *dest,
const T& rfv)
const
683 { do_resize_fill (src, dest, rfv, m_n-1); }
688 template <
typename T>
689 void do_resize_fill (
const T *src, T *dest,
const T& rfv,
int lev)
const
693 std::copy_n (src, m_cext[0], dest);
694 std::fill_n (dest + m_cext[0], m_dext[0] - m_cext[0], rfv);
701 for (k = 0; k < m_cext[lev]; k++)
702 do_resize_fill (src + k * sd, dest + k * dd, rfv, lev - 1);
704 std::fill_n (dest + k * dd, m_dext[lev] - k * dd, rfv);
716template <
typename T,
typename Alloc>
748 if (i.extent (n) != n)
749 octave::err_index_out_of_range (1, 1, i.extent (n), n, m_dimensions);
751 dim_vector result_dims = i.orig_dimensions ();
754 if (n != 1 && is_nd_vector () && idx_len != 1
766 if (idx_len != 0 && i.is_cont_range (n, l, u))
776 i.index (data (), n, retval.
rwdata ());
783template <
typename T,
typename Alloc>
793 if (i.is_colon () && j.is_colon ())
800 if (i.extent (r) != r)
801 octave::err_index_out_of_range (2, 1, i.extent (r), r, m_dimensions);
802 if (j.extent (c) != c)
803 octave::err_index_out_of_range (2, 2, j.extent (c), c, m_dimensions);
809 octave::idx_vector ii (i);
811 if (ii.maybe_reduce (r, j, c))
814 if (ii.length () > 0 && ii.is_cont_range (n, l, u))
822 ii.index (data (), n, retval.
rwdata ());
830 const T *src = data ();
834 dest += i.index (src + r * j.xelem (k), r, dest);
841template <
typename T,
typename Alloc>
845 int ial = ia.
numel ();
850 retval = index (ia(0));
852 retval = index (ia(0), ia(1));
859 bool all_colons =
true;
860 for (
int i = 0; i < ial; i++)
862 if (ia(i).extent (dv(i)) != dv(i))
863 octave::err_index_out_of_range (ial, i+1, ia(i).extent (dv(i)), dv(i),
866 all_colons = all_colons && ia(i).is_colon ();
879 for (
int i = 0; i < ial; i++) rdv(i) = ia(i).length (dv(i));
883 rec_index_helper rh (dv, ia);
886 if (rh.is_cont_range (l, u))
895 rh.index (data (), retval.
rwdata ());
905template <
typename T,
typename Alloc>
909 static T zero = T ();
916template <
typename T,
typename Alloc>
920 if (n < 0 || ndims () != 2)
921 octave::err_invalid_resize ();
931 bool invalid =
false;
932 if (rows () == 0 || rows () == 1)
934 else if (columns () == 1)
940 octave::err_invalid_resize ();
943 if (n == nx - 1 && n > 0)
946 if (m_rep->m_count == 1)
947 m_slice_data[m_slice_len-1] = T ();
951 else if (n == nx + 1 && nx > 0)
954 if (m_rep->m_count == 1
955 && m_slice_data + m_slice_len < m_rep->m_data + m_rep->m_len)
957 m_slice_data[m_slice_len++] = rfv;
965 T *dest = tmp.rwdata ();
967 std::copy_n (data (), nx, dest);
980 std::copy_n (data (), n0, dest);
981 std::fill_n (dest + n0, n1, rfv);
987template <
typename T,
typename Alloc>
991 if (r < 0 || c < 0 || ndims () != 2)
992 octave::err_invalid_resize ();
996 if (r != rx || c != cx)
1005 const T *src = data ();
1008 std::copy_n (src, r * c0, dest);
1015 std::copy_n (src, r0, dest);
1018 std::fill_n (dest, r1, rfv);
1023 std::fill_n (dest, r * c1, rfv);
1029template <
typename T,
typename Alloc>
1033 int dvl = dv.
ndims ();
1035 resize2 (dv(0), dv(1), rfv);
1036 else if (m_dimensions != dv)
1038 if (m_dimensions.ndims () > dvl || dv.
any_neg ())
1039 octave::err_invalid_resize ();
1043 rec_resize_helper rh (dv, m_dimensions.
redim (dvl));
1046 rh.resize_fill (data (), tmp.
rwdata (), rfv);
1051template <
typename T,
typename Alloc>
1068 if (tmp.
numel () != nx)
1072 return tmp.
index (i);
1075template <
typename T,
typename Alloc>
1078 bool resize_ok,
const T& rfv)
const
1088 if (r != rx || c != cx)
1090 if (i.is_scalar () && j.is_scalar ())
1100 return tmp.
index (i, j);
1103template <
typename T,
typename Alloc>
1106 bool resize_ok,
const T& rfv)
const
1111 int ial = ia.
numel ();
1114 for (
int i = 0; i < ial; i++)
1115 dvx(i) = ia(i).extent (dv(i));
1118 bool all_scalars =
true;
1119 for (
int i = 0; i < ial; i++)
1120 all_scalars = all_scalars && ia(i).is_scalar ();
1131 return tmp.
index (ia);
1134template <
typename T,
typename Alloc>
1138 return index (ia, resize_ok, resize_fill_value ());
1141template <
typename T,
typename Alloc>
1148 if (rhl != 1 && i.length (n) != rhl)
1149 octave::err_nonconformant (
"=",
dim_vector(i.length(n), 1), rhs.
dims());
1152 bool colon = i.is_colon_equiv (nx);
1157 if (m_dimensions.zero_by_zero () && colon)
1176 *
this = rhs.
reshape (m_dimensions);
1181 i.fill (rhs(0), n, rwdata ());
1183 i.assign (rhs.
data (), n, rwdata ());
1188template <
typename T,
typename Alloc>
1193 bool initial_dims_all_zero = m_dimensions.all_zero ();
1207 if (initial_dims_all_zero)
1211 rdv(0) = i.extent (dv(0));
1212 rdv(1) = j.extent (dv(1));
1215 bool isfill = rhs.
numel () == 1;
1219 bool match = (isfill
1220 || (rhdv.
ndims () == 2 && il == rhdv(0) && jl == rhdv(1)));
1221 match = match || (il == 1 && jl == rhdv(0) && rhdv(1) == 1);
1225 bool all_colons = (i.is_colon_equiv (rdv(0))
1226 && j.is_colon_equiv (rdv(1)));
1250 *
this = rhs.
reshape (m_dimensions);
1258 octave::idx_vector ii (i);
1260 const T *src = rhs.
data ();
1261 T *dest = rwdata ();
1264 if (ii.maybe_reduce (r, j, c))
1267 ii.fill (*src, n, dest);
1269 ii.assign (src, n, dest);
1276 i.fill (*src, r, dest + r * j.xelem (k));
1281 src += i.assign (src, r, dest + r * j.xelem (k));
1287 else if ((il != 0 && jl != 0) || (rhdv(0) != 0 && rhdv(1) != 0))
1288 octave::err_nonconformant (
"=", il, jl, rhs.
dim1 (), rhs.
dim2 ());
1292template <
typename T,
typename Alloc>
1297 int ial = ia.
numel ();
1301 assign (ia(0), rhs, rfv);
1303 assign (ia(0), ia(1), rhs, rfv);
1306 bool initial_dims_all_zero = m_dimensions.all_zero ();
1320 if (initial_dims_all_zero)
1325 for (
int i = 0; i < ial; i++)
1326 rdv(i) = ia(i).extent (dv(i));
1331 bool all_colons =
true;
1332 bool isfill = rhs.
numel () == 1;
1336 int rhdvl = rhdv.
ndims ();
1337 for (
int i = 0; i < ial; i++)
1339 all_colons = all_colons && ia(i).is_colon_equiv (rdv(i));
1341 if (l == 1)
continue;
1342 match = match && j < rhdvl && l == rhdv(j++);
1345 match = match && (j == rhdvl || rhdv(j) == 1);
1346 match = match || isfill;
1374 *
this = rhs.
reshape (m_dimensions);
1381 rec_index_helper rh (dv, ia);
1385 rh.fill (rhs(0), rwdata ());
1387 rh.assign (rhs.
data (), rwdata ());
1393 bool lhsempty, rhsempty;
1394 lhsempty = rhsempty =
false;
1396 for (
int i = 0; i < ial; i++)
1400 lhsempty = lhsempty || (l == 0);
1401 rhsempty = rhsempty || (rhdv(j++) == 0);
1403 if (! lhsempty || ! rhsempty)
1406 octave::err_nonconformant (
"=", lhs_dv, rhdv);
1412template <
typename T,
typename Alloc>
1417 assign (ia, rhs, resize_fill_value ());
1428template <
typename T,
typename Alloc>
1437 else if (i.length (n) != 0)
1439 if (i.extent (n) != n)
1440 octave::err_del_index_out_of_range (
true, i.extent (n), n);
1443 bool col_vec = ndims () == 2 && columns () == 1 && rows () != 1;
1444 if (i.is_scalar () && i(0) == n-1 && m_dimensions.isvector ())
1449 else if (i.is_cont_range (n, l, u))
1454 const T *src = data ();
1456 std::copy_n (src, l, dest);
1457 std::copy (src + u, src + n, dest + l);
1463 *
this = index (i.complement (n));
1468template <
typename T,
typename Alloc>
1473 (*current_liboctave_error_handler) (
"invalid dimension in delete_elements");
1477 if (dim >= ndims ())
1478 dimensions.
resize (dim + 1, 1);
1487 else if (i.length (n) != 0)
1489 if (i.extent (n) != n)
1490 octave::err_del_index_out_of_range (
false, i.extent (n), n);
1494 if (i.is_cont_range (n, l, u))
1502 for (
int k = 0; k < dim; k++) dl *= dimensions(k);
1503 for (
int k = dim + 1; k < ndim; k++) du *= dimensions(k);
1507 const T *src = data ();
1509 l *= dl; u *= dl; n *= dl;
1512 std::copy_n (src, l, dest);
1514 std::copy (src + u, src + n, dest);
1525 ia (dim) = i.complement (n);
1531template <
typename T,
typename Alloc>
1535 int ial = ia.
numel ();
1538 delete_elements (ia(0));
1542 for (k = 0; k < ial; k++)
1544 if (! ia(k).is_colon ())
1560 delete_elements (dim, ia(dim));
1575 bool empty_assignment =
false;
1577 int num_non_colon_indices = 0;
1581 for (
int i = 0; i < ial; i++)
1585 if (ia(i).length (dim_len) == 0)
1587 empty_assignment =
true;
1591 if (! ia(i).is_colon_equiv (dim_len))
1593 num_non_colon_indices++;
1595 if (num_non_colon_indices == 2)
1600 if (! empty_assignment)
1601 (*current_liboctave_error_handler)
1602 (
"a null assignment can only have one non-colon index");
1608template <
typename T,
typename Alloc>
1612 octave::idx_vector i (r, r + a.
rows ());
1613 octave::idx_vector j (c, c + a.
columns ());
1614 if (ndims () == 2 && a.
ndims () == 2)
1621 for (
int k = 2; k < a.
ndims (); k++)
1629template <
typename T,
typename Alloc>
1637 idx(k) = octave::idx_vector (
ra_idx(k),
ra_idx(k) + dva(k));
1644template <
typename T,
typename Alloc>
1653 if (nr >= 8 && nc >= 8)
1659 rec_permute_helper::blk_trans (data (), result.
rwdata (), nr, nc);
1663 else if (nr > 1 && nc > 1)
1669 result.
xelem (j, i) = xelem (i, j);
1680template <
typename T>
1682no_op_fcn (
const T&
x)
1687template <
typename T,
typename Alloc>
1699 if (nr >= 8 && nc >= 8)
1708 for (jj = 0; jj < (nc - 8 + 1); jj += 8)
1711 for (ii = 0; ii < (nr - 8 + 1); ii += 8)
1715 j < jj + 8; j++, idxj += nr)
1717 buf[k++] = xelem (i + idxj);
1724 result.
xelem (j + idxi) = fcn (buf[k]);
1730 result.
xelem (j, i) = fcn (xelem (i, j));
1735 result.
xelem (j, i) = fcn (xelem (i, j));
1745 result.
xelem (j, i) = fcn (xelem (i, j));
1785template <
typename T,
typename Alloc>
1791 return m_slice_data;
1795template <
typename T>
1802template <
typename T,
typename Alloc>
1807 (*current_liboctave_error_handler) (
"sort: invalid dimension");
1812 if (dim >= ndims ())
1829 for (
int i = 0; i < dim; i++)
1833 const T *ov = data ();
1857 if (sort_isnan<T> (tmp))
1869 std::reverse (v + ku, v + ns);
1871 std::rotate (v, v + ku, v + ns);
1886 offset += n_strides * stride * (ns - 1);
1893 T tmp = ov[i*stride + offset];
1894 if (sort_isnan<T> (tmp))
1901 lsort.
sort (buf, kl);
1906 std::reverse (buf + ku, buf + ns);
1908 std::rotate (buf, buf + ku, buf + ns);
1913 v[i*stride + offset] = buf[i];
1920template <
typename T,
typename Alloc>
1926 (*current_liboctave_error_handler) (
"sort: invalid dimension");
1932 if (
numel () < 1 || dim >= ndims ())
1941 for (
int i = 0; i < dim; i++)
1945 const T *ov = data ();
1968 if (sort_isnan<T> (tmp))
1983 lsort.
sort (v, vi, kl);
1988 std::reverse (v + ku, v + ns);
1989 std::reverse (vi + ku, vi + ns);
1992 std::rotate (v, v + ku, v + ns);
1993 std::rotate (vi, vi + ku, vi + ns);
2011 offset += n_strides * stride * (ns - 1);
2018 T tmp = ov[i*stride + offset];
2019 if (sort_isnan<T> (tmp))
2034 lsort.
sort (buf, bufi, kl);
2039 std::reverse (buf + ku, buf + ns);
2040 std::reverse (bufi + ku, bufi + ns);
2043 std::rotate (buf, buf + ku, buf + ns);
2044 std::rotate (bufi, bufi + ku, bufi + ns);
2050 v[i*stride + offset] = buf[i];
2052 vi[i*stride + offset] = bufi[i];
2059template <
typename T,
typename Alloc>
2072template <
typename T,
typename Alloc>
2086 compare_fcn_type compare
2089 if (compare (elem (n-1), elem (0)))
2104template <
typename T,
typename Alloc>
2122template <
typename T,
typename Alloc>
2131 if (r <= 1 || c == 0)
2137 compare_fcn_type compare
2141 for (i = 0; i < cols (); i++)
2144 T u = elem (rows () - 1, i);
2155 else if (compare (u, l))
2166 if (mode ==
UNSORTED && i == cols ())
2183template <
typename T,
typename Alloc>
2201 return lsort.
lookup (data (), n, value);
2204template <
typename T,
typename Alloc>
2226 static const double RATIO = 1.0;
2230 if (nval > RATIO * n / octave::math::log2 (n + 1.0))
2234 if ((vmode ==
ASCENDING && sort_isnan<T> (values(nval-1)))
2235 || (vmode ==
DESCENDING && sort_isnan<T> (values(0))))
2241 idx.
rwdata (), vmode != mode);
2248template <
typename T,
typename Alloc>
2252 const T *src = data ();
2255 const T zero = T ();
2263template <
typename T,
typename Alloc>
2268 const T *src = data ();
2270 const T zero = T ();
2271 if (n < 0 || n >= nel)
2277 cnt += src[i] != zero;
2279 retval.
clear (cnt, 1);
2282 if (src[i] != zero) *dest++ = i;
2289 retval.
clear (n, 1);
2297 for (; l >= 0 && src[l] == zero; l--) ;
2306 std::reverse (rdata, rdata + k);
2315 for (; l != nel && src[l] == zero; l++) ;
2336 || (rows () == 0 && dims ().
numel (1) == 0))
2338 else if (rows () == 1 && ndims () == 2)
2344template <
typename T,
typename Alloc>
2349 (*current_liboctave_error_handler) (
"nth_element: invalid dimension");
2352 if (dim >= dv.ndims ())
2353 dv.resize (dim+1, 1);
2359 dv(dim) = std::min (nn, ns);
2360 dv.chop_trailing_singletons ();
2371 switch (n.idx_class ())
2373 case octave::idx_vector::class_scalar:
2377 case octave::idx_vector::class_range:
2392 case octave::idx_vector::class_vector:
2395 if (n(1) - n(0) == 1)
2400 else if (n(1) - n(0) == -1)
2407 if ((mode ==
ASCENDING && n(i) - n(i-1) != 1)
2408 || (mode ==
DESCENDING && n(i) - n(i-1) != -1))
2416 (*current_liboctave_error_handler)
2417 (
"nth_element: n must be a scalar or a contiguous range");
2421 if (lo < 0 || up > ns)
2422 (*current_liboctave_error_handler) (
"nth_element: invalid element index");
2427 for (
int i = 0; i < dim; i++)
2431 const T *ov = data ();
2449 if (sort_isnan<T> (tmp))
2463 T tmp = ov[offset + i*stride];
2464 if (sort_isnan<T> (tmp))
2470 if (offset == stride-1)
2477 lsort.
nth_element (buf, ku, lo, std::min (ku, up));
2482 lsort.
nth_element (buf, ku, std::max (lo - nnan, zero),
2483 std::max (up - nnan, zero));
2484 std::rotate (buf, buf + ku, buf + ns);
2498 v[offset + stride * i] = buf[lo + i];
2499 if (offset == stride-1)
2507#define NO_INSTANTIATE_ARRAY_SORT_API(T, API) \
2508 template <> API Array<T> \
2509 Array<T>::sort (int, sortmode) const \
2513 template <> API Array<T> \
2514 Array<T>::sort (Array<octave_idx_type> &sidx, int, sortmode) const \
2516 sidx = Array<octave_idx_type> (); \
2519 template <> API sortmode \
2520 Array<T>::issorted (sortmode) const \
2524 API Array<T>::compare_fcn_type \
2525 safe_comparator (sortmode, const Array<T>&, bool) \
2529 template <> API Array<octave_idx_type> \
2530 Array<T>::sort_rows_idx (sortmode) const \
2532 return Array<octave_idx_type> (); \
2534 template <> API sortmode \
2535 Array<T>::is_sorted_rows (sortmode) const \
2539 template <> API octave_idx_type \
2540 Array<T>::lookup (T const &, sortmode) const \
2544 template <> API Array<octave_idx_type> \
2545 Array<T>::lookup (const Array<T>&, sortmode) const \
2547 return Array<octave_idx_type> (); \
2549 template <> API octave_idx_type \
2550 Array<T>::nnz () const \
2554 template <> API Array<octave_idx_type> \
2555 Array<T>::find (octave_idx_type, bool) const \
2557 return Array<octave_idx_type> (); \
2559 template <> API Array<T> \
2560 Array<T>::nth_element (const octave::idx_vector&, int) const { \
2561 return Array<T> (); \
2564#define NO_INSTANTIATE_ARRAY_SORT(T) NO_INSTANTIATE_ARRAY_SORT_API (T,)
2566template <
typename T,
typename Alloc>
2575 (*current_liboctave_error_handler) (
"Matrix must be 2-dimensional");
2580 if (nnr == 0 && nnc == 0)
2582 else if (nnr != 1 && nnc != 1)
2590 if (nnr > 0 && nnc > 0)
2599 d.xelem (i) = elem (i, i+k);
2604 d.xelem (i) = elem (i-k, i);
2609 d.xelem (i) = elem (i, i);
2637 d.xelem (i+roff, i+coff) = elem (0, i);
2645 d.xelem (i+roff, i+coff) = elem (i, 0);
2652template <
typename T,
typename Alloc>
2656 if (ndims () != 2 || (rows () != 1 && cols () != 1))
2657 (*current_liboctave_error_handler) (
"cat: invalid dimension");
2663 retval.xelem (i, i) = xelem (i);
2668template <
typename T,
typename Alloc>
2675 if (dim == -1 || dim == -2)
2681 (*current_liboctave_error_handler) (
"cat: invalid dimension");
2684 return array_list[0];
2711 if (n > 2 && dim > 1)
2731 if (! (dv.*concat_rule) (array_list[i].
dims (), dim))
2732 (*current_liboctave_error_handler) (
"cat: dimension mismatch");
2736 if (retval.isempty ())
2751 if (array_list[i].isempty ())
2757 if (dim < array_list[i].ndims ())
2758 u = l + array_list[i].
dims ()(dim);
2762 idxa(dim) = octave::idx_vector (l, u);
2764 retval.assign (idxa, array_list[i]);
2772template <
typename T,
typename Alloc>
2776 os << prefix <<
"m_rep address: " << m_rep <<
'\n'
2777 << prefix <<
"m_rep->m_len: " << m_rep->m_len <<
'\n'
2778 << prefix <<
"m_rep->m_data: " <<
static_cast<void *
> (m_rep->m_data) <<
'\n'
2779 << prefix <<
"m_rep->m_count: " << m_rep->m_count <<
'\n'
2780 << prefix <<
"m_slice_data: " <<
static_cast<void *
> (m_slice_data) <<
'\n'
2781 << prefix <<
"m_slice_len: " << m_slice_len <<
'\n';
2789template <
typename T,
typename Alloc>
2793 bool retval = m_dimensions == dv;
2800template <
typename T,
typename Alloc>
2809#define INSTANTIATE_ARRAY(T, API) \
2810 template <> API void \
2811 Array<T>::instantiation_guard () { } \
2813 template class API Array<T>
2817template <
typename T,
typename Alloc>
2823 int n_dims = a_dims.
ndims ();
2825 os << n_dims <<
"-dimensional array";
2828 os <<
" (" << a_dims.
str () <<
')';
2841 for (
int i = 2; i < n_dims; i++)
2885 for (
int i = 0; i < m; i++)
2889 for (
int j = 2; j < n_dims - 1; j++)
2890 os <<
ra_idx(j) + 1 <<
',';
2892 os <<
ra_idx(n_dims - 1) + 1 <<
") = \n";
bool sort_isnan(typename ref_param< T >::type)
Array< T, Alloc >::compare_fcn_type safe_comparator(sortmode mode, const Array< T, Alloc > &, bool)
std::ostream & operator<<(std::ostream &os, const Array< T, Alloc > &a)
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
dim_vector zero_dims_inquire(const Array< octave::idx_vector > &ia, const dim_vector &rhdv)
void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension)
The real representation of all arrays.
octave::refcount< octave_idx_type > m_count
N Dimensional Array with copy-on-write semantics.
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Array< T, Alloc >::ArrayRep * m_rep
T & xelem(octave_idx_type n)
Size of the specified dimension.
Array< T, Alloc > index(const octave::idx_vector &i) const
Indexing without resizing.
friend class Array
Size of the specified dimension.
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.
Array< T, Alloc > nth_element(const octave::idx_vector &n, int dim=0) const
Returns the n-th element in increasing order, using the same ordering as used for sort.
octave_idx_type compute_index_unchecked(const Array< octave_idx_type > &ra_idx) const
Size of the specified dimension.
Array< T, Alloc > hermitian(T(*fcn)(const T &)=nullptr) const
Size of the specified dimension.
void resize1(octave_idx_type n, const T &rfv)
Size of the specified dimension.
T & elem(octave_idx_type n)
Size of the specified dimension.
int ndims() const
Size of the specified dimension.
ref_param< T >::type crefT
Array< T, Alloc > column(octave_idx_type k) const
Extract column: A(:,k+1).
Array< T, Alloc > linear_slice(octave_idx_type lo, octave_idx_type up) const
Extract a slice from this array as a column vector: A(:)(lo+1:up).
bool optimize_dimensions(const dim_vector &dv)
Returns true if this->dims () == dv, and if so, replaces this->m_dimensions by a shallow copy of dv.
octave_idx_type nnz() const
Count nonzero elements.
octave_idx_type rows() const
Array< T, Alloc > page(octave_idx_type k) const
Extract page: A(:,:,k+1).
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Array< T, Alloc > & insert(const Array< T, Alloc > &a, const Array< octave_idx_type > &idx)
Insert an array into another at a specified position.
Array< T, Alloc > squeeze() const
Chop off leading singleton dimensions.
octave_idx_type dim2() const
octave_idx_type columns() const
void delete_elements(const octave::idx_vector &i)
Deleting elements.
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Sort by rows returns only indices.
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
octave_idx_type dim1() const
Array< T, Alloc > permute(const Array< octave_idx_type > &vec, bool inv=false) const
Size of the specified dimension.
Array< T, Alloc > sort(int dim=0, sortmode mode=ASCENDING) const
Size of the specified dimension.
Array< T, Alloc > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
bool isempty() const
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
void print_info(std::ostream &os, const std::string &prefix) const
Size of the specified dimension.
sortmode issorted(sortmode mode=UNSORTED) const
Ordering is auto-detected or can be specified.
T * rwdata()
Size of the specified dimension.
T & checkelem(octave_idx_type n)
Size of the specified dimension.
sortmode is_sorted_rows(sortmode mode=UNSORTED) const
Ordering is auto-detected or can be specified.
Array< T, Alloc > diag(octave_idx_type k=0) const
Get the kth super or subdiagonal.
virtual T resize_fill_value() const
Size of the specified dimension.
octave_idx_type compute_index(octave_idx_type i, octave_idx_type j) const
Size of the specified dimension.
octave_idx_type lookup(const T &value, sortmode mode=UNSORTED) const
Do a binary lookup in a sorted array.
void resize2(octave_idx_type nr, octave_idx_type nc, const T &rfv)
Resizing (with fill).
static Array< T, Alloc > cat(int dim, octave_idx_type n, const Array< T, Alloc > *array_list)
Concatenation along a specified (0-based) dimension, equivalent to cat().
octave_idx_type numel() const
Number of elements in the array.
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 chop_trailing_singletons()
void resize(int n, int fill_value=0)
static dim_vector alloc(int n)
bool is_nd_vector() const
octave_idx_type ndims() const
Number of dimensions.
void chop_all_singletons()
bool zero_by_zero() const
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 ().
dim_vector make_nd_vector(octave_idx_type n) const
virtual octave_idx_type numel() const
void set_compare(const compare_fcn_type &comp)
void sort_rows(const T *data, octave_idx_type *idx, octave_idx_type rows, octave_idx_type cols)
static bool descending_compare(typename ref_param< T >::type, typename ref_param< T >::type)
bool issorted(const T *data, octave_idx_type nel)
octave_idx_type lookup(const T *data, octave_idx_type nel, const T &value)
void sort(T *data, octave_idx_type nel)
void nth_element(T *data, octave_idx_type nel, octave_idx_type lo, octave_idx_type up=-1)
bool is_sorted_rows(const T *data, octave_idx_type rows, octave_idx_type cols)
void lookup_sorted(const T *data, octave_idx_type nel, const T *values, octave_idx_type nvalues, octave_idx_type *idx, bool rev=false)
if_then_else< is_class_type< T >::no, T, Tconst & >::result type
#define liboctave_panic_unless(cond)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
#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