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