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