26#if defined (HAVE_CONFIG_H)
47OCTAVE_NORETURN
static void err_invalid_range ()
49 (*current_liboctave_error_handler) (
"invalid range used as index");
52OCTAVE_NORETURN
static void
53err_index_out_of_range ()
55 (*current_liboctave_error_handler)
56 (
"internal error: idx_vector index out of range");
59idx_vector::idx_vector_rep *
62 static idx_vector_rep ivr;
67idx_vector::idx_base_rep::as_array ()
69 (*current_liboctave_error_handler)
70 (
"internal error: as_array not allowed for this index class");
76idx_vector::idx_colon_rep::idx_colon_rep (
char c)
80 (*current_liboctave_error_handler)
81 (
"internal error: invalid character converted to idx_vector; must be ':'");
88 err_index_out_of_range ();
93idx_vector::idx_base_rep *
96 (*current_liboctave_error_handler)
97 (
"internal error: idx_colon_rep::sort_idx");
101idx_vector::idx_colon_rep::print (std::ostream& os)
const
109 : idx_base_rep (), m_start(start),
112 ? std::
max ((limit - start + step - (step > 0 ? 1 : -1)) / step,
118 err_invalid_range ();
121 if (m_step < 0 && m_start + (m_len-1)*m_step < 0)
125idx_vector::idx_range_rep::idx_range_rep (
const range<double>& r)
126 : idx_base_rep (), m_start (0), m_len (r.
numel ()), m_step (1)
129 err_invalid_range ();
139 if (m_step < 0 && m_start + (m_len - 1)*m_step < 0)
145 double b = r.base ();
146 double inc = r.increment ();
155 if (i < 0 || i >= m_len)
156 err_index_out_of_range ();
158 return m_start + i*m_step;
161idx_vector::idx_base_rep *
162idx_vector::idx_range_rep::sort_uniq_clone (
bool)
165 return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);
173idx_vector::idx_base_rep *
176 if (m_step < 0 && m_len > 0)
178 idx.
clear (1, m_len);
180 idx.
xelem (i) = m_len - 1 - i;
181 return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);
185 idx.
clear (1, m_len);
194idx_vector::idx_range_rep::print (std::ostream& os)
const
196 os << m_start <<
':' << m_step <<
':' << m_start + m_len *m_step;
201idx_vector::idx_range_rep::unconvert ()
const
204 (
static_cast<double> (m_start+1),
static_cast<double> (m_step), m_len);
208idx_vector::idx_range_rep::as_array ()
212 retval.xelem (i) = m_start + i*m_step;
234 if (
static_cast<double> (i) !=
x)
256idx_vector::idx_scalar_rep::idx_scalar_rep (T
x)
257 : idx_base_rep (), m_data (0)
265 : idx_base_rep (), m_data (i)
275 err_index_out_of_range ();
280idx_vector::idx_base_rep *
290idx_vector::idx_scalar_rep::print (std::ostream& os)
const
296idx_vector::idx_scalar_rep::unconvert ()
const
302idx_vector::idx_scalar_rep::as_array ()
308idx_vector::idx_vector_rep::idx_vector_rep (
const Array<T>& nda)
309 : idx_base_rep (), m_data (nullptr), m_len (nda.
numel ()), m_ext (0),
310 m_aowner (nullptr), m_orig_dims (nda.dims ())
319 m_data =
d.release ();
326 : idx_base_rep (), m_data (inda.data ()), m_len (inda.
numel ()), m_ext (0),
347 : idx_base_rep (), m_data (inda.data ()), m_len (inda.
numel ()),
349 m_orig_dims (inda.dims ())
363idx_vector::idx_vector_rep::idx_vector_rep (
bool b)
364 : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),
365 m_aowner (nullptr), m_orig_dims (m_len, m_len)
376idx_vector::idx_vector_rep::idx_vector_rep (
const Array<bool>& bnda,
378 : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (0),
379 m_aowner (nullptr), m_orig_dims ()
405idx_vector::idx_vector_rep::idx_vector_rep (
const Sparse<bool>& bnda)
406 : idx_base_rep (), m_data (nullptr), m_len (bnda.nnz ()), m_ext (0),
407 m_aowner (nullptr), m_orig_dims ()
424 d[k++] = j * nr + bnda.
ridx (i);
432idx_vector::idx_vector_rep::~idx_vector_rep ()
443 if (n < 0 || n >= m_len)
449idx_vector::idx_base_rep *
450idx_vector::idx_vector_rep::sort_uniq_clone (
bool uniq)
459 std::unique_ptr<idx_vector_rep> new_rep
460 (
new idx_vector_rep (
nullptr, m_len, m_ext, m_orig_dims, DIRECT));
462 if (m_ext > m_len*math::log2 (1.0 + m_len))
466 new_rep->m_data = new_data;
468 std::copy_n (m_data, m_len, new_data);
471 lsort.
sort (new_data, m_len);
477 new_rep->m_len = new_len;
478 if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)
479 new_rep->m_orig_dims =
dim_vector (1, new_len);
481 new_rep->m_orig_dims =
dim_vector (new_len, 1);
489 has[m_data[i]] =
true;
495 new_rep->m_len = new_len;
496 if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)
497 new_rep->m_orig_dims =
dim_vector (1, new_len);
499 new_rep->m_orig_dims =
dim_vector (new_len, 1);
502 new_rep->m_data = new_data;
516 new_rep->m_data = new_data;
525 return new_rep.release ();
528idx_vector::idx_base_rep *
532 std::unique_ptr<idx_vector_rep> new_rep
533 (
new idx_vector_rep (
nullptr, m_len, m_ext, m_orig_dims, DIRECT));
535 if (m_ext > m_len*math::log2 (1.0 + m_len))
538 idx.
clear (m_orig_dims);
544 new_rep->m_data = new_data;
545 std::copy_n (m_data, m_len, new_data);
549 lsort.
sort (new_data, idx_data, m_len);
559 idx.
clear (m_orig_dims);
563 new_rep->m_data = new_data;
581 return new_rep.release ();
585idx_vector::idx_vector_rep::print (std::ostream& os)
const
590 os << m_data[i] <<
',' <<
' ';
593 os << m_data[m_len-1];
601idx_vector::idx_vector_rep::unconvert ()
const
605 retval.xelem (i) = m_data[i] + 1;
610idx_vector::idx_vector_rep::as_array ()
620 std::memcpy (retval.rwdata (), m_data, m_len* sizeof (
octave_idx_type));
625 m_data = retval.rwdata ();
632idx_vector::idx_mask_rep::idx_mask_rep (
bool b)
633 : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),
634 m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (m_len, m_len)
638 bool *
d =
new bool [1];
645idx_vector::idx_mask_rep::idx_mask_rep (
const Array<bool>& bnda,
647 : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (bnda.
numel ()),
648 m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims ()
655 while (m_ext > 0 && ! bnda(m_ext-1))
663 m_data = bnda.
data ();
666idx_vector::idx_mask_rep::~idx_mask_rep ()
680 while (! m_data[++m_lste]) ;
687 if (m_data[++m_lste]) --n;
695 if (n < 0 || n >= m_len)
702idx_vector::idx_mask_rep::print (std::ostream& os)
const
707 os << m_data[i] <<
',' <<
' ';
710 os << m_data[m_ext-1];
718idx_vector::idx_mask_rep::unconvert ()
const
726 retval.xelem (i) = m_data[i];
732idx_vector::idx_mask_rep::as_array ()
741 retval.xelem (j++) = i;
747idx_vector::idx_base_rep *
750 idx.
clear (m_len, 1);
766 if (nnz <= bnda.
numel () / factor)
767 m_rep =
new idx_vector_rep (bnda, nnz);
769 m_rep =
new idx_mask_rep (bnda, nnz);
776 bool reduced =
false;
779 if (m_rep->length (n) == 0)
786 if (n == 1 && m_rep->is_colon_equiv (n))
798 switch (m_rep->idx_class ())
808 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
810 *
this =
new idx_range_rep (k, nj, n, DIRECT);
818 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
824 *
this =
new idx_range_rep (s, l * nj, t, DIRECT);
836 switch (m_rep->idx_class ())
841 idx_range_rep *rj =
dynamic_cast<idx_range_rep *
> (j.m_rep);
842 if (rj->get_step () == 1)
846 *
this =
new idx_range_rep (sj * n, lj * n, 1, DIRECT);
855 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
856 idx_range_rep *rj =
dynamic_cast<idx_range_rep *
> (j.m_rep);
861 *
this =
new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
870 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
874 idx_range_rep *rj =
dynamic_cast<idx_range_rep *
> (j.m_rep);
878 if ((l*t == n && tj == 1) || (t == 0 && tj == 0))
880 *
this =
new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
892 switch (m_rep->idx_class ())
897 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
898 idx_scalar_rep *rj =
dynamic_cast<idx_scalar_rep *
> (j.m_rep);
900 *
this =
new idx_scalar_rep (k, DIRECT);
908 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
909 idx_scalar_rep *rj =
dynamic_cast<idx_scalar_rep *
> (j.m_rep);
914 *
this =
new idx_range_rep (n * k + s, l, t, DIRECT);
922 idx_scalar_rep *rj =
dynamic_cast<idx_scalar_rep *
> (j.m_rep);
924 *
this =
new idx_range_rep (n * k, n, 1, DIRECT);
947 switch (m_rep->idx_class ())
956 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
957 if (r->get_step () == 1)
960 u = l + r->length (n);
968 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
977 idx_mask_rep *r =
dynamic_cast<idx_mask_rep *
> (m_rep);
1000 switch (m_rep->idx_class ())
1007 retval =
dynamic_cast<idx_range_rep *
> (m_rep) -> get_step ();
1031 idx_vector_rep *r =
dynamic_cast<idx_vector_rep *
> (m_rep);
1035 return r->get_data ();
1043 switch (m_rep->idx_class ())
1046 (*current_liboctave_error_handler) (
"unexpected: invalid index");
1050 (*current_liboctave_error_handler) (
"colon not allowed");
1055 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
1060 for (i = m_start, j = m_start + m_len; i < j; i++) *m_data++ = i;
1061 else if (m_step == -1)
1062 for (i = m_start, j = m_start - m_len; i > j; i--) *m_data++ = i;
1064 for (i = 0, j = m_start; i < m_len; i++, j += m_step) *m_data++ = j;
1070 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
1071 *m_data = r->get_data ();
1077 idx_vector_rep *r =
dynamic_cast<idx_vector_rep *
> (m_rep);
1079 std::copy_n (rdata, m_len, m_data);
1085 idx_mask_rep *r =
dynamic_cast<idx_mask_rep *
> (m_rep);
1086 const bool *mask = r->get_data ();
1105 (*current_liboctave_error_handler)
1106 (
"internal error: out of range complement index requested");
1110 idx_mask_rep *r =
dynamic_cast<idx_mask_rep *
> (m_rep);
1114 const bool *m_data = r->get_data ();
1115 bool *ndata = mask.
rwdata ();
1117 ndata[i] = ! m_data[i];
1118 std::fill_n (ndata + m_ext, n - m_ext,
true);
1119 retval =
new idx_mask_rep (mask, n - nz);
1134 bool retval =
false;
1179 idx_vector_rep *r =
dynamic_cast<idx_vector_rep *
> (m_rep);
1183 idx.
xelem (ri[i]) = i;
1184 retval =
new idx_vector_rep (idx, r->extent (0), DIRECT);
1200 idx_mask_rep *r =
dynamic_cast<idx_mask_rep *
> (m_rep);
1201 const bool *m_data = r->get_data ();
1210 m_ext = (m_len > 0 ? idata[m_len - 1] + 1 : 0);
1212 return new idx_vector_rep (idata, m_len, m_ext, r->orig_dimensions (),
1228 (*current_liboctave_error_handler) (
"unexpected: invalid index");
1236 idx_range_rep *r =
dynamic_cast<idx_range_rep *
> (m_rep);
1237 range = r->unconvert ();
1243 idx_scalar_rep *r =
dynamic_cast<idx_scalar_rep *
> (m_rep);
1244 scalar = r->unconvert ();
1250 idx_vector_rep *r =
dynamic_cast<idx_vector_rep *
> (m_rep);
1251 array = r->unconvert ();
1257 idx_mask_rep *r =
dynamic_cast<idx_mask_rep *
> (m_rep);
1258 mask = r->unconvert ();
1271 return m_rep->as_array ();
1283 if (! resize_ok &&
extent (z_len) > z_len)
1284 (*current_liboctave_error_handler)
1285 (
"invalid matrix index = %" OCTAVE_IDX_TYPE_FORMAT,
extent (z_len));
1308#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \
1309 template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \
1310 template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);
1323OCTAVE_END_NAMESPACE(octave)
charNDArray max(char d, const charNDArray &m)
N Dimensional Array with copy-on-write semantics.
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
T & xelem(octave_idx_type n)
Size of the specified dimension.
octave_idx_type nnz() const
Count nonzero elements.
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
Array< T, Alloc > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
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 cols() const
octave_idx_type rows() const
Vector representing the dimensions (size) of an Array.
dim_vector make_nd_vector(octave_idx_type n) const
idx_vector unmask() const
octave_idx_type xelem(octave_idx_type n) const
idx_class_type idx_class() const
octave_idx_type ones_count() const
idx_vector sorted(bool uniq=false) const
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
static const idx_vector colon
dim_vector orig_dimensions() const
bool maybe_reduce(octave_idx_type n, const idx_vector &j, octave_idx_type nj)
void copy_data(octave_idx_type *data) const
void unconvert(idx_class_type &iclass, double &scalar, range< double > &range, Array< double > &array, Array< bool > &mask) const
octave_idx_type length(octave_idx_type n=0) const
octave_idx_type elem(octave_idx_type n) const
octave_idx_type freeze(octave_idx_type z_len, const char *tag, bool resize_ok=false)
bool is_cont_range(octave_idx_type n, octave_idx_type &l, octave_idx_type &u) const
idx_vector complement(octave_idx_type n) const
Array< octave_idx_type > as_array() const
bool is_permutation(octave_idx_type n) const
idx_vector inverse_permutation(octave_idx_type n) const
octave_idx_type increment() const
octave_idx_type extent(octave_idx_type n) const
const octave_idx_type * raw()
bool is_colon_equiv(octave_idx_type n) const
void set_compare(const compare_fcn_type &comp)
void sort(T *data, octave_idx_type nel)
bool all_elements_are_ints() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T)
octave_idx_type convert_index(octave_idx_type i, octave_idx_type &ext)
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
#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_INIT(T, buf, size, value)
T::size_type numel(const T &str)