GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
idx-vector.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cinttypes>
31 #include <cstdlib>
32 
33 #include <ostream>
34 
35 #include "idx-vector.h"
36 #include "Array.h"
37 #include "Array-util.h"
38 #include "Sparse.h"
39 #include "Range.h"
40 
41 #include "oct-locbuf.h"
42 #include "lo-error.h"
43 #include "lo-mappers.h"
44 
45 OCTAVE_NORETURN static
46 void
48 {
49  (*current_liboctave_error_handler) ("invalid range used as index");
50 }
51 
52 static void
54 {
55  (*current_liboctave_error_handler)
56  ("internal error: idx_vector index out of range");
57 }
58 
61 {
62  static idx_vector_rep ivr;
63  return &ivr;
64 }
65 
68 {
69  static idx_vector_rep ivr;
70  ivr.err = true;
71  return &ivr;
72 }
73 
76 {
77  (*current_liboctave_error_handler)
78  ("internal error: as_array not allowed for this index class");
79 
80  // Never actually executed, but required to silence compiler warning
81  return Array<octave_idx_type> ();
82 }
83 
85  : idx_base_rep ()
86 {
87  if (c != ':')
88  {
89  (*current_liboctave_error_handler)
90  ("internal error: invalid character converted to idx_vector; must be ':'");
91  // FIXME: this is unreachable now.
92  err = true;
93  }
94 }
95 
98 {
99  if (i < 0)
101 
102  return i;
103 }
104 
107 {
108  (*current_liboctave_error_handler)
109  ("internal error: idx_colon_rep::sort_idx");
110 }
111 
112 std::ostream&
113 idx_vector::idx_colon_rep::print (std::ostream& os) const
114 {
115  return os << ':';
116 }
117 
119  octave_idx_type _limit,
120  octave_idx_type _step)
121  : idx_base_rep (), start(_start),
122  len (_step ? std::max ((_limit - _start) / _step,
123  static_cast<octave_idx_type> (0))
124  : -1),
125  step (_step)
126 {
127  if (len < 0)
129  if (start < 0)
131  if (step < 0 && start + (len-1)*step < 0)
133 }
134 
136  : idx_base_rep (), start (0), len (r.numel ()), step (1)
137 {
138  if (len < 0)
140 
141  if (len > 0)
142  {
143  if (r.all_elements_are_ints ())
144  {
145  start = static_cast<octave_idx_type> (r.base ()) - 1;
146  step = static_cast<octave_idx_type> (r.inc ());
147  if (start < 0)
149  if (step < 0 && start + (len - 1)*step < 0)
151  }
152  else
153  {
154  // find first non-integer, then gripe about it
155  double b = r.base ();
156  double inc = r.inc ();
157  octave::err_invalid_index (b != std::trunc (b) ? b : b + inc);
158  }
159  }
160 }
161 
164 {
165  if (i < 0 || i >= len)
167 
168  return start + i*step;
169 }
170 
173 {
174  if (step < 0)
175  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
176  else
177  {
178  count++;
179  return this;
180  }
181 }
182 
185 {
186  if (step < 0 && len > 0)
187  {
188  idx.clear (1, len);
189  for (octave_idx_type i = 0; i < len; i++)
190  idx.xelem (i) = len - 1 - i;
191  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
192  }
193  else
194  {
195  idx.clear (1, len);
196  for (octave_idx_type i = 0; i < len; i++)
197  idx.xelem (i) = i;
198  count++;
199  return this;
200  }
201 }
202 
203 std::ostream&
204 idx_vector::idx_range_rep::print (std::ostream& os) const
205 {
206  os << start << ':' << step << ':' << start + len*step;
207  return os;
208 }
209 
210 Range
212 {
213  return Range (static_cast<double> (start+1),
214  static_cast<double> (step), len);
215 }
216 
219 {
221  for (octave_idx_type i = 0; i < len; i++)
222  retval.xelem (i) = start + i*step;
223 
224  return retval;
225 }
226 
227 inline octave_idx_type
228 convert_index (octave_idx_type i, bool& conv_error,
229  octave_idx_type& ext)
230 {
231  if (i <= 0 && ! conv_error)
233 
234  if (ext < i)
235  ext = i;
236 
237  return i - 1;
238 }
239 
240 inline octave_idx_type
241 convert_index (double x, bool& conv_error, octave_idx_type& ext)
242 {
243  octave_idx_type i = static_cast<octave_idx_type> (x);
244 
245  if (static_cast<double> (i) != x)
247 
248  return convert_index (i, conv_error, ext);
249 }
250 
251 inline octave_idx_type
252 convert_index (float x, bool& conv_error, octave_idx_type& ext)
253 {
254  return convert_index (static_cast<double> (x), conv_error, ext);
255 }
256 
257 template <typename T>
258 inline octave_idx_type
259 convert_index (octave_int<T> x, bool& conv_error,
260  octave_idx_type& ext)
261 {
263 
264  return convert_index (i, conv_error, ext);
265 }
266 
267 template <typename T>
269  : idx_base_rep (), data (0)
270 {
271  octave_idx_type dummy = 0;
272 
273  data = convert_index (x, err, dummy);
274 }
275 
277  : idx_base_rep (), data (i)
278 {
279  if (data < 0)
281 }
282 
285 {
286  if (i != 0)
288 
289  return data;
290 }
291 
294 {
295  idx.clear (1, 1);
296  idx.fill (0);
297  count++;
298  return this;
299 }
300 
301 std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const
302 {
303  return os << data;
304 }
305 
306 double
308 {
309  return data + 1;
310 }
311 
314 {
315  return Array<octave_idx_type> (dim_vector (1, 1), data);
316 }
317 
318 template <typename T>
320  : idx_base_rep (), data (nullptr), len (nda.numel ()), ext (0),
321  aowner (nullptr), orig_dims (nda.dims ())
322 {
323  if (len != 0)
324  {
325  std::unique_ptr<octave_idx_type []> d (new octave_idx_type [len]);
326 
327  for (octave_idx_type i = 0; i < len; i++)
328  d[i] = convert_index (nda.xelem (i), err, ext);
329 
330  data = d.release ();
331  }
332 }
333 
334 // Note that this makes a shallow copy of the index array.
335 
337  : idx_base_rep (), data (inda.data ()), len (inda.numel ()), ext (0),
338  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
339 {
340  if (len != 0)
341  {
342  octave_idx_type max = -1;
343  for (octave_idx_type i = 0; i < len; i++)
344  {
345  octave_idx_type k = inda.xelem (i);
346  if (k < 0)
347  {
348  if (! err)
350  }
351  else if (k > max)
352  max = k;
353  }
354 
355  ext = max + 1;
356  }
357 }
358 
360  octave_idx_type _ext, direct)
361  : idx_base_rep (), data (inda.data ()), len (inda.numel ()), ext (_ext),
362  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
363 {
364  // No checking.
365  if (ext < 0)
366  {
367  octave_idx_type max = -1;
368  for (octave_idx_type i = 0; i < len; i++)
369  if (data[i] > max)
370  max = data[i];
371 
372  ext = max + 1;
373  }
374 }
375 
377  : idx_base_rep (), data (nullptr), len (b ? 1 : 0), ext (0),
378  aowner (nullptr), orig_dims (len, len)
379 {
380  if (len != 0)
381  {
382  octave_idx_type *d = new octave_idx_type [1];
383  d[0] = 0;
384  data = d;
385  ext = 1;
386  }
387 }
388 
390  octave_idx_type nnz)
391  : idx_base_rep (), data (nullptr), len (nnz), ext (0), aowner (nullptr),
392  orig_dims ()
393 {
394  if (nnz < 0)
395  len = bnda.nnz ();
396 
397  const dim_vector dv = bnda.dims ();
398 
400 
401  if (len != 0)
402  {
404 
405  octave_idx_type ntot = bnda.numel ();
406 
407  octave_idx_type k = 0;
408  for (octave_idx_type i = 0; i < ntot; i++)
409  if (bnda.xelem (i))
410  d[k++] = i;
411 
412  data = d;
413 
414  ext = d[k-1] + 1;
415  }
416 }
417 
419  : idx_base_rep (), data (nullptr), len (bnda.nnz ()), ext (0),
420  aowner (nullptr), orig_dims ()
421 {
422  const dim_vector dv = bnda.dims ();
423 
425 
426  if (len != 0)
427  {
429 
430  octave_idx_type k = 0;
431  octave_idx_type nc = bnda.cols ();
432  octave_idx_type nr = bnda.rows ();
433 
434  for (octave_idx_type j = 0; j < nc; j++)
435  for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++)
436  if (bnda.data (i))
437  d[k++] = j * nr + bnda.ridx (i);
438 
439  data = d;
440 
441  ext = d[k-1] + 1;
442  }
443 }
444 
446 {
447  if (aowner)
448  delete aowner;
449  else
450  delete [] data;
451 }
452 
455 {
456  if (n < 0 || n >= len)
458 
459  return xelem (n);
460 }
461 
464 {
465  if (len == 0)
466  {
467  count++;
468  return this;
469  }
470 
471  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
472  std::unique_ptr<idx_vector_rep> new_rep
473  (new idx_vector_rep (nullptr, len, ext, orig_dims, DIRECT));
474 
475  if (ext > len*octave::math::log2 (1.0 + len))
476  {
477  // Use standard sort via octave_sort.
478  octave_idx_type *new_data = new octave_idx_type [len];
479  new_rep->data = new_data;
480 
481  std::copy_n (data, len, new_data);
483  lsort.set_compare (ASCENDING);
484  lsort.sort (new_data, len);
485 
486  if (uniq)
487  {
488  octave_idx_type new_len = std::unique (new_data, new_data + len)
489  - new_data;
490  new_rep->len = new_len;
491  if (new_rep->orig_dims.ndims () == 2 && new_rep->orig_dims(0) == 1)
492  new_rep->orig_dims = dim_vector (1, new_len);
493  else
494  new_rep->orig_dims = dim_vector (new_len, 1);
495  }
496  }
497  else if (uniq)
498  {
499  // Use two-pass bucket sort (only a mask array needed).
500  OCTAVE_LOCAL_BUFFER_INIT (bool, has, ext, false);
501  for (octave_idx_type i = 0; i < len; i++)
502  has[data[i]] = true;
503 
504  octave_idx_type new_len = 0;
505  for (octave_idx_type i = 0; i < ext; i++)
506  new_len += has[i];
507 
508  new_rep->len = new_len;
509  if (new_rep->orig_dims.ndims () == 2 && new_rep->orig_dims(0) == 1)
510  new_rep->orig_dims = dim_vector (1, new_len);
511  else
512  new_rep->orig_dims = dim_vector (new_len, 1);
513 
514  octave_idx_type *new_data = new octave_idx_type [new_len];
515  new_rep->data = new_data;
516 
517  for (octave_idx_type i = 0, j = 0; i < ext; i++)
518  if (has[i])
519  new_data[j++] = i;
520  }
521  else
522  {
523  // Use two-pass bucket sort.
525  for (octave_idx_type i = 0; i < len; i++)
526  cnt[data[i]]++;
527 
528  octave_idx_type *new_data = new octave_idx_type [len];
529  new_rep->data = new_data;
530 
531  for (octave_idx_type i = 0, j = 0; i < ext; i++)
532  {
533  for (octave_idx_type k = 0; k < cnt[i]; k++)
534  new_data[j++] = i;
535  }
536  }
537 
538  return new_rep.release ();
539 }
540 
543 {
544  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
545  std::unique_ptr<idx_vector_rep> new_rep
546  (new idx_vector_rep (nullptr, len, ext, orig_dims, DIRECT));
547 
548  if (ext > len*octave::math::log2 (1.0 + len))
549  {
550  // Use standard sort via octave_sort.
551  idx.clear (orig_dims);
552  octave_idx_type *idx_data = idx.fortran_vec ();
553  for (octave_idx_type i = 0; i < len; i++)
554  idx_data[i] = i;
555 
556  octave_idx_type *new_data = new octave_idx_type [len];
557  new_rep->data = new_data;
558  std::copy_n (data, len, new_data);
559 
561  lsort.set_compare (ASCENDING);
562  lsort.sort (new_data, idx_data, len);
563  }
564  else
565  {
566  // Use two-pass bucket sort.
568 
569  for (octave_idx_type i = 0; i < len; i++)
570  cnt[data[i]]++;
571 
572  idx.clear (orig_dims);
573  octave_idx_type *idx_data = idx.fortran_vec ();
574 
575  octave_idx_type *new_data = new octave_idx_type [len];
576  new_rep->data = new_data;
577 
578  for (octave_idx_type i = 0, k = 0; i < ext; i++)
579  {
580  octave_idx_type j = cnt[i];
581  cnt[i] = k;
582  k += j;
583  }
584 
585  for (octave_idx_type i = 0; i < len; i++)
586  {
587  octave_idx_type j = data[i];
588  octave_idx_type k = cnt[j]++;
589  new_data[k] = j;
590  idx_data[k] = i;
591  }
592  }
593 
594  return new_rep.release ();
595 }
596 
597 std::ostream&
598 idx_vector::idx_vector_rep::print (std::ostream& os) const
599 {
600  os << '[';
601 
602  for (octave_idx_type i = 0; i < len - 1; i++)
603  os << data[i] << ',' << ' ';
604 
605  if (len > 0)
606  os << data[len-1];
607 
608  os << ']';
609 
610  return os;
611 }
612 
615 {
616  Array<double> retval (orig_dims);
617  for (octave_idx_type i = 0; i < len; i++)
618  retval.xelem (i) = data[i] + 1;
619  return retval;
620 }
621 
624 {
625  if (aowner)
626  return *aowner;
627  else
628  {
629  Array<octave_idx_type> retval (orig_dims);
630 
631  if (data)
632  {
633  std::memcpy (retval.fortran_vec (), data, len*sizeof (octave_idx_type));
634  // Delete the old copy and share the data instead to save memory.
635  delete [] data;
636  }
637 
638  data = retval.fortran_vec ();
639  aowner = new Array<octave_idx_type> (retval);
640 
641  return retval;
642  }
643 }
644 
646  : idx_base_rep (), data (nullptr), len (b ? 1 : 0), ext (0),
647  lsti (-1), lste (-1), aowner (nullptr), orig_dims (len, len)
648 {
649  if (len != 0)
650  {
651  bool *d = new bool [1];
652  d[0] = true;
653  data = d;
654  ext = 1;
655  }
656 }
657 
659  octave_idx_type nnz)
660  : idx_base_rep (), data (nullptr), len (nnz), ext (bnda.numel ()),
661  lsti (-1), lste (-1), aowner (nullptr), orig_dims ()
662 {
663  if (nnz < 0)
664  len = bnda.nnz ();
665 
666  // We truncate the extent as much as possible. For Matlab
667  // compatibility, but maybe it's not a bad idea anyway.
668  while (ext > 0 && ! bnda(ext-1))
669  ext--;
670 
671  const dim_vector dv = bnda.dims ();
672 
674 
675  aowner = new Array<bool> (bnda);
676  data = bnda.data ();
677 }
678 
680 {
681  if (aowner)
682  delete aowner;
683  else
684  delete [] data;
685 }
686 
689 {
690  if (n == lsti + 1)
691  {
692  lsti = n;
693  while (! data[++lste]) ;
694  }
695  else
696  {
697  lsti = n++;
698  lste = -1;
699  while (n > 0)
700  if (data[++lste]) --n;
701  }
702  return lste;
703 }
704 
707 {
708  if (n < 0 || n >= len)
710 
711  return xelem (n);
712 }
713 
714 std::ostream&
715 idx_vector::idx_mask_rep::print (std::ostream& os) const
716 {
717  os << '[';
718 
719  for (octave_idx_type i = 0; i < ext - 1; i++)
720  os << data[i] << ',' << ' ';
721 
722  if (ext > 0)
723  os << data[ext-1];
724 
725  os << ']';
726 
727  return os;
728 }
729 
732 {
733  if (aowner)
734  return *aowner;
735  else
736  {
737  Array<bool> retval (dim_vector (ext, 1));
738  for (octave_idx_type i = 0; i < ext; i++)
739  retval.xelem (i) = data[i];
740  return retval;
741  }
742 }
743 
746 {
747  if (aowner)
748  return aowner->find ().reshape (orig_dims);
749  else
750  {
751  Array<bool> retval (orig_dims);
752  for (octave_idx_type i = 0, j = 0; i < ext; i++)
753  if (data[i])
754  retval.xelem (j++) = i;
755 
756  return retval;
757  }
758 }
759 
762 {
763  idx.clear (len, 1);
764  for (octave_idx_type i = 0; i < len; i++)
765  idx.xelem (i) = i;
766 
767  count++;
768  return this;
769 }
770 
772 
774  : rep (nullptr)
775 {
776  // Convert only if it means saving at least half the memory.
777  static const int factor = (2 * sizeof (octave_idx_type));
778  octave_idx_type nnz = bnda.nnz ();
779  if (nnz <= bnda.numel () / factor)
780  rep = new idx_vector_rep (bnda, nnz);
781  else
782  rep = new idx_mask_rep (bnda, nnz);
783 }
784 
785 bool
787  octave_idx_type nj)
788 {
789  bool reduced = false;
790 
791  // Empty index always reduces.
792  if (rep->length (n) == 0)
793  {
794  *this = idx_vector ();
795  return true;
796  }
797 
798  // Possibly skip singleton dims.
799  if (n == 1 && rep->is_colon_equiv (n))
800  {
801  *this = j;
802  return true;
803  }
804 
805  if (nj == 1 && j.is_colon_equiv (nj))
806  return true;
807 
808  switch (j.idx_class ())
809  {
810  case class_colon:
811  switch (rep->idx_class ())
812  {
813  case class_colon:
814  // (:,:) reduces to (:)
815  reduced = true;
816  break;
817 
818  case class_scalar:
819  {
820  // (i,:) reduces to a range.
821  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
822  octave_idx_type k = r->get_data ();
823  *this = new idx_range_rep (k, nj, n, DIRECT);
824  reduced = true;
825  }
826  break;
827 
828  case class_range:
829  {
830  // (i:k:end,:) reduces to a range if i <= k and k divides n.
831  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
832  octave_idx_type s = r->get_start ();
833  octave_idx_type l = r->length (n);
834  octave_idx_type t = r->get_step ();
835  if (l*t == n)
836  {
837  *this = new idx_range_rep (s, l * nj, t, DIRECT);
838  reduced = true;
839  }
840  }
841  break;
842 
843  default:
844  break;
845  }
846  break;
847 
848  case class_range:
849  switch (rep->idx_class ())
850  {
851  case class_colon:
852  {
853  // (:,i:j) reduces to a range (the step must be 1)
854  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
855  if (rj->get_step () == 1)
856  {
857  octave_idx_type sj = rj->get_start ();
858  octave_idx_type lj = rj->length (nj);
859  *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);
860  reduced = true;
861  }
862  }
863  break;
864 
865  case class_scalar:
866  {
867  // (k,i:d:j) reduces to a range.
868  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
869  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
870  octave_idx_type k = r->get_data ();
871  octave_idx_type sj = rj->get_start ();
872  octave_idx_type lj = rj->length (nj);
873  octave_idx_type tj = rj->get_step ();
874  *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
875  reduced = true;
876  }
877  break;
878 
879  case class_range:
880  {
881  // (i:k:end,p:q) reduces to a range if i <= k and k divides n.
882  // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n))
883  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
884  octave_idx_type s = r->get_start ();
885  octave_idx_type l = r->length (n);
886  octave_idx_type t = r->get_step ();
887  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
888  octave_idx_type sj = rj->get_start ();
889  octave_idx_type lj = rj->length (nj);
890  octave_idx_type tj = rj->get_step ();
891  if ((l*t == n && tj == 1) || (t == 0 && tj == 0))
892  {
893  *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
894  reduced = true;
895  }
896  }
897  break;
898 
899  default:
900  break;
901  }
902  break;
903 
904  case class_scalar:
905  switch (rep->idx_class ())
906  {
907  case class_scalar:
908  {
909  // (i,j) reduces to a single index.
910  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
911  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
912  octave_idx_type k = r->get_data () + n * rj->get_data ();
913  *this = new idx_scalar_rep (k, DIRECT);
914  reduced = true;
915  }
916  break;
917 
918  case class_range:
919  {
920  // (i:d:j,k) reduces to a range.
921  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
922  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
923  octave_idx_type s = r->get_start ();
924  octave_idx_type l = r->length (nj);
925  octave_idx_type t = r->get_step ();
926  octave_idx_type k = rj->get_data ();
927  *this = new idx_range_rep (n * k + s, l, t, DIRECT);
928  reduced = true;
929  }
930  break;
931 
932  case class_colon:
933  {
934  // (:,k) reduces to a range.
935  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
936  octave_idx_type k = rj->get_data ();
937  *this = new idx_range_rep (n * k, n, 1, DIRECT);
938  reduced = true;
939  }
940  break;
941 
942  default:
943  break;
944  }
945  break;
946 
947  default:
948  break;
949  }
950 
951  return reduced;
952 }
953 
954 bool
956  octave_idx_type& l, octave_idx_type& u) const
957 {
958  bool res = false;
959 
960  switch (rep->idx_class ())
961  {
962  case class_colon:
963  l = 0; u = n;
964  res = true;
965  break;
966 
967  case class_range:
968  {
969  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
970  if (r->get_step () == 1)
971  {
972  l = r->get_start ();
973  u = l + r->length (n);
974  res = true;
975  }
976  }
977  break;
978 
979  case class_scalar:
980  {
981  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
982  l = r->get_data ();
983  u = l + 1;
984  res = true;
985  }
986  break;
987 
988  case class_mask:
989  {
990  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
991  octave_idx_type ext = r->extent (0);
992  octave_idx_type len = r->length (0);
993  if (ext == len)
994  {
995  l = 0;
996  u = len;
997  res = true;
998  }
999  }
1000 
1001  default:
1002  break;
1003  }
1004 
1005  return res;
1006 }
1007 
1010 {
1011  octave_idx_type retval = 0;
1012 
1013  switch (rep->idx_class ())
1014  {
1015  case class_colon:
1016  retval = 1;
1017  break;
1018 
1019  case class_range:
1020  retval = dynamic_cast<idx_range_rep *> (rep) -> get_step ();
1021  break;
1022 
1023  case class_vector:
1024  case class_mask:
1025  {
1026  if (length (0) > 1)
1027  retval = elem (1) - elem (0);
1028  }
1029  break;
1030 
1031  default:
1032  break;
1033  }
1034 
1035  return retval;
1036 }
1037 
1038 const octave_idx_type *
1040 {
1041  if (rep->idx_class () != class_vector)
1042  *this = idx_vector (as_array (), extent (0));
1043 
1044  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1045 
1046  assert (r != nullptr);
1047 
1048  return r->get_data ();
1049 }
1050 
1051 void
1053 {
1054  octave_idx_type len = rep->length (0);
1055 
1056  switch (rep->idx_class ())
1057  {
1058  case class_colon:
1059  (*current_liboctave_error_handler) ("colon not allowed");
1060  break;
1061 
1062  case class_range:
1063  {
1064  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
1065  octave_idx_type start = r->get_start ();
1066  octave_idx_type step = r->get_step ();
1067  octave_idx_type i, j;
1068  if (step == 1)
1069  for (i = start, j = start + len; i < j; i++) *data++ = i;
1070  else if (step == -1)
1071  for (i = start, j = start - len; i > j; i--) *data++ = i;
1072  else
1073  for (i = 0, j = start; i < len; i++, j += step) *data++ = j;
1074  }
1075  break;
1076 
1077  case class_scalar:
1078  {
1079  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
1080  *data = r->get_data ();
1081  }
1082  break;
1083 
1084  case class_vector:
1085  {
1086  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1087  const octave_idx_type *rdata = r->get_data ();
1088  std::copy_n (rdata, len, data);
1089  }
1090  break;
1091 
1092  case class_mask:
1093  {
1094  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1095  const bool *mask = r->get_data ();
1096  octave_idx_type ext = r->extent (0);
1097  for (octave_idx_type i = 0, j = 0; i < ext; i++)
1098  if (mask[i])
1099  data[j++] = i;
1100  }
1101  break;
1102 
1103  default:
1104  assert (false);
1105  break;
1106  }
1107 }
1108 
1109 idx_vector
1111 {
1113  if (extent (n) > n)
1114  (*current_liboctave_error_handler)
1115  ("internal error: out of range complement index requested");
1116 
1117  if (idx_class () == class_mask)
1118  {
1119  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1120  octave_idx_type nz = r->length (0);
1121  octave_idx_type ext = r->extent (0);
1122  Array<bool> mask (dim_vector (n, 1));
1123  const bool *data = r->get_data ();
1124  bool *ndata = mask.fortran_vec ();
1125  for (octave_idx_type i = 0; i < ext; i++)
1126  ndata[i] = ! data[i];
1127  std::fill_n (ndata + ext, n - ext, true);
1128  retval = new idx_mask_rep (mask, n - nz);
1129  }
1130  else
1131  {
1132  Array<bool> mask (dim_vector (n, 1), true);
1133  fill (false, length (n), mask.fortran_vec ());
1134  retval = idx_vector (mask);
1135  }
1136 
1137  return retval;
1138 }
1139 
1140 bool
1142 {
1143  bool retval = false;
1144 
1145  if (is_colon_equiv (n))
1146  retval = true;
1147  else if (length(n) == n && extent(n) == n)
1148  {
1149  OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true);
1150 
1151  retval = true;
1152 
1153  for (octave_idx_type i = 0, len = length (); i < len; i++)
1154  {
1155  octave_idx_type k = xelem (i);
1156  if (left[k])
1157  left[k] = false;
1158  else
1159  {
1160  retval = false;
1161  break;
1162  }
1163  }
1164  }
1165 
1166  return retval;
1167 }
1168 
1169 idx_vector
1171 {
1172  assert (n == length (n));
1173 
1175 
1176  switch (idx_class ())
1177  {
1178  case class_range:
1179  {
1180  if (increment () == -1)
1181  retval = sorted ();
1182  else
1183  retval = *this;
1184  break;
1185  }
1186  case class_vector:
1187  {
1188  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1189  const octave_idx_type *ri = r->get_data ();
1191  for (octave_idx_type i = 0; i < n; i++)
1192  idx.xelem (ri[i]) = i;
1193  retval = new idx_vector_rep (idx, r->extent (0), DIRECT);
1194  break;
1195  }
1196  default:
1197  retval = *this;
1198  break;
1199  }
1200 
1201  return retval;
1202 }
1203 
1204 idx_vector
1206 {
1207  if (idx_class () == class_mask)
1208  {
1209  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1210  const bool *data = r->get_data ();
1211  octave_idx_type ext = r->extent (0);
1212  octave_idx_type len = r->length (0);
1213  octave_idx_type *idata = new octave_idx_type [len];
1214 
1215  for (octave_idx_type i = 0, j = 0; i < ext; i++)
1216  if (data[i])
1217  idata[j++] = i;
1218 
1219  ext = (len > 0 ? idata[len - 1] + 1 : 0);
1220 
1221  return new idx_vector_rep (idata, len, ext, r->orig_dimensions (),
1222  DIRECT);
1223  }
1224  else
1225  return *this;
1226 }
1227 
1229  double& scalar, Range& range,
1230  Array<double>& array, Array<bool>& mask) const
1231 {
1232  iclass = idx_class ();
1233  switch (iclass)
1234  {
1235  case class_colon:
1236  break;
1237 
1238  case class_range:
1239  {
1240  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
1241  range = r->unconvert ();
1242  }
1243  break;
1244 
1245  case class_scalar:
1246  {
1247  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
1248  scalar = r->unconvert ();
1249  }
1250  break;
1251 
1252  case class_vector:
1253  {
1254  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1255  array = r->unconvert ();
1256  }
1257  break;
1258 
1259  case class_mask:
1260  {
1261  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1262  mask = r->unconvert ();
1263  }
1264  break;
1265 
1266  default:
1267  assert (false);
1268  break;
1269  }
1270 }
1271 
1274 {
1275  return rep->as_array ();
1276 }
1277 
1278 bool
1280 {
1281  return idx_class () != class_vector || orig_dimensions ().isvector ();
1282 }
1283 
1285 idx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok)
1286 {
1287  if (! resize_ok && extent (z_len) > z_len)
1288  {
1289  (*current_liboctave_error_handler)
1290  ("invalid matrix index = %" OCTAVE_IDX_TYPE_FORMAT, extent (z_len));
1291  // FIXME: Should we call this before calling error_handler?
1292  rep->err = true;
1293  chkerr ();
1294  }
1295 
1296  return length (z_len);
1297 }
1298 
1301 {
1302  octave_idx_type n = 0;
1303 
1304  if (is_colon ())
1305  n = 1;
1306  else
1307  {
1308  for (octave_idx_type i = 0; i < length (1); i++)
1309  if (xelem (i) == 0)
1310  n++;
1311  }
1312 
1313  return n;
1314 }
1315 
1316 // Instantiate the octave_int constructors we want.
1317 #define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \
1318  template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \
1319  template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);
1320 
1331 
1332 /*
1333 
1334 %!error id=Octave:index-out-of-bounds 1(find ([1,1] != 0))
1335 %!assert ((1:3)(find ([1,0,1] != 0)), [1,3])
1336 
1337 */
template class OCTAVE_API Array< bool >
Definition: Array-b.cc:123
template class OCTAVE_API Array< octave_idx_type >
octave_idx_type nnz(void) const
Count nonzero elements.
Definition: Array.cc:2210
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:469
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
Definition: Array.cc:2225
void fill(const T &val)
Definition: Array.cc:73
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:581
Array< T > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
Definition: Array.h:560
void clear(void)
Definition: Array.cc:87
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:453
const T * fortran_vec(void) const
Size of the specified dimension.
Definition: Array.h:583
Definition: Range.h:40
octave_idx_type cols(void) const
Definition: Sparse.h:251
T * data(void)
Definition: Sparse.h:470
octave_idx_type * cidx(void)
Definition: Sparse.h:492
octave_idx_type rows(void) const
Definition: Sparse.h:250
dim_vector dims(void) const
Definition: Sparse.h:270
octave_idx_type * ridx(void)
Definition: Sparse.h:479
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
bool isvector(void) const
Definition: dim-vector.h:461
dim_vector make_nd_vector(octave_idx_type n) const
Definition: dim-vector.h:487
virtual Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:75
virtual octave_idx_type length(octave_idx_type n) const =0
virtual idx_class_type idx_class(void) const
Definition: idx-vector.h:100
virtual bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:108
idx_colon_rep(void)=default
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:113
OCTAVE_NORETURN idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:106
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:97
octave_idx_type len
Definition: idx-vector.h:420
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:745
Array< bool > * aowner
Definition: idx-vector.h:435
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:761
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:706
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:715
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.cc:688
octave_idx_type ext
Definition: idx-vector.h:421
Array< bool > unconvert(void) const
Definition: idx-vector.cc:731
octave_idx_type start
Definition: idx-vector.h:221
octave_idx_type get_step(void) const
Definition: idx-vector.h:211
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:163
octave_idx_type get_start(void) const
Definition: idx-vector.h:209
Range unconvert(void) const
Definition: idx-vector.cc:211
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:189
octave_idx_type len
Definition: idx-vector.h:221
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:184
octave_idx_type step
Definition: idx-vector.h:221
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:218
idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:172
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:204
octave_idx_type get_data(void) const
Definition: idx-vector.h:267
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:313
octave_idx_type data
Definition: idx-vector.h:277
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:284
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:301
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:293
double unconvert(void) const
Definition: idx-vector.cc:307
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:623
idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:463
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:598
Array< double > unconvert(void) const
Definition: idx-vector.cc:614
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:454
const octave_idx_type * data
Definition: idx-vector.h:346
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:542
octave_idx_type ones_count(void) const
Definition: idx-vector.cc:1300
octave_idx_type xelem(octave_idx_type n) const
Definition: idx-vector.h:564
const octave_idx_type * raw(void)
Definition: idx-vector.cc:1039
bool is_colon(void) const
Definition: idx-vector.h:576
idx_vector sorted(bool uniq=false) const
Definition: idx-vector.h:588
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
Definition: idx-vector.h:768
static const idx_vector colon
Definition: idx-vector.h:499
bool isvector(void) const
Definition: idx-vector.cc:1279
bool maybe_reduce(octave_idx_type n, const idx_vector &j, octave_idx_type nj)
Definition: idx-vector.cc:786
void copy_data(octave_idx_type *data) const
Definition: idx-vector.cc:1052
void unconvert(idx_class_type &iclass, double &scalar, Range &range, Array< double > &array, Array< bool > &mask) const
Definition: idx-vector.cc:1228
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:558
octave_idx_type elem(octave_idx_type n) const
Definition: idx-vector.h:1030
idx_vector unmask(void) const
Definition: idx-vector.cc:1205
octave_idx_type freeze(octave_idx_type z_len, const char *tag, bool resize_ok=false)
Definition: idx-vector.cc:1285
bool is_cont_range(octave_idx_type n, octave_idx_type &l, octave_idx_type &u) const
Definition: idx-vector.cc:955
idx_vector complement(octave_idx_type n) const
Definition: idx-vector.cc:1110
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:594
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1141
void chkerr(void)
Definition: idx-vector.h:451
Array< octave_idx_type > as_array(void) const
Definition: idx-vector.cc:1273
idx_vector inverse_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1170
static idx_vector_rep * err_rep(void)
Definition: idx-vector.cc:67
idx_base_rep * rep
Definition: idx-vector.h:1048
octave_idx_type max(void) const
Definition: idx-vector.h:1044
octave_idx_type increment(void) const
Definition: idx-vector.cc:1009
idx_vector(void)
Definition: idx-vector.h:465
static idx_vector_rep * nil_rep(void)
Definition: idx-vector.cc:60
idx_class_type idx_class(void) const
Definition: idx-vector.h:556
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:561
@ class_vector
Definition: idx-vector.h:65
@ class_scalar
Definition: idx-vector.h:64
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:585
T value(void) const
Definition: oct-inttypes.h:842
void set_compare(compare_fcn_type comp)
Definition: oct-sort.h:118
void sort(T *data, octave_idx_type nel)
Definition: oct-sort.cc:1517
#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T)
Definition: idx-vector.cc:1317
static OCTAVE_NORETURN void err_invalid_range(void)
Definition: idx-vector.cc:47
static void err_index_out_of_range(void)
Definition: idx-vector.cc:53
octave_idx_type convert_index(octave_idx_type i, bool &conv_error, octave_idx_type &ext)
Definition: idx-vector.cc:228
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::complex< T > trunc(const std::complex< T > &x)
Definition: lo-mappers.h:111
Complex log2(const Complex &x)
Definition: lo-mappers.cc:139
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
static int left
Definition: randmtzig.cc:191
#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)
Definition: oct-locbuf.h:50
@ ASCENDING
Definition: oct-sort.h:95
T::size_type numel(const T &str)
Definition: oct-string.cc:71
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:669
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
F77_RET_T len
Definition: xerbla.cc:61