GNU Octave  4.4.1
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-2018 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
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License 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 <https://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 
76  idx_base_rep (void) : count (1), err (false) { }
77 
78  // No copying!
79 
80  idx_base_rep (const idx_base_rep&) = delete;
81 
82  idx_base_rep& operator = (const idx_base_rep&) = delete;
83 
84  virtual ~idx_base_rep (void) = default;
85 
86  // Non-range-checking element query.
87  virtual octave_idx_type xelem (octave_idx_type i) const = 0;
88 
89  // Range-checking element query.
90  virtual octave_idx_type checkelem (octave_idx_type i) const = 0;
91 
92  // Length of the index vector.
93  virtual octave_idx_type length (octave_idx_type n) const = 0;
94 
95  // The maximum index + 1. The actual dimension is passed in.
96  virtual octave_idx_type extent (octave_idx_type n) const = 0;
97 
98  // Index class.
99  virtual idx_class_type idx_class (void) const { return class_invalid; }
100 
101  // Sorts, maybe uniqifies, and returns a clone object pointer.
102  virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0;
103  // Sorts, and returns a sorting permutation (aka Array::sort).
104  virtual idx_base_rep * sort_idx (Array<octave_idx_type>&) = 0;
105 
106  // Checks whether the index is colon or a range equivalent to colon.
107  virtual bool is_colon_equiv (octave_idx_type) const { return false; }
108 
109  // The original dimensions of object (used when subscribing by matrices).
110  virtual dim_vector orig_dimensions (void) const { return dim_vector (); }
111 
112  // i/o
113  virtual std::ostream& print (std::ostream& os) const = 0;
114 
115  virtual Array<octave_idx_type> as_array (void);
116 
118 
119  bool err;
120  };
121 
122  // The magic colon index.
123  class OCTAVE_API idx_colon_rep : public idx_base_rep
124  {
125  public:
126 
127  idx_colon_rep (void) = default;
128 
129  idx_colon_rep (char c);
130 
131  // No copying!
132 
133  idx_colon_rep (const idx_colon_rep& idx) = delete;
134 
135  idx_colon_rep& operator = (const idx_colon_rep& idx) = delete;
136 
138 
140 
141  octave_idx_type length (octave_idx_type n) const { return n; }
142 
143  octave_idx_type extent (octave_idx_type n) const { return n; }
144 
145  idx_class_type idx_class (void) const { return class_colon; }
146 
147  idx_base_rep * sort_uniq_clone (bool = false)
148  { count++; return this; }
149 
150  OCTAVE_NORETURN idx_base_rep * sort_idx (Array<octave_idx_type>&);
151 
152  bool is_colon_equiv (octave_idx_type) const { return true; }
153 
154  std::ostream& print (std::ostream& os) const;
155  };
156 
157  // To distinguish the "direct" constructors that blindly trust the data.
158  enum direct { DIRECT };
159 
160  // The integer range index.
161  class OCTAVE_API idx_range_rep : public idx_base_rep
162  {
163  public:
164 
165  idx_range_rep (void) = delete;
166 
168  octave_idx_type _step, direct)
169  : idx_base_rep (), start(_start), len(_len), step(_step) { }
170 
171  // Zero-based constructor.
173  octave_idx_type _step);
174 
175  idx_range_rep (const Range&);
176 
177  // No copying!
178 
179  idx_range_rep (const idx_range_rep& idx) = delete;
180 
181  idx_range_rep& operator = (const idx_range_rep& idx) = delete;
182 
184  { return start + i * step; }
185 
187 
188  octave_idx_type length (octave_idx_type) const { return len; }
189 
191  {
192  return len ? std::max (n, start + 1 + (step < 0 ? 0 : step * (len - 1)))
193  : n;
194  }
195 
196  idx_class_type idx_class (void) const { return class_range; }
197 
198  idx_base_rep * sort_uniq_clone (bool uniq = false);
199 
201 
203  { return start == 0 && step == 1 && len == n; }
204 
206  { return dim_vector (1, len); }
207 
208  octave_idx_type get_start (void) const { return start; }
209 
210  octave_idx_type get_step (void) const { return step; }
211 
212  std::ostream& print (std::ostream& os) const;
213 
214  Range unconvert (void) const;
215 
217 
218  private:
219 
221  };
222 
223  // The integer scalar index.
224  class OCTAVE_API idx_scalar_rep : public idx_base_rep
225  {
226  public:
227 
228  idx_scalar_rep (void) = delete;
229 
231  : idx_base_rep (), data (i) { }
232 
233  // No copying!
234 
235  idx_scalar_rep (const idx_scalar_rep& idx) = delete;
236 
237  idx_scalar_rep& operator = (const idx_scalar_rep& idx) = delete;
238 
239  // Zero-based constructor.
241 
242  template <typename T>
243  idx_scalar_rep (T x);
244 
245  octave_idx_type xelem (octave_idx_type) const { return data; }
246 
248 
249  octave_idx_type length (octave_idx_type) const { return 1; }
250 
252  { return std::max (n, data + 1); }
253 
254  idx_class_type idx_class (void) const { return class_scalar; }
255 
256  idx_base_rep * sort_uniq_clone (bool = false)
257  { count++; return this; }
258 
260 
262  { return n == 1 && data == 0; }
263 
264  dim_vector orig_dimensions (void) const { return dim_vector (1, 1); }
265 
266  octave_idx_type get_data (void) const { return data; }
267 
268  std::ostream& print (std::ostream& os) const;
269 
270  double unconvert (void) const;
271 
273 
274  private:
275 
277  };
278 
279  // The integer vector index.
280  class OCTAVE_API idx_vector_rep : public idx_base_rep
281  {
282  public:
283 
285  : data (nullptr), len (0), ext (0), aowner (nullptr), orig_dims ()
286  { }
287 
288  // Direct constructor.
290  octave_idx_type _ext, const dim_vector& od, direct)
291  : idx_base_rep (), data (_data), len (_len), ext (_ext),
292  aowner (nullptr), orig_dims (od)
293  { }
294 
295  // Zero-based constructor.
297 
299  octave_idx_type _ext, direct);
300 
301  template <typename T>
302  idx_vector_rep (const Array<T>&);
303 
304  idx_vector_rep (bool);
305 
307 
308  idx_vector_rep (const Sparse<bool>&);
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 data[i]; }
319 
321 
322  octave_idx_type length (octave_idx_type) const { return len; }
323 
325  { return std::max (n, 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 orig_dims; }
334 
335  const octave_idx_type * get_data (void) const { return data; }
336 
337  std::ostream& print (std::ostream& os) const;
338 
339  Array<double> unconvert (void) const;
340 
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.
362  class OCTAVE_API idx_mask_rep : public idx_base_rep
363  {
364  public:
365 
366  idx_mask_rep (void) = delete;
367 
368  // Direct constructor.
369  idx_mask_rep (bool *_data, octave_idx_type _len,
370  octave_idx_type _ext, const dim_vector& od, direct)
371  : idx_base_rep (), data (_data), len (_len), ext (_ext),
372  lsti (-1), lste (-1), aowner (nullptr), orig_dims (od)
373  { }
374 
375  idx_mask_rep (bool);
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 
385  ~idx_mask_rep (void);
386 
388 
390 
391  octave_idx_type length (octave_idx_type) const { return len; }
392 
394  { return std::max (n, ext); }
395 
396  idx_class_type idx_class (void) const { return class_mask; }
397 
398  idx_base_rep * sort_uniq_clone (bool = false)
399  { count++; return this; }
400 
402 
403  dim_vector orig_dimensions (void) const { return orig_dims; }
404 
406  { return len == n && ext == n; }
407 
408  const bool * get_data (void) const { return data; }
409 
410  std::ostream& print (std::ostream& os) const;
411 
412  Array<bool> unconvert (void) const;
413 
415 
416  private:
417 
418  const bool *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) : rep (r) { }
440 
441  // The shared empty vector representation (for fast default
442  // constructor).
443  static idx_vector_rep *nil_rep (void);
444 
445  // The shared empty vector representation with the error flag set.
446  static idx_vector_rep *err_rep (void);
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 
470 #if OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_IDX_TYPE
471  idx_vector (octave_f77_int_type i)
472  : rep (new idx_scalar_rep (static_cast<octave_idx_type> (i)))
473  { chkerr (); }
474 #endif
475 
477  octave_idx_type step = 1)
478  : rep (new idx_range_rep (start, limit, step))
479  { chkerr (); }
480 
481  static idx_vector
483  octave_idx_type len)
484  {
485  return idx_vector (new idx_range_rep (start, len, step, DIRECT));
486  }
487 
489  : rep (new idx_vector_rep (inda))
490  { chkerr (); }
491 
492  // Directly pass extent, no checking.
494  : rep (new idx_vector_rep (inda, ext, DIRECT))
495  { }
496 
497  // Colon is best constructed by simply copying (or referencing) this member.
498  static const idx_vector colon;
499 
500  // or passing ':' here
501  idx_vector (char c) : rep (new idx_colon_rep (c)) { chkerr (); }
502 
503  // Conversion constructors (used by interpreter).
504 
505  template <typename T>
506  idx_vector (octave_int<T> x) : rep (new idx_scalar_rep (x)) { chkerr (); }
507 
508  idx_vector (double x) : rep (new idx_scalar_rep (x)) { chkerr (); }
509 
510  idx_vector (float x) : rep (new idx_scalar_rep (x)) { chkerr (); }
511 
512  // A scalar bool does not necessarily map to scalar index.
513  idx_vector (bool x) : rep (new idx_mask_rep (x)) { chkerr (); }
514 
515  template <typename T>
516  idx_vector (const Array<octave_int<T>>& nda) : rep (new idx_vector_rep (nda))
517  { chkerr (); }
518 
519  idx_vector (const Array<double>& nda) : rep (new idx_vector_rep (nda))
520  { chkerr (); }
521 
522  idx_vector (const Array<float>& nda) : rep (new idx_vector_rep (nda))
523  { chkerr (); }
524 
525  idx_vector (const Array<bool>& nda);
526 
527  idx_vector (const Range& r)
528  : rep (new idx_range_rep (r))
529  { chkerr (); }
530 
531  idx_vector (const Sparse<bool>& nda) : rep (new idx_vector_rep (nda))
532  { chkerr (); }
533 
534  idx_vector (const idx_vector& a) : rep (a.rep) { rep->count++; }
535 
536  ~idx_vector (void)
537  {
538  if (--rep->count == 0)
539  delete rep;
540  }
541 
542  idx_vector& operator = (const idx_vector& a)
543  {
544  if (this != &a)
545  {
546  if (--rep->count == 0)
547  delete rep;
548 
549  rep = a.rep;
550  rep->count++;
551  }
552  return *this;
553  }
554 
555  idx_class_type idx_class (void) const { return rep->idx_class (); }
556 
558  { return rep->length (n); }
559 
561  { return rep->extent (n); }
562 
564  { return rep->xelem (n); }
565 
567  { return rep->xelem (n); }
568 
569  octave_idx_type operator () (octave_idx_type n) const
570  { return rep->xelem (n); }
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 <typename 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_n (src, len, dest);
629  break;
630 
631  case class_range:
632  {
633  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
635  octave_idx_type step = r->get_step ();
636  const T *ssrc = src + start;
637  if (step == 1)
638  std::copy_n (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 <typename 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_n (src, len, dest);
703  break;
704 
705  case class_range:
706  {
707  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
709  octave_idx_type step = r->get_step ();
710  T *sdest = dest + start;
711  if (step == 1)
712  std::copy_n (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 <typename 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_n (dest, len, val);
775  break;
776 
777  case class_range:
778  {
779  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
781  octave_idx_type step = r->get_step ();
782  T *sdest = dest + start;
783  if (step == 1)
784  std::fill_n (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 <typename 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);
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 <typename 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  {
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);
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 ();
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 isvector (void) const;
1025 
1026  OCTAVE_DEPRECATED (4.4, "use 'isvector' instead")
1027  bool is_vector (void) const
1028  { return isvector (); }
1029 
1030  // FIXME: these are here for compatibility. They should be removed
1031  // when no longer in use.
1032 
1034  { return (*this) (n); }
1035 
1036  bool is_colon_equiv (octave_idx_type n, int) const
1037  { return is_colon_equiv (n); }
1038 
1040  freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false);
1041 
1042  void sort (bool uniq = false)
1043  { *this = sorted (uniq); }
1044 
1045  octave_idx_type ones_count (void) const;
1046 
1047  octave_idx_type max (void) const { return extent (1) - 1; }
1048 
1049 private:
1050 
1052 
1053 };
1054 
1055 #endif
idx_class_type idx_class(void) const
Definition: idx-vector.h:254
octave_idx_type len
Definition: idx-vector.h:419
const octave_idx_type * get_data(void) const
Definition: idx-vector.h:335
octave_idx_type data
Definition: idx-vector.h:276
virtual Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:73
octave_idx_type checkelem(octave_idx_type n) const
Definition: idx-vector.h:566
octave_idx_type step
Definition: idx-vector.h:220
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:593
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:398
octave_idx_type lsti
Definition: idx-vector.h:424
idx_class_type idx_class(void) const
Definition: idx-vector.h:555
idx_vector(const Array< octave_idx_type > &inda)
Definition: idx-vector.h:488
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:405
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:251
void loop(octave_idx_type n, Functor body) const
Definition: idx-vector.h:837
nd group nd example oindent but is performed more efficiently If only and it is a scalar
Definition: data.cc:5264
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:560
idx_class_type idx_class(void) const
Definition: idx-vector.h:396
static const idx_vector colon
Definition: idx-vector.h:498
bool is_colon_equiv(octave_idx_type n, int) const
Definition: idx-vector.h:1036
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
octave_idx_type max(void) const
Definition: idx-vector.h:1047
idx_vector(const Range &r)
Definition: idx-vector.h:527
octave_idx_type xelem(octave_idx_type n) const
Definition: idx-vector.h:563
idx_vector(const Array< octave_int< T >> &nda)
Definition: idx-vector.h:516
virtual dim_vector orig_dimensions(void) const
Definition: idx-vector.h:110
Definition: Range.h:33
idx_vector(char c)
Definition: idx-vector.h:501
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:190
idx_vector(bool x)
Definition: idx-vector.h:513
void unconvert(idx_class_type &iclass, double &scalar, Range &range, Array< double > &array, Array< bool > &mask) const
Definition: idx-vector.cc:1226
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:333
u
Definition: lu.cc:138
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:324
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
virtual idx_class_type idx_class(void) const
Definition: idx-vector.h:99
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:143
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:188
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:322
const bool * get_data(void) const
Definition: idx-vector.h:408
octave_idx_type lste
Definition: idx-vector.h:425
octave_idx_type elem(octave_idx_type n) const
Definition: idx-vector.h:1033
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:400
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:264
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
idx_class_type idx_class(void) const
Definition: idx-vector.h:196
idx_class_type idx_class(void) const
Definition: idx-vector.h:327
octave_idx_type assign(const T *src, octave_idx_type n, T *dest) const
Definition: idx-vector.h:695
Array< bool > * aowner
Definition: idx-vector.h:434
virtual bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:107
octave_idx_type orig_rows(void) const
Definition: idx-vector.h:595
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:391
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:403
bool is_range(void) const
Definition: idx-vector.h:581
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:393
octave_idx_type xelem(octave_idx_type) const
Definition: idx-vector.h:245
bool is_colon(void) const
Definition: idx-vector.h:575
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:249
int orig_empty(void) const
Definition: idx-vector.h:601
octave_idx_type ext
Definition: idx-vector.h:420
idx_base_rep * rep
Definition: idx-vector.h:1051
idx_range_rep(octave_idx_type _start, octave_idx_type _len, octave_idx_type _step, direct)
Definition: idx-vector.h:167
idx_vector(float x)
Definition: idx-vector.h:510
is false
Definition: cellfun.cc:400
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:557
dim_vector freeze(Array< idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:259
idx_vector sorted(bool uniq=false) const
Definition: idx-vector.h:587
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:289
idx_vector(octave_idx_type i)
Definition: idx-vector.h:467
virtual octave_idx_type xelem(octave_idx_type i) const =0
octave_idx_type orig_columns(void) const
Definition: idx-vector.h:598
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:261
idx_mask_rep(bool *_data, octave_idx_type _len, octave_idx_type _ext, const dim_vector &od, direct)
Definition: idx-vector.h:369
idx_vector sorted(Array< octave_idx_type > &sidx) const
Definition: idx-vector.h:590
void sort(bool uniq=false)
Definition: idx-vector.h:1042
virtual octave_idx_type checkelem(octave_idx_type i) const =0
bool isvector(const dim_vector &dim)
Definition: Array-util.cc:138
octave_idx_type get_step(void) const
Definition: idx-vector.h:210
octave::refcount< int > count
Definition: idx-vector.h:117
octave_idx_type get_start(void) const
Definition: idx-vector.h:208
octave_idx_type bloop(octave_idx_type n, Functor body) const
Definition: idx-vector.h:905
octave_idx_type get_data(void) const
Definition: idx-vector.h:266
idx_vector(const Array< float > &nda)
Definition: idx-vector.h:522
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:125
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:152
octave::sys::time start
Definition: graphics.cc:12337
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:205
idx_vector(const Array< double > &nda)
Definition: idx-vector.h:519
idx_vector(const Array< octave_idx_type > &inda, octave_idx_type ext)
Definition: idx-vector.h:493
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:584
octave_idx_type index(const T *src, octave_idx_type n, T *dest) const
Definition: idx-vector.h:621
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:183
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:147
idx_scalar_rep(octave_idx_type i, direct)
Definition: idx-vector.h:230
idx_vector(idx_base_rep *r)
Definition: idx-vector.h:439
template OCTAVE_API std::ostream & operator<<(std::ostream &, const Array< bool > &)
idx_class_type idx_class(void) const
Definition: idx-vector.h:145
idx_vector(octave_idx_type start, octave_idx_type limit, octave_idx_type step=1)
Definition: idx-vector.h:476
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
Definition: idx-vector.h:767
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:318
const octave_idx_type * data
Definition: idx-vector.h:345
~idx_vector(void)
Definition: idx-vector.h:536
idx_vector(octave_int< T > x)
Definition: idx-vector.h:506
virtual idx_base_rep * sort_idx(Array< octave_idx_type > &)=0
idx_vector(const Sparse< bool > &nda)
Definition: idx-vector.h:531
void chkerr(void)
Definition: idx-vector.h:450
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:202
for i
Definition: data.cc:5264
OCTAVE_EXPORT octave_value_list error nd deftypefn *const octave_scalar_map err
Definition: error.cc:1049
Array< octave_idx_type > * aowner
Definition: idx-vector.h:356
virtual idx_base_rep * sort_uniq_clone(bool uniq=false)=0
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
octave_idx_type length(octave_idx_type n) const
Definition: idx-vector.h:141
idx_base_rep * sort_uniq_clone(bool=false)
Definition: idx-vector.h:256
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
idx_base_rep & operator=(const idx_base_rep &)=delete
bool is_scalar(void) const
Definition: idx-vector.h:578
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:137
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:482
virtual std::ostream & print(std::ostream &os) const =0
std::ostream & print(std::ostream &os) const
Definition: idx-vector.h:606
octave::stream os
Definition: file-io.cc:627
idx_vector(double x)
Definition: idx-vector.h:508
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 const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
idx_vector(const idx_vector &a)
Definition: idx-vector.h:534