GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
idx-vector.h
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2022 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 (octave_idx_vector_h)
27#define octave_idx_vector_h 1
28
29#include "octave-config.h"
30
31#include <cassert>
32#include <cstring>
33
34#include <algorithm>
35#include <iosfwd>
36#include <memory>
37
38#include "Array-fwd.h"
39#include "dim-vector.h"
40#include "oct-inttypes.h"
41#include "oct-refcount.h"
42#include "Sparse-fwd.h"
43#include "range-fwd.h"
44
45namespace octave
46{
47 // Design rationale:
48 //
49 // idx_vector is a reference-counting, polymorphic pointer, that can
50 // contain 4 types of index objects: a magic colon, a range, a scalar,
51 // or an index vector.
52 //
53 // Polymorphic methods for single element access are provided, as well
54 // as templates implementing "early dispatch", i.e., hoisting the checks
55 // for index type out of loops.
56
57 class
60 {
61 public:
62
64 {
65 class_invalid = -1,
66 class_colon = 0,
70 class_mask
71 };
72
73 template <typename T, typename D> friend class std::unique_ptr;
74
75 private:
76
78 {
79 public:
80
81 idx_base_rep (void) : m_count (1) { }
82
83 // No copying!
84
85 idx_base_rep (const idx_base_rep&) = delete;
86
87 idx_base_rep& operator = (const idx_base_rep&) = delete;
88
89 virtual ~idx_base_rep (void) = default;
90
91 // Non-range-checking element query.
92 virtual octave_idx_type xelem (octave_idx_type i) const = 0;
93
94 // Range-checking element query.
96
97 // Length of the index vector.
98 virtual octave_idx_type length (octave_idx_type n) const = 0;
99
100 // The maximum index + 1. The actual dimension is passed in.
102
103 // Index class.
104 virtual idx_class_type idx_class (void) const { return class_invalid; }
105
106 // Sorts, maybe uniqifies, and returns a clone object pointer.
107 virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0;
108 // Sorts, and returns a sorting permutation (aka Array::sort).
110
111 // Checks whether the index is colon or a range equivalent to colon.
112 virtual bool is_colon_equiv (octave_idx_type) const { return false; }
113
114 // The original dimensions of object (used when subscribing by matrices).
115 virtual dim_vector orig_dimensions (void) const { return dim_vector (); }
116
117 // i/o
118 virtual std::ostream& print (std::ostream& os) const = 0;
119
120 virtual Array<octave_idx_type> as_array (void);
121
123 };
124
125 // The magic colon index.
127 {
128 public:
129
130 idx_colon_rep (void) = default;
131
132 OCTAVE_API idx_colon_rep (char c);
133
134 // No copying!
135
136 idx_colon_rep (const idx_colon_rep& idx) = delete;
137
138 idx_colon_rep& operator = (const idx_colon_rep& idx) = delete;
139
140 octave_idx_type xelem (octave_idx_type i) const { return i; }
141
142 OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;
143
144 octave_idx_type length (octave_idx_type n) const { return n; }
145
146 octave_idx_type extent (octave_idx_type n) const { return n; }
147
148 idx_class_type idx_class (void) const { return class_colon; }
149
151 { m_count++; return this; }
152
153 OCTAVE_NORETURN idx_base_rep * sort_idx (Array<octave_idx_type>&);
154
155 bool is_colon_equiv (octave_idx_type) const { return true; }
156
157 OCTAVE_API std::ostream& print (std::ostream& os) const;
158 };
159
160 // To distinguish the "direct" constructors that blindly trust the data.
161 enum direct { DIRECT };
162
163 // The integer range index.
165 {
166 public:
167
168 idx_range_rep (void) = delete;
169
172 : idx_base_rep (), m_start (start), m_len (len), m_step (step) { }
173
174 // Zero-based constructor.
176 octave_idx_type step);
177
178 OCTAVE_API idx_range_rep (const range<double>&);
179
180 // No copying!
181
182 idx_range_rep (const idx_range_rep& idx) = delete;
183
184 idx_range_rep& operator = (const idx_range_rep& idx) = delete;
185
187 { return m_start + i * m_step; }
188
189 octave_idx_type checkelem (octave_idx_type i) const;
190
191 octave_idx_type length (octave_idx_type) const { return m_len; }
192
194 {
195 return m_len ? std::max (n, m_start + 1 + (m_step < 0 ? 0 : m_step * (m_len - 1))) : n;
196 }
197
198 idx_class_type idx_class (void) const { return class_range; }
199
200 OCTAVE_API idx_base_rep * sort_uniq_clone (bool uniq = false);
201
203
205 { return m_start == 0 && m_step == 1 && m_len == n; }
206
208 { return dim_vector (1, m_len); }
209
210 octave_idx_type get_start (void) const { return m_start; }
211
212 octave_idx_type get_step (void) const { return m_step; }
213
214 OCTAVE_API std::ostream& print (std::ostream& os) const;
215
216 OCTAVE_API range<double> unconvert (void) const;
217
218 OCTAVE_API Array<octave_idx_type> as_array (void);
219
220 private:
221
222 octave_idx_type m_start, m_len, m_step;
223 };
224
225 // The integer scalar index.
227 {
228 public:
229
230 idx_scalar_rep (void) = delete;
231
233
234 // No copying!
235
236 idx_scalar_rep (const idx_scalar_rep& idx) = delete;
237
238 idx_scalar_rep& operator = (const idx_scalar_rep& idx) = delete;
239
240 // Zero-based constructor.
242
243 template <typename T>
244 idx_scalar_rep (T x);
245
246 octave_idx_type xelem (octave_idx_type) const { return m_data; }
247
248 OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;
249
251
253 { return std::max (n, m_data + 1); }
254
255 idx_class_type idx_class (void) const { return class_scalar; }
256
258 { m_count++; return this; }
259
261
263 { return n == 1 && m_data == 0; }
264
265 dim_vector orig_dimensions (void) const { return dim_vector (1, 1); }
266
267 octave_idx_type get_data (void) const { return m_data; }
268
269 OCTAVE_API std::ostream& print (std::ostream& os) const;
270
271 OCTAVE_API double unconvert (void) const;
272
273 OCTAVE_API Array<octave_idx_type> as_array (void);
274
275 private:
276
278 };
279
280 // The integer vector index.
282 {
283 public:
284
286 : m_data (nullptr), m_len (0), m_ext (0), m_aowner (nullptr), m_orig_dims () { }
287
288 // Direct constructor.
290 octave_idx_type ext, const dim_vector& od, direct)
291 : idx_base_rep (), m_data (data), m_len (len), m_ext (ext),
292 m_aowner (nullptr), m_orig_dims (od)
293 { }
294
295 // Zero-based constructor.
297
300
301 template <typename T>
302 idx_vector_rep (const Array<T>&);
303
305
307
309
310 // No copying!
311
312 idx_vector_rep (const idx_vector_rep& idx) = delete;
313
314 idx_vector_rep& operator = (const idx_vector_rep& idx) = delete;
315
316 ~idx_vector_rep (void);
317
318 octave_idx_type xelem (octave_idx_type i) const { return m_data[i]; }
319
320 OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const;
321
322 octave_idx_type length (octave_idx_type) const { return m_len; }
323
325 { return std::max (n, m_ext); }
326
327 idx_class_type idx_class (void) const { return class_vector; }
328
329 idx_base_rep * sort_uniq_clone (bool uniq = false);
330
332
333 dim_vector orig_dimensions (void) const { return m_orig_dims; }
334
335 const octave_idx_type * get_data (void) const { return m_data; }
336
337 OCTAVE_API std::ostream& print (std::ostream& os) const;
338
339 OCTAVE_API Array<double> unconvert (void) const;
340
341 OCTAVE_API Array<octave_idx_type> as_array (void);
342
343 private:
344
348
349 // This is a trick to allow user-given zero-based arrays to be used
350 // as indices without copying. If the following pointer is nonzero,
351 // we do not own the data, but rather have an Array<octave_idx_type>
352 // object that provides us the data. Note that we need a pointer
353 // because we deferred the Array<T> declaration and we do not want
354 // it yet to be defined.
355
357
359 };
360
361 // The logical mask index.
363 {
364 public:
365
366 idx_mask_rep (void) = delete;
367
368 // Direct constructor.
370 octave_idx_type ext, const dim_vector& od, direct)
371 : idx_base_rep (), m_data (data), m_len (len), m_ext (ext),
372 m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (od)
373 { }
374
376
378
379 // No copying!
380
381 idx_mask_rep (const idx_mask_rep& idx) = delete;
382
383 idx_mask_rep& operator = (const idx_mask_rep& idx) = delete;
384
386
387 octave_idx_type xelem (octave_idx_type i) const;
388
389 octave_idx_type checkelem (octave_idx_type i) const;
390
391 octave_idx_type length (octave_idx_type) const { return m_len; }
392
394 { return std::max (n, m_ext); }
395
396 idx_class_type idx_class (void) const { return class_mask; }
397
399 { m_count++; return this; }
400
402
403 dim_vector orig_dimensions (void) const { return m_orig_dims; }
404
406 { return m_len == n && m_ext == n; }
407
408 const bool * get_data (void) const { return m_data; }
409
410 OCTAVE_API std::ostream& print (std::ostream& os) const;
411
412 OCTAVE_API Array<bool> unconvert (void) const;
413
414 OCTAVE_API Array<octave_idx_type> as_array (void);
415
416 private:
417
418 const bool *m_data;
421
422 // FIXME: I'm not sure if this is a good design. Maybe it would be
423 // better to employ some sort of generalized iteration scheme.
426
427 // This is a trick to allow user-given mask arrays to be used as
428 // indices without copying. If the following pointer is nonzero, we
429 // do not own the data, but rather have an Array<bool> object that
430 // provides us the data. Note that we need a pointer because we
431 // deferred the Array<T> declaration and we do not want it yet to be
432 // defined.
433
435
437 };
438
439 idx_vector (idx_base_rep *r) : m_rep (r) { }
440
441 // The shared empty vector representation (for fast default
442 // constructor).
443 static OCTAVE_API idx_vector_rep * nil_rep (void);
444
445 public:
446
447 // Fast empty constructor.
448 idx_vector (void) : m_rep (nil_rep ()) { m_rep->m_count++; }
449
450 // Zero-based constructors (for use from C++).
451 idx_vector (octave_idx_type i) : m_rep (new idx_scalar_rep (i)) { }
452
453#if OCTAVE_SIZEOF_INT != OCTAVE_SIZEOF_IDX_TYPE
454 idx_vector (int i)
455 : m_rep (new idx_scalar_rep (static_cast<octave_idx_type> (i))) { }
456#endif
457
458#if (OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_IDX_TYPE \
459 && OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_INT)
460 idx_vector (octave_f77_int_type i)
461 : m_rep (new idx_scalar_rep (static_cast<octave_idx_type> (i))) { }
462#endif
463
465 octave_idx_type step = 1)
466 : m_rep (new idx_range_rep (start, limit, step)) { }
467
468 static idx_vector
471 {
472 return idx_vector (new idx_range_rep (start, len, step, DIRECT));
473 }
474
476 : m_rep (new idx_vector_rep (inda)) { }
477
478 // Directly pass extent, no checking.
480 : m_rep (new idx_vector_rep (inda, ext, DIRECT)) { }
481
482 // Colon is best constructed by simply copying (or referencing) this member.
483 static const idx_vector colon;
484
485 // or passing ':' here
486 idx_vector (char c) : m_rep (new idx_colon_rep (c)) { }
487
488 // Conversion constructors (used by interpreter).
489
490 template <typename T>
492
493 idx_vector (double x) : m_rep (new idx_scalar_rep (x)) { }
494
495 idx_vector (float x) : m_rep (new idx_scalar_rep (x)) { }
496
497 // A scalar bool does not necessarily map to scalar index.
498 idx_vector (bool x) : m_rep (new idx_mask_rep (x)) { }
499
500 template <typename T>
502 : m_rep (new idx_vector_rep (nda)) { }
503
504 idx_vector (const Array<double>& nda) : m_rep (new idx_vector_rep (nda)) { }
505
506 idx_vector (const Array<float>& nda) : m_rep (new idx_vector_rep (nda)) { }
507
508 OCTAVE_API idx_vector (const Array<bool>& nda);
509
510 idx_vector (const range<double>& r) : m_rep (new idx_range_rep (r)) { }
511
512 idx_vector (const Sparse<bool>& nda) : m_rep (new idx_vector_rep (nda)) { }
513
514 idx_vector (const idx_vector& a) : m_rep (a.m_rep) { m_rep->m_count++; }
515
517 {
518 if (--m_rep->m_count == 0 && m_rep != nil_rep ())
519 delete m_rep;
520 }
521
522 idx_vector& operator = (const idx_vector& a)
523 {
524 if (this != &a)
525 {
526 if (--m_rep->m_count == 0 && m_rep != nil_rep ())
527 delete m_rep;
528
529 m_rep = a.m_rep;
530 m_rep->m_count++;
531 }
532 return *this;
533 }
534
535 idx_class_type idx_class (void) const { return m_rep->idx_class (); }
536
538 { return m_rep->length (n); }
539
541 { return m_rep->extent (n); }
542
544 { return m_rep->xelem (n); }
545
547 { return m_rep->xelem (n); }
548
549 octave_idx_type operator () (octave_idx_type n) const
550 { return m_rep->xelem (n); }
551
552 // FIXME: idx_vector objects are either created successfully or an
553 // error is thrown, so this method no longer makes sense.
554 operator bool (void) const { return true; }
555
556 bool is_colon (void) const
557 { return m_rep->idx_class () == class_colon; }
558
559 bool is_scalar (void) const
560 { return m_rep->idx_class () == class_scalar; }
561
562 bool is_range (void) const
563 { return m_rep->idx_class () == class_range; }
564
566 { return m_rep->is_colon_equiv (n); }
567
568 idx_vector sorted (bool uniq = false) const
569 { return idx_vector (m_rep->sort_uniq_clone (uniq)); }
570
572 { return idx_vector (m_rep->sort_idx (sidx)); }
573
574 dim_vector orig_dimensions (void) const { return m_rep->orig_dimensions (); }
575
577 { return orig_dimensions () (0); }
578
580 { return orig_dimensions () (1); }
581
582 int orig_empty (void) const
583 { return (! is_colon () && orig_dimensions ().any_zero ()); }
584
585 // i/o
586
587 std::ostream& print (std::ostream& os) const { return m_rep->print (os); }
588
589 friend std::ostream& operator << (std::ostream& os, const idx_vector& a)
590 { return a.print (os); }
591
592 // Slice with specializations. No checking of bounds!
593 //
594 // This is equivalent to the following loop (but much faster):
595 //
596 // for (octave_idx_type i = 0; i < idx->length (n); i++)
597 // dest[i] = src[idx(i)];
598 // return i;
599 //
600 template <typename T>
602 index (const T *src, octave_idx_type n, T *dest) const
603 {
604 octave_idx_type len = m_rep->length (n);
605
606 switch (m_rep->idx_class ())
607 {
608 case class_colon:
609 std::copy_n (src, len, dest);
610 break;
611
612 case class_range:
613 {
614 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
615 octave_idx_type start = r->get_start ();
616 octave_idx_type step = r->get_step ();
617 const T *ssrc = src + start;
618 if (step == 1)
619 std::copy_n (ssrc, len, dest);
620 else if (step == -1)
621 std::reverse_copy (ssrc - len + 1, ssrc + 1, dest);
622 else if (step == 0)
623 std::fill_n (dest, len, *ssrc);
624 else
625 {
626 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
627 dest[i] = ssrc[j];
628 }
629 }
630 break;
631
632 case class_scalar:
633 {
634 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
635 dest[0] = src[r->get_data ()];
636 }
637 break;
638
639 case class_vector:
640 {
641 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
642 const octave_idx_type *data = r->get_data ();
643 for (octave_idx_type i = 0; i < len; i++)
644 dest[i] = src[data[i]];
645 }
646 break;
647
648 case class_mask:
649 {
650 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
651 const bool *data = r->get_data ();
652 octave_idx_type ext = r->extent (0);
653 for (octave_idx_type i = 0; i < ext; i++)
654 if (data[i]) *dest++ = src[i];
655 }
656 break;
657
658 default:
659 assert (false);
660 break;
661 }
662
663 return len;
664 }
665
666 // Slice assignment with specializations. No checking of bounds!
667 //
668 // This is equivalent to the following loop (but much faster):
669 //
670 // for (octave_idx_type i = 0; i < idx->length (n); i++)
671 // dest[idx(i)] = src[i];
672 // return i;
673 //
674 template <typename T>
676 assign (const T *src, octave_idx_type n, T *dest) const
677 {
678 octave_idx_type len = m_rep->length (n);
679
680 switch (m_rep->idx_class ())
681 {
682 case class_colon:
683 std::copy_n (src, len, dest);
684 break;
685
686 case class_range:
687 {
688 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
689 octave_idx_type start = r->get_start ();
690 octave_idx_type step = r->get_step ();
691 T *sdest = dest + start;
692 if (step == 1)
693 std::copy_n (src, len, sdest);
694 else if (step == -1)
695 std::reverse_copy (src, src + len, sdest - len + 1);
696 else
697 {
698 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
699 sdest[j] = src[i];
700 }
701 }
702 break;
703
704 case class_scalar:
705 {
706 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
707 dest[r->get_data ()] = src[0];
708 }
709 break;
710
711 case class_vector:
712 {
713 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
714 const octave_idx_type *data = r->get_data ();
715 for (octave_idx_type i = 0; i < len; i++)
716 dest[data[i]] = src[i];
717 }
718 break;
719
720 case class_mask:
721 {
722 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
723 const bool *data = r->get_data ();
724 octave_idx_type ext = r->extent (0);
725 for (octave_idx_type i = 0; i < ext; i++)
726 if (data[i]) dest[i] = *src++;
727 }
728 break;
729
730 default:
731 assert (false);
732 break;
733 }
734
735 return len;
736 }
737
738 // Slice fill with specializations. No checking of bounds!
739 //
740 // This is equivalent to the following loop (but much faster):
741 //
742 // for (octave_idx_type i = 0; i < idx->length (n); i++)
743 // dest[idx(i)] = val;
744 // return i;
745 //
746 template <typename T>
748 fill (const T& val, octave_idx_type n, T *dest) const
749 {
750 octave_idx_type len = m_rep->length (n);
751
752 switch (m_rep->idx_class ())
753 {
754 case class_colon:
755 std::fill_n (dest, len, val);
756 break;
757
758 case class_range:
759 {
760 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
761 octave_idx_type start = r->get_start ();
762 octave_idx_type step = r->get_step ();
763 T *sdest = dest + start;
764 if (step == 1)
765 std::fill_n (sdest, len, val);
766 else if (step == -1)
767 std::fill (sdest - len + 1, sdest + 1, val);
768 else
769 {
770 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
771 sdest[j] = val;
772 }
773 }
774 break;
775
776 case class_scalar:
777 {
778 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
779 dest[r->get_data ()] = val;
780 }
781 break;
782
783 case class_vector:
784 {
785 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
786 const octave_idx_type *data = r->get_data ();
787 for (octave_idx_type i = 0; i < len; i++)
788 dest[data[i]] = val;
789 }
790 break;
791
792 case class_mask:
793 {
794 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
795 const bool *data = r->get_data ();
796 octave_idx_type ext = r->extent (0);
797 for (octave_idx_type i = 0; i < ext; i++)
798 if (data[i]) dest[i] = val;
799 }
800 break;
801
802 default:
803 assert (false);
804 break;
805 }
806
807 return len;
808 }
809
810 // Generic non-breakable indexed loop. The loop body should be
811 // encapsulated in a single functor body. This is equivalent to the
812 // following loop (but faster, at least for simple inlined bodies):
813 //
814 // for (octave_idx_type i = 0; i < idx->length (n); i++) body (idx(i));
815
816 template <typename Functor>
817 void
818 loop (octave_idx_type n, Functor body) const
819 {
820 octave_idx_type len = m_rep->length (n);
821
822 switch (m_rep->idx_class ())
823 {
824 case class_colon:
825 for (octave_idx_type i = 0; i < len; i++) body (i);
826 break;
827
828 case class_range:
829 {
830 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
831 octave_idx_type start = r->get_start ();
832 octave_idx_type step = r->get_step ();
833 octave_idx_type i, j;
834 if (step == 1)
835 for (i = start, j = start + len; i < j; i++) body (i);
836 else if (step == -1)
837 for (i = start, j = start - len; i > j; i--) body (i);
838 else
839 for (i = 0, j = start; i < len; i++, j += step) body (j);
840 }
841 break;
842
843 case class_scalar:
844 {
845 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
846 body (r->get_data ());
847 }
848 break;
849
850 case class_vector:
851 {
852 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
853 const octave_idx_type *data = r->get_data ();
854 for (octave_idx_type i = 0; i < len; i++) body (data[i]);
855 }
856 break;
857
858 case class_mask:
859 {
860 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
861 const bool *data = r->get_data ();
862 octave_idx_type ext = r->extent (0);
863 for (octave_idx_type i = 0; i < ext; i++)
864 if (data[i]) body (i);
865 }
866 break;
867
868 default:
869 assert (false);
870 break;
871 }
872
873 }
874
875 // Generic breakable indexed loop. The loop body should be
876 // encapsulated in a single functor body. This is equivalent to the
877 // following loop (but faster, at least for simple inlined bodies):
878 //
879 // for (octave_idx_type i = 0; i < idx->length (n); i++)
880 // if (body (idx(i))) break;
881 // return i;
882 //
883
884 template <typename Functor>
886 bloop (octave_idx_type n, Functor body) const
887 {
888 octave_idx_type len = m_rep->length (n), ret;
889
890 switch (m_rep->idx_class ())
891 {
892 case class_colon:
893 {
895 for (i = 0; i < len && body (i); i++) ;
896 ret = i;
897 }
898 break;
899
900 case class_range:
901 {
902 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
903 octave_idx_type start = r->get_start ();
904 octave_idx_type step = r->get_step ();
905 octave_idx_type i, j;
906 if (step == 1)
907 for (i = start, j = start + len; i < j && body (i); i++) ;
908 else if (step == -1)
909 for (i = start, j = start - len; i > j && body (i); i--) ;
910 else
911 for (i = 0, j = start; i < len && body (j); i++, j += step) ;
912 ret = i;
913 }
914 break;
915
916 case class_scalar:
917 {
918 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
919 ret = (body (r->get_data ()) ? 1 : 0);
920 }
921 break;
922
923 case class_vector:
924 {
925 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
926 const octave_idx_type *data = r->get_data ();
928 for (i = 0; i < len && body (data[i]); i++) ;
929 ret = i;
930 }
931 break;
932
933 case class_mask:
934 {
935 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
936 const bool *data = r->get_data ();
937 octave_idx_type ext = r->extent (0);
938 octave_idx_type j = 0;
939 for (octave_idx_type i = 0; i < ext; i++)
940 {
941 if (data[i])
942 {
943 if (body (i))
944 break;
945 else
946 j++;
947 }
948 }
949
950 ret = j;
951 }
952 break;
953
954 default:
955 assert (false);
956 break;
957 }
958
959 return ret;
960 }
961
962 // Rationale:
963 // This method is the key to "smart indexing". When indexing cartesian
964 // arrays, sometimes consecutive index vectors can be reduced into a
965 // single index. If rows (A) = k and i.maybe_reduce (j) gives k, then
966 // A(i,j)(:) is equal to A(k)(:).
967
968 // If the next index can be reduced, returns true and updates this.
969 OCTAVE_API bool
970 maybe_reduce (octave_idx_type n, const idx_vector& j, octave_idx_type nj);
971
972 OCTAVE_API bool
973 is_cont_range (octave_idx_type n, octave_idx_type& l,
974 octave_idx_type& u) const;
975
976 // Returns the increment for ranges and colon, 0 for scalars and empty
977 // vectors, 1st difference otherwise.
978 OCTAVE_API octave_idx_type increment (void) const;
979
981 complement (octave_idx_type n) const;
982
983 OCTAVE_API bool is_permutation (octave_idx_type n) const;
984
985 // Returns the inverse permutation. If this is not a permutation on 1:n, the
986 // result is undefined (but no error unless extent () != n).
987 OCTAVE_API idx_vector inverse_permutation (octave_idx_type n) const;
988
989 // Copies all the indices to a given array. Not allowed for colons.
990 OCTAVE_API void copy_data (octave_idx_type *data) const;
991
992 // If the index is a mask, convert it to index vector.
993 OCTAVE_API idx_vector unmask (void) const;
994
995 // Unconverts the index to a scalar, Range, double array or a mask.
996 OCTAVE_API void
997 unconvert (idx_class_type& iclass, double& scalar, range<double>& range,
998 Array<double>& array, Array<bool>& mask) const;
999
1000 OCTAVE_API Array<octave_idx_type> as_array (void) const;
1001
1002 // Raw pointer to index array. This is non-const because it may be
1003 // necessary to mutate the index.
1004 const OCTAVE_API octave_idx_type * raw (void);
1005
1006 OCTAVE_API bool isvector (void) const;
1007
1008 // FIXME: these are here for compatibility. They should be removed
1009 // when no longer in use.
1010
1012 { return (*this) (n); }
1013
1015 { return is_colon_equiv (n); }
1016
1018 freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false);
1019
1020 void sort (bool uniq = false)
1021 { *this = sorted (uniq); }
1022
1023 OCTAVE_API octave_idx_type ones_count (void) const;
1024
1025 octave_idx_type max (void) const { return extent (1) - 1; }
1026
1027 private:
1028
1030
1031 };
1032}
1033
1034// Provide the following typedef for backward compatibility. Don't
1035// deprecate (yet) because it is used extensively.
1036
1038
1039#endif
dim_vector freeze(Array< octave::idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:261
bool isvector(const dim_vector &dim)
Definition: Array-util.cc:140
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
virtual ~idx_base_rep(void)=default
virtual bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:112
virtual octave_idx_type checkelem(octave_idx_type i) const =0
virtual octave_idx_type xelem(octave_idx_type i) const =0
virtual idx_base_rep * sort_idx(Array< octave_idx_type > &)=0
idx_base_rep(const idx_base_rep &)=delete
virtual octave_idx_type length(octave_idx_type n) const =0
virtual octave_idx_type extent(octave_idx_type n) const =0
virtual std::ostream & print(std::ostream &os) const =0
refcount< octave_idx_type > m_count
Definition: idx-vector.h:122
virtual idx_class_type idx_class(void) const
Definition: idx-vector.h:104
virtual idx_base_rep * sort_uniq_clone(bool uniq=false)=0
virtual dim_vector orig_dimensions(void) const
Definition: idx-vector.h:115
idx_colon_rep(const idx_colon_rep &idx)=delete
bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:155
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:146
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:140
idx_class_type idx_class(void) const
Definition: idx-vector.h:148
octave_idx_type length(octave_idx_type n) const
Definition: idx-vector.h:144
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:150
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:398
idx_mask_rep(bool *data, octave_idx_type len, octave_idx_type ext, const dim_vector &od, direct)
Definition: idx-vector.h:369
const bool * get_data(void) const
Definition: idx-vector.h:408
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:405
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:391
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:393
idx_mask_rep(const idx_mask_rep &idx)=delete
idx_class_type idx_class(void) const
Definition: idx-vector.h:396
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:403
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:193
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:204
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:207
idx_class_type idx_class(void) const
Definition: idx-vector.h:198
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:186
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:191
idx_range_rep(const idx_range_rep &idx)=delete
idx_range_rep(octave_idx_type start, octave_idx_type len, octave_idx_type step, direct)
Definition: idx-vector.h:170
octave_idx_type get_start(void) const
Definition: idx-vector.h:210
octave_idx_type get_step(void) const
Definition: idx-vector.h:212
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:265
idx_class_type idx_class(void) const
Definition: idx-vector.h:255
octave_idx_type get_data(void) const
Definition: idx-vector.h:267
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:250
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:257
idx_scalar_rep(octave_idx_type i, direct)
Definition: idx-vector.h:232
idx_scalar_rep(const idx_scalar_rep &idx)=delete
octave_idx_type xelem(octave_idx_type) const
Definition: idx-vector.h:246
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:252
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:262
const octave_idx_type * get_data(void) const
Definition: idx-vector.h:335
Array< octave_idx_type > * m_aowner
Definition: idx-vector.h:356
const octave_idx_type * m_data
Definition: idx-vector.h:345
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:318
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:322
idx_vector_rep(const idx_vector_rep &idx)=delete
idx_class_type idx_class(void) const
Definition: idx-vector.h:327
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:333
idx_vector_rep(octave_idx_type *data, octave_idx_type len, octave_idx_type ext, const dim_vector &od, direct)
Definition: idx-vector.h:289
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:324
idx_vector(octave_idx_type start, octave_idx_type limit, octave_idx_type step=1)
Definition: idx-vector.h:464
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:469
octave_idx_type orig_columns(void) const
Definition: idx-vector.h:579
bool is_colon(void) const
Definition: idx-vector.h:556
idx_vector(const Array< double > &nda)
Definition: idx-vector.h:504
void loop(octave_idx_type n, Functor body) const
Definition: idx-vector.h:818
idx_vector(const Array< octave_idx_type > &inda)
Definition: idx-vector.h:475
idx_vector(idx_base_rep *r)
Definition: idx-vector.h:439
idx_vector sorted(bool uniq=false) const
Definition: idx-vector.h:568
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:540
idx_base_rep * m_rep
Definition: idx-vector.h:1029
octave_idx_type max(void) const
Definition: idx-vector.h:1025
idx_vector(octave_idx_type i)
Definition: idx-vector.h:451
octave_idx_type orig_rows(void) const
Definition: idx-vector.h:576
octave_idx_type xelem(octave_idx_type n) const
Definition: idx-vector.h:543
idx_vector(const range< double > &r)
Definition: idx-vector.h:510
idx_vector(const Array< octave_idx_type > &inda, octave_idx_type ext)
Definition: idx-vector.h:479
octave_idx_type checkelem(octave_idx_type n) const
Definition: idx-vector.h:546
std::ostream & print(std::ostream &os) const
Definition: idx-vector.h:587
idx_vector(float x)
Definition: idx-vector.h:495
idx_class_type idx_class(void) const
Definition: idx-vector.h:535
idx_vector(const Array< octave_int< T > > &nda)
Definition: idx-vector.h:501
octave_idx_type assign(const T *src, octave_idx_type n, T *dest) const
Definition: idx-vector.h:676
bool is_scalar(void) const
Definition: idx-vector.h:559
idx_vector(const idx_vector &a)
Definition: idx-vector.h:514
octave_idx_type elem(octave_idx_type n) const
Definition: idx-vector.h:1011
bool is_colon_equiv(octave_idx_type n, int) const
Definition: idx-vector.h:1014
void sort(bool uniq=false)
Definition: idx-vector.h:1020
octave_idx_type bloop(octave_idx_type n, Functor body) const
Definition: idx-vector.h:886
idx_vector(const Array< float > &nda)
Definition: idx-vector.h:506
idx_vector(octave_int< T > x)
Definition: idx-vector.h:491
idx_vector(const Sparse< bool > &nda)
Definition: idx-vector.h:512
octave_idx_type index(const T *src, octave_idx_type n, T *dest) const
Definition: idx-vector.h:602
idx_vector sorted(Array< octave_idx_type > &sidx) const
Definition: idx-vector.h:571
static const idx_vector colon
Definition: idx-vector.h:483
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:574
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
Definition: idx-vector.h:748
idx_vector(double x)
Definition: idx-vector.h:493
bool is_range(void) const
Definition: idx-vector.h:562
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:537
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:565
int orig_empty(void) const
Definition: idx-vector.h:582
octave::idx_vector idx_vector
Definition: idx-vector.h:1037
F77_RET_T const F77_DBLE * x
#define OCTAVE_API
Definition: main.in.cc:55
class OCTAVE_API range
Definition: range-fwd.h:33
std::ostream & operator<<(std::ostream &os, const CollocWt &a)
Definition: CollocWt.cc:482
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:679
F77_RET_T len
Definition: xerbla.cc:61