This file is indexed.

/usr/include/octave-3.2.4/octave/idx-vector.h is in octave3.2-headers 3.2.4-12.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
/*

Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003,
              2004, 2005, 2006, 2007 John W. Eaton
Copyright (C) 2008, 2009 Jaroslav Hajek

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#if !defined (octave_idx_vector_h)
#define octave_idx_vector_h 1

#include <cassert>

#include <algorithm>
#include <iosfwd>

#include "dim-vector.h"
#include "oct-inttypes.h"
#include "oct-alloc.h"

template<class T> class Array;
template<class T> class Sparse;
class Range;

// Design rationale:
// idx_vector is a reference-counting, polymorphic pointer, that can contain
// 4 types of index objects: a magic colon, a range, a scalar, or an index vector.
// Polymorphic methods for single element access are provided, as well as
// templates implementing "early dispatch", i.e. hoisting the checks for index
// type out of loops.

class
OCTAVE_API
idx_vector
{
public:
  
  enum idx_class_type
    {
      class_invalid = -1,
      class_colon = 0,
      class_range,
      class_scalar,
      class_vector
    };

private:

  class OCTAVE_API idx_base_rep
  {
  public:
    idx_base_rep (void) : count (1), err (false) { }

    virtual ~idx_base_rep (void) { }

    // Non-range-checking element query.
    virtual octave_idx_type xelem (octave_idx_type i) const = 0;

    // Range-checking element query.
    virtual octave_idx_type checkelem (octave_idx_type i) const = 0;

    // Length of the index vector.
    virtual octave_idx_type length (octave_idx_type n) const = 0;

    // The maximum index + 1. The actual dimension is passed in.
    virtual octave_idx_type extent (octave_idx_type n) const = 0;

    // Index class.
    virtual idx_class_type idx_class (void) const { return class_invalid; }

    // Sorts, maybe uniqifies, and returns a clone object pointer.
    virtual idx_base_rep *sort_uniq_clone (bool uniq = false) = 0;

    // Checks whether the index is colon or a range equivalent to colon.
    virtual bool is_colon_equiv (octave_idx_type) const
      { return false; }

    // The original dimensions of this object (used when subscribing by matrices).
    virtual dim_vector orig_dimensions (void) const
      { return dim_vector (); }

    // i/o
    virtual std::ostream& print (std::ostream& os) const = 0;

    int count;

    bool err;

  private:

    // No copying!
    idx_base_rep (const idx_base_rep&);
  };

  // The magic colon index.
  class OCTAVE_API idx_colon_rep : public idx_base_rep
  {
  public:
    idx_colon_rep (void) { }

    idx_colon_rep (char c);

    octave_idx_type xelem (octave_idx_type i) const
      { return i; }

    octave_idx_type checkelem (octave_idx_type i) const;

    octave_idx_type length (octave_idx_type n) const
      { return n; }

    octave_idx_type extent (octave_idx_type n) const
      { return n; }

    idx_class_type idx_class (void) const { return class_colon; }

    idx_base_rep *sort_uniq_clone (bool = false) 
      { count++; return this; }

    bool is_colon_equiv (octave_idx_type) const
      { return true; }

    std::ostream& print (std::ostream& os) const;

  private:

    DECLARE_OCTAVE_ALLOCATOR

    // No copying!
    idx_colon_rep (const idx_colon_rep& idx);
  };

  // To distinguish the "direct" constructors that blindly trust the data.
  enum direct { DIRECT };

  // The integer range index.
  class OCTAVE_API idx_range_rep : public idx_base_rep
  {
  public:
    idx_range_rep (octave_idx_type _start, octave_idx_type _len,
                   octave_idx_type _step, direct) 
      : idx_base_rep (), start(_start), len(_len), step(_step) { }

    idx_range_rep (void) 
      : start(0), len(0), step(1) { }

    // Zero-based constructor.
    idx_range_rep (octave_idx_type _start, octave_idx_type _limit,
                   octave_idx_type _step); 

    idx_range_rep (const Range&);

    octave_idx_type xelem (octave_idx_type i) const
      { return start + i * step; }

    octave_idx_type checkelem (octave_idx_type i) const;

    octave_idx_type length (octave_idx_type) const
      { return len; }

    octave_idx_type extent (octave_idx_type n) const
      { return len ? std::max (n, (start + 1 + (step < 0 ? 0 : step * (len - 1)))) : n; }

    idx_class_type idx_class (void) const { return class_range; }

    idx_base_rep *sort_uniq_clone (bool uniq = false);

    bool is_colon_equiv (octave_idx_type n) const
      { return start == 0 && step == 1 && len == n; }

    dim_vector orig_dimensions (void) const
      { return dim_vector (1, len); }

    octave_idx_type get_start (void) const { return start; }

    octave_idx_type get_step (void) const { return step; }

    std::ostream& print (std::ostream& os) const;

  private:

    DECLARE_OCTAVE_ALLOCATOR

    // No copying!
    idx_range_rep (const idx_range_rep& idx);

    octave_idx_type start, len, step;

  };

  // The integer scalar index.
  class OCTAVE_API idx_scalar_rep : public idx_base_rep
  {
  public:
    idx_scalar_rep (octave_idx_type i, direct)
      : data (i) { }

    idx_scalar_rep (void)
      : data (0) { }

    // Zero-based constructor.
    idx_scalar_rep (octave_idx_type i);

    template <class T>
    idx_scalar_rep (T x);

    octave_idx_type xelem (octave_idx_type) const
      { return data; }

    octave_idx_type checkelem (octave_idx_type i) const;

    octave_idx_type length (octave_idx_type) const
      { return 1; }

    octave_idx_type extent (octave_idx_type n) const
      { return std::max (n, data + 1); }

    idx_class_type idx_class (void) const { return class_scalar; }

    idx_base_rep *sort_uniq_clone (bool = false)
      { count++; return this; }

    bool is_colon_equiv (octave_idx_type n) const
      { return n == 1 && data == 0; }

    dim_vector orig_dimensions (void) const
      { return dim_vector (1, 1); }

    octave_idx_type get_data (void) const { return data; }

    std::ostream& print (std::ostream& os) const;

  private:

    DECLARE_OCTAVE_ALLOCATOR

    // No copying!
    idx_scalar_rep (const idx_scalar_rep& idx);

    octave_idx_type data;

  };

  // The integer vector index.
  class OCTAVE_API idx_vector_rep : public idx_base_rep
  {
  public:
    // Direct constructor.
    idx_vector_rep (octave_idx_type *_data, octave_idx_type _len, 
                    octave_idx_type _ext, const dim_vector& od, direct)
      : data (_data), len (_len), ext (_ext), aowner (0), orig_dims (od) { }

    idx_vector_rep (void) 
      : data (0), len (0), aowner (0)
      { }

    // Zero-based constructor.
    idx_vector_rep (const Array<octave_idx_type>& inda);

    template <class T>
    idx_vector_rep (const Array<T>&);

    idx_vector_rep (bool);

    idx_vector_rep (const Array<bool>&);

    idx_vector_rep (const Sparse<bool>&);

    ~idx_vector_rep (void);

    octave_idx_type xelem (octave_idx_type i) const
      { return data[i]; }

    octave_idx_type checkelem (octave_idx_type i) const;

    octave_idx_type length (octave_idx_type) const
      { return len; }

    octave_idx_type extent (octave_idx_type n) const
      { return std::max (n, ext); }

    idx_class_type idx_class (void) const { return class_vector; }

    idx_base_rep *sort_uniq_clone (bool uniq = false);

    dim_vector orig_dimensions (void) const
      { return orig_dims; }

    const octave_idx_type *get_data (void) const { return data; }

    std::ostream& print (std::ostream& os) const;

  private:

    DECLARE_OCTAVE_ALLOCATOR

    // No copying!
    idx_vector_rep (const idx_vector_rep& idx);

    const octave_idx_type *data;
    octave_idx_type len, ext;

    // This is a trick to allow user-given zero-based arrays to be used as indices
    // without copying. If the following pointer is nonzero, we do not own the data,
    // but rather have an Array<octave_idx_type> object that provides us the data.
    // Note that we need a pointer because we deferred the Array<T> declaration and
    // we do not want it yet to be defined.
    
    Array<octave_idx_type> *aowner;

    dim_vector orig_dims;
  };


  idx_vector (idx_base_rep *r) : rep (r) { }

  // The shared empty vector representation (for fast default constructor)
  static idx_vector_rep *nil_rep (void)
    {
      static idx_vector_rep ivr;
      return &ivr;
    }

  // The shared empty vector representation with the error flag set.
  static idx_vector_rep *err_rep (void)
    {
      static idx_vector_rep ivr;
      ivr.err = true;
      return &ivr;
    }

  // If there was an error in constructing the rep, replace it with empty vector
  // for safety.
  void chkerr (void)
    {
      if (rep->err)
        {
          if (--rep->count == 0)
            delete rep;
          rep = err_rep ();
          rep->count++;
        }
    }

public:

  // Fast empty constructor.
  idx_vector (void) : rep (nil_rep ()) { rep->count++; }

  // Zero-based constructors (for use from C++).
  idx_vector (octave_idx_type i) : rep (new idx_scalar_rep (i)) 
    { chkerr (); }

  idx_vector (octave_idx_type start, octave_idx_type limit,
              octave_idx_type step = 1)
    : rep (new idx_range_rep (start, limit, step)) 
    { chkerr (); }

  idx_vector (const Array<octave_idx_type>& inda) 
    : rep (new idx_vector_rep (inda))
    { chkerr (); }

  // Colon is best constructed by simply copying (or referencing) this member.
  static const idx_vector colon;

  // or passing ':' here
  idx_vector (char c) : rep (new idx_colon_rep (c)) { chkerr (); }

  // Conversion constructors (used by interpreter).

  template <class T>
  idx_vector (octave_int<T> x) : rep (new idx_scalar_rep (x)) { chkerr (); }

  idx_vector (double x) : rep (new idx_scalar_rep (x)) { chkerr (); }

  idx_vector (float x) : rep (new idx_scalar_rep (x)) { chkerr (); }

  // A scalar bool does not necessarily map to scalar index.
  idx_vector (bool x) : rep (new idx_vector_rep (x)) { chkerr (); }

  template <class T>
  idx_vector (const Array<octave_int<T> >& nda) : rep (new idx_vector_rep (nda))
    { chkerr (); }

  idx_vector (const Array<double>& nda) : rep (new idx_vector_rep (nda))
    { chkerr (); }

  idx_vector (const Array<float>& nda) : rep (new idx_vector_rep (nda))
    { chkerr (); }

  idx_vector (const Array<bool>& nda) : rep (new idx_vector_rep (nda))
    { chkerr (); }

  idx_vector (const Range& r) 
    : rep (new idx_range_rep (r))
    { chkerr (); }

  idx_vector (const Sparse<bool>& nda) : rep (new idx_vector_rep (nda))
    { chkerr (); }

  idx_vector (const idx_vector& a) : rep (a.rep) { rep->count++; }

  ~idx_vector (void)
    {
      if (--rep->count == 0)
	delete rep;
    }

  idx_vector& operator = (const idx_vector& a)
    {
      if (this != &a)
	{
	  if (--rep->count == 0)
	    delete rep;

	  rep = a.rep;
	  rep->count++;
	}
      return *this;
    }

  idx_class_type idx_class (void) const { return rep->idx_class (); }

  octave_idx_type length (octave_idx_type n = 0) const 
    { return rep->length (n); }

  octave_idx_type extent (octave_idx_type n) const 
    { return rep->extent (n); }

  octave_idx_type xelem (octave_idx_type n) const 
    { return rep->xelem (n); }

  octave_idx_type checkelem (octave_idx_type n) const 
    { return rep->checkelem (n); }

  octave_idx_type operator () (octave_idx_type n) const 
    {
#if defined (BOUNDS_CHECKING)
      return rep->checkelem (n); 
#else
      return rep->xelem (n);
#endif
    }

  operator bool (void) const
    { return ! rep->err; }

  bool is_colon (void) const 
    { return rep->idx_class () == class_colon; }

  bool is_scalar (void) const 
    { return rep->idx_class () == class_scalar; }

  bool is_colon_equiv (octave_idx_type n) const
    { return rep->is_colon_equiv (n); }

  idx_vector sorted (bool uniq = false) const
    { return idx_vector (rep->sort_uniq_clone (uniq)); }

  dim_vector orig_dimensions (void) const { return rep->orig_dimensions (); }

  octave_idx_type orig_rows (void) const
    { return orig_dimensions () (0); }

  octave_idx_type orig_columns (void) const
    { return orig_dimensions () (1); }

  int orig_empty (void) const
    { return (! is_colon () && orig_dimensions().any_zero ()); }

  // i/o

  std::ostream& print (std::ostream& os) const { return rep->print (os); }

  friend std::ostream& operator << (std::ostream& os, const idx_vector& a)
    { return a.print (os); }

  // Slice with specializations. No checking of bounds!
  //
  // This is equivalent to the following loop (but much faster):
  //
  // for (octave_idx_type i = 0; i < idx->length (n); i++)
  //   dest[i] = src[idx(i)];
  // return i;
  //
  template <class T>
  octave_idx_type
  index (const T *src, octave_idx_type n, T *dest) const
    {
      octave_idx_type len = rep->length (n);
      switch (rep->idx_class ())
        {
        case class_colon:
          std::copy (src, src + len, dest);
          break;
        case class_range:
          {
            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
            octave_idx_type start = r->get_start (), step = r->get_step ();
            const T *ssrc = src + start;
            if (step == 1)
              std::copy (ssrc, ssrc + len, dest);
            else if (step == -1)
              std::reverse_copy (ssrc - len + 1, ssrc + 1, dest);
            else if (step == 0)
              std::fill_n (dest, len, *ssrc);
            else
              {
                for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
                  dest[i] = ssrc[j];
              }
          }
          break;
        case class_scalar:
          {
            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
            dest[0] = src[r->get_data ()];
          }
          break;
        case class_vector:
          {
            idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
            const octave_idx_type *data = r->get_data ();
            for (octave_idx_type i = 0; i < len; i++)
              dest[i] = src[data[i]];
          }
          break;
        default:
          assert (false);
          break;
        }

      return len;
    }

  // Slice assignment with specializations. No checking of bounds!
  //
  // This is equivalent to the following loop (but much faster):
  //
  // for (octave_idx_type i = 0; i < idx->length (n); i++)
  //   dest[idx(i)] = src[i];
  // return i;
  //
  template <class T>
  octave_idx_type
  assign (const T *src, octave_idx_type n, T *dest) const
    {
      octave_idx_type len = rep->length (n);
      switch (rep->idx_class ())
        {
        case class_colon:
          std::copy (src, src + len, dest);
          break;
        case class_range:
          {
            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
            octave_idx_type start = r->get_start (), step = r->get_step ();
            T *sdest = dest + start;
            if (step == 1)
              std::copy (src, src + len, sdest);
            else if (step == -1)
              std::reverse_copy (src, src + len, sdest - len + 1);
            else
              {
                for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
                  sdest[j] = src[i];
              }
          }
          break;
        case class_scalar:
          {
            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
            dest[r->get_data ()] = src[0];
          }
          break;
        case class_vector:
          {
            idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
            const octave_idx_type *data = r->get_data ();
            for (octave_idx_type i = 0; i < len; i++)
              dest[data[i]] = src[i];
          }
          break;
        default:
          assert (false);
          break;
        }

      return len;
    }

  // Slice fill with specializations. No checking of bounds!
  //
  // This is equivalent to the following loop (but much faster):
  //
  // for (octave_idx_type i = 0; i < idx->length (n); i++)
  //   dest[idx(i)] = val;
  // return i;
  //
  template <class T>
  octave_idx_type
  fill (const T& val, octave_idx_type n, T *dest) const
    {
      octave_idx_type len = rep->length (n);
      switch (rep->idx_class ())
        {
        case class_colon:
          std::fill (dest, dest + len, val);
          break;
        case class_range:
          {
            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
            octave_idx_type start = r->get_start (), step = r->get_step ();
            T *sdest = dest + start;
            if (step == 1)
              std::fill (sdest, sdest + len, val);
            else if (step == -1)
              std::fill (sdest - len + 1, sdest + 1, val);
            else
              {
                for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
                  sdest[j] = val;
              }
          }
          break;
        case class_scalar:
          {
            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
            dest[r->get_data ()] = val;
          }
          break;
        case class_vector:
          {
            idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
            const octave_idx_type *data = r->get_data ();
            for (octave_idx_type i = 0; i < len; i++)
              dest[data[i]] = val;
          }
          break;
        default:
          assert (false);
          break;
        }

      return len;
    }

  // Generic non-breakable indexed loop. The loop body should be encapsulated in a
  // single functor body. 
  // This is equivalent to the following loop (but faster, at least for simple
  // inlined bodies):
  //
  // for (octave_idx_type i = 0; i < idx->length (n); i++) body (idx(i));
  // 

  template <class Functor>
  void
  loop (octave_idx_type n, Functor body) const
    {
      octave_idx_type len = rep->length (n);
      switch (rep->idx_class ())
        {
        case class_colon:
          for (octave_idx_type i = 0; i < len; i++) body (i);
          break;
        case class_range:
          {
            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
            octave_idx_type start = r->get_start (), step = r->get_step ();
            octave_idx_type i, j;
            if (step == 1)
              for (i = start, j = start + len; i < j; i++) body (i);
            else if (step == -1)
              for (i = start, j = start - len; i > j; i--) body (i);
            else
              for (i = 0, j = start; i < len; i++, j += step) body (j);
          }
          break;
        case class_scalar:
          {
            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
            body (r->get_data ());
          }
          break;
        case class_vector:
          {
            idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
            const octave_idx_type *data = r->get_data ();
            for (octave_idx_type i = 0; i < len; i++) body (data[i]);
          }
          break;
        default:
          assert (false);
          break;
        }

    }

  // Generic breakable indexed loop. The loop body should be encapsulated in a
  // single functor body. 
  // This is equivalent to the following loop (but faster, at least for simple
  // inlined bodies):
  //
  // for (octave_idx_type i = 0; i < idx->length (n); i++)
  //   if (body (idx(i))) break;
  // return i;
  // 

  template <class Functor>
  octave_idx_type
  bloop (octave_idx_type n, Functor body) const
    {
      octave_idx_type len = rep->length (n), ret;
      switch (rep->idx_class ())
        {
        case class_colon:
          {
            octave_idx_type i;
            for (i = 0; i < len && body (i); i++) ;
            ret = i;
          }
          break;
        case class_range:
          {
            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
            octave_idx_type start = r->get_start (), step = r->get_step ();
            octave_idx_type i, j;
            if (step == 1)
              for (i = start, j = start + len; i < j && body (i); i++) ;
            else if (step == -1)
              for (i = start, j = start - len; i > j && body (i); i--) ;
            else
              for (i = 0, j = start; i < len && body (j); i++, j += step) ;
            ret = i;
          }
          break;
        case class_scalar:
          {
            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
            ret = body (r->get_data ()) ? 1 : 0;
          }
          break;
        case class_vector:
          {
            idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
            const octave_idx_type *data = r->get_data ();
            octave_idx_type i;
            for (i = 0; i < len && body (data[i]); i++) ;
            ret = i;
          }
          break;
        default:
          assert (false);
          break;
        }

      return ret;
    }

  // Rationale: 
  // This method is the key to "smart indexing". When indexing cartesian
  // arrays, sometimes consecutive index vectors can be reduced into a single
  // index. If rows (A) = k and i.maybe_reduce (j) gives k, then A(i,j)(:) is
  // equal to A(k)(:).

  // If the next index can be reduced, returns true and updates this.
  bool maybe_reduce (octave_idx_type n, const idx_vector& j,
                     octave_idx_type nj);

  bool is_cont_range (octave_idx_type n,
                      octave_idx_type& l, octave_idx_type& u) const;

  idx_vector
  complement (octave_idx_type n) const;

  bool is_permutation (octave_idx_type n) const;

  // FIXME -- these are here for compatibility.  They should be removed
  // when no longer in use.

  octave_idx_type elem (octave_idx_type n) const 
    { return (*this) (n); }

  bool is_colon_equiv (octave_idx_type n, int) const
    { return is_colon_equiv (n); }

  octave_idx_type
  freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false);

  void sort (bool uniq = false)
    { *this = sorted (uniq); }

  octave_idx_type ones_count (void) const;

  octave_idx_type max (void) const { return extent (1) - 1; }
  
private:

  idx_base_rep *rep;

};

#endif

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/