GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
idx-vector.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 Copyright (C) 2008-2009 Jaroslav Hajek
5 Copyright (C) 2009-2010 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 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <cstdlib>
30 
31 #include <iostream>
32 
33 #include "idx-vector.h"
34 #include "Array.h"
35 #include "Array-util.h"
36 #include "Sparse.h"
37 #include "Range.h"
38 
39 #include "oct-locbuf.h"
40 #include "lo-error.h"
41 #include "lo-mappers.h"
42 
43 static void
45 {
46  (*current_liboctave_error_handler)
47  ("invalid range used as index");
48 }
49 
50 static void
52 {
53  (*current_liboctave_error_handler)
54  ("internal error: idx_vector index out of range");
55 }
56 
59 {
60  (*current_liboctave_error_handler)
61  ("internal error: as_array not allowed for this index class");
62 
63  return Array<octave_idx_type> ();
64 }
65 
67 
69 {
70  if (c != ':')
71  {
72  (*current_liboctave_error_handler)
73  ("internal error: invalid character converted to idx_vector; must be ':'");
74  err = true;
75  }
76 }
77 
80 {
81  if (i < 0)
82  {
84  return 0;
85  }
86  else
87  return i;
88 }
89 
92 {
93  (*current_liboctave_error_handler)
94  ("internal error: idx_colon_rep::sort_idx");
95 
96  count++;
97  return this;
98 }
99 
100 std::ostream&
101 idx_vector::idx_colon_rep::print (std::ostream& os) const
102 {
103  return os << ":";
104 }
105 
107 
109  octave_idx_type _limit,
110  octave_idx_type _step)
111  : start(_start), len (_step ? std::max ((_limit - _start) / _step, static_cast<octave_idx_type> (0)) : -1), step (_step)
112 {
113  if (len < 0)
114  {
116  err = true;
117  }
118  else if (start < 0 || (step < 0 && start + (len-1)*step < 0))
119  {
121  err = true;
122  }
123 }
124 
126  : start (0), len (r.nelem ()), step (1)
127 {
128  if (len < 0)
129  {
131  err = true;
132  }
133  else if (len > 0)
134  {
135  if (r.all_elements_are_ints ())
136  {
137  start = static_cast<octave_idx_type> (r.base ()) - 1;
138  step = static_cast<octave_idx_type> (r.inc ());
139  if (start < 0 || (step < 0 && start + (len-1)*step < 0))
140  {
142  err = true;
143  }
144  }
145  else
146  {
148  err = true;
149  }
150  }
151 }
152 
155 {
156  if (i < 0 || i >= len)
157  {
159  return 0;
160  }
161  else
162  return start + i*step;
163 }
164 
167 {
168  if (step < 0)
169  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
170  else
171  {
172  count++;
173  return this;
174  }
175 }
176 
179 {
180  if (step < 0 && len > 0)
181  {
182  idx.clear (1, len);
183  for (octave_idx_type i = 0; i < len; i++)
184  idx.xelem (i) = len - 1 - i;
185  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
186  }
187  else
188  {
189  idx.clear (1, len);
190  for (octave_idx_type i = 0; i < len; i++)
191  idx.xelem (i) = i;
192  count++;
193  return this;
194  }
195 }
196 
197 std::ostream&
198 idx_vector::idx_range_rep::print (std::ostream& os) const
199 {
200  os << start << ':' << step << ':' << start + len*step;
201  return os;
202 }
203 
204 Range
206 {
207  return Range (static_cast<double> (start+1),
208  static_cast<double> (step), len);
209 }
210 
213 {
214  Array<octave_idx_type> retval (dim_vector (1, len));
215  for (octave_idx_type i = 0; i < len; i++)
216  retval.xelem (i) = start + i*step;
217 
218  return retval;
219 }
220 
221 inline octave_idx_type
222 convert_index (octave_idx_type i, bool& conv_error,
223  octave_idx_type& ext)
224 {
225  if (i <= 0)
226  conv_error = true;
227 
228  if (ext < i)
229  ext = i;
230 
231  return i - 1;
232 }
233 
234 inline octave_idx_type
235 convert_index (double x, bool& conv_error, octave_idx_type& ext)
236 {
237  octave_idx_type i = static_cast<octave_idx_type> (x);
238 
239  if (static_cast<double> (i) != x)
240  conv_error = true;
241 
242  return convert_index (i, conv_error, ext);
243 }
244 
245 inline octave_idx_type
246 convert_index (float x, bool& conv_error, octave_idx_type& ext)
247 {
248  return convert_index (static_cast<double> (x), conv_error, ext);
249 }
250 
251 template <class T>
252 inline octave_idx_type
253 convert_index (octave_int<T> x, bool& conv_error,
254  octave_idx_type& ext)
255 {
257 
258  return convert_index (i, conv_error, ext);
259 }
260 
262 
263 template <class T>
265  : data (0)
266 {
267  octave_idx_type dummy = 0;
268 
269  data = convert_index (x, err, dummy);
270 
271  if (err)
273 }
274 
276  : data (i)
277 {
278  if (data < 0)
279  {
281  err = true;
282  }
283 }
284 
287 {
288  if (i != 0)
290 
291  return data;
292 }
293 
296 {
297  idx.clear (1, 1);
298  idx.fill (0);
299  count++;
300  return this;
301 }
302 
303 std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const
304 {
305  return os << data;
306 }
307 
308 double
310 {
311  return data + 1;
312 }
313 
316 {
317  return Array<octave_idx_type> (dim_vector (1, 1), data);
318 }
319 
321 
322 template <class T>
324  : data (0), len (nda.numel ()), ext (0), aowner (0), orig_dims (nda.dims ())
325 {
326  if (len != 0)
327  {
329  for (octave_idx_type i = 0; i < len; i++)
330  d[i] = convert_index (nda.xelem (i), err, ext);
331  data = d;
332 
333  if (err)
334  {
335  delete [] data;
337  }
338  }
339 }
340 
341 // Note that this makes a shallow copy of the index array.
342 
344  : data (inda.data ()), len (inda.numel ()), ext (0),
345  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
346 {
347  if (len != 0)
348  {
349  octave_idx_type max = -1;
350  for (octave_idx_type i = 0; i < len; i++)
351  {
352  octave_idx_type k = inda.xelem (i);
353  if (k < 0)
354  err = true;
355  else if (k > max)
356  max = k;
357  }
358 
359  ext = max + 1;
360 
361  if (err)
363  }
364 }
365 
367  octave_idx_type _ext, direct)
368  : data (inda.data ()), len (inda.numel ()), ext (_ext),
369  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
370 {
371  // No checking.
372  if (ext < 0)
373  {
374  octave_idx_type max = -1;
375  for (octave_idx_type i = 0; i < len; i++)
376  if (data[i] > max)
377  max = data[i];
378 
379  ext = max + 1;
380  }
381 }
382 
384  : data (0), len (b ? 1 : 0), ext (0), aowner (0), orig_dims (len, len)
385 {
386  if (len != 0)
387  {
388  octave_idx_type *d = new octave_idx_type [1];
389  d[0] = 0;
390  data = d;
391  ext = 1;
392  }
393 }
394 
397  : data (0), len (nnz), ext (0), aowner (0), orig_dims ()
398 {
399  if (nnz < 0)
400  len = bnda.nnz ();
401 
402  const dim_vector dv = bnda.dims ();
403 
404  if (! dv.all_zero ())
405  orig_dims = ((dv.length () == 2 && dv(0) == 1)
406  ? dim_vector (1, len) : dim_vector (len, 1));
407 
408  if (len != 0)
409  {
411 
412  octave_idx_type ntot = bnda.length ();
413 
414  octave_idx_type k = 0;
415  for (octave_idx_type i = 0; i < ntot; i++)
416  if (bnda.xelem (i))
417  d[k++] = i;
418 
419  data = d;
420 
421  ext = d[k-1] + 1;
422  }
423 }
424 
426  : data (0), len (bnda.nnz ()), ext (0), aowner (0), orig_dims ()
427 {
428  const dim_vector dv = bnda.dims ();
429 
430  if (! dv.all_zero ())
431  orig_dims = ((dv.length () == 2 && dv(0) == 1)
432  ? dim_vector (1, len) : dim_vector (len, 1));
433 
434  if (len != 0)
435  {
437 
438  octave_idx_type k = 0;
439  octave_idx_type nc = bnda.cols ();
440  octave_idx_type nr = bnda.rows ();
441 
442  for (octave_idx_type j = 0; j < nc; j++)
443  for (octave_idx_type i = bnda.cidx(j); i < bnda.cidx(j+1); i++)
444  if (bnda.data (i))
445  d[k++] = j * nr + bnda.ridx (i);
446 
447  data = d;
448 
449  ext = d[k-1] + 1;
450  }
451 }
452 
454 {
455  if (aowner)
456  delete aowner;
457  else
458  delete [] data;
459 }
460 
463 {
464  if (n < 0 || n >= len)
465  {
467  return 0;
468  }
469 
470  return xelem (n);
471 }
472 
475 {
476  if (len == 0)
477  {
478  count++;
479  return this;
480  }
481 
482  // This is wrapped in auto_ptr so that we don't leak on out-of-memory.
483  std::auto_ptr<idx_vector_rep> new_rep (
484  new idx_vector_rep (0, len, ext, orig_dims, DIRECT));
485 
486  if (ext > len*xlog2 (1.0 + len))
487  {
488  // Use standard sort via octave_sort.
489  octave_idx_type *new_data = new octave_idx_type [len];
490  new_rep->data = new_data;
491 
492  std::copy (data, data + len, new_data);
494  lsort.set_compare (ASCENDING);
495  lsort.sort (new_data, len);
496 
497  if (uniq)
498  {
499  octave_idx_type new_len = std::unique (new_data, new_data + len)
500  - new_data;
501  new_rep->len = new_len;
502  if (new_rep->orig_dims.length () == 2 && new_rep->orig_dims(0) == 1)
503  new_rep->orig_dims = dim_vector (1, new_len);
504  else
505  new_rep->orig_dims = dim_vector (new_len, 1);
506  }
507  }
508  else if (uniq)
509  {
510  // Use two-pass bucket sort (only a mask array needed).
511  OCTAVE_LOCAL_BUFFER_INIT (bool, has, ext, false);
512  for (octave_idx_type i = 0; i < len; i++)
513  has[data[i]] = true;
514 
515  octave_idx_type new_len = 0;
516  for (octave_idx_type i = 0; i < ext; i++)
517  new_len += has[i];
518 
519  new_rep->len = new_len;
520  if (new_rep->orig_dims.length () == 2 && new_rep->orig_dims(0) == 1)
521  new_rep->orig_dims = dim_vector (1, new_len);
522  else
523  new_rep->orig_dims = dim_vector (new_len, 1);
524 
525  octave_idx_type *new_data = new octave_idx_type [new_len];
526  new_rep->data = new_data;
527 
528  for (octave_idx_type i = 0, j = 0; i < ext; i++)
529  if (has[i])
530  new_data[j++] = i;
531  }
532  else
533  {
534  // Use two-pass bucket sort.
536  for (octave_idx_type i = 0; i < len; i++)
537  cnt[data[i]]++;
538 
539  octave_idx_type *new_data = new octave_idx_type [len];
540  new_rep->data = new_data;
541 
542  for (octave_idx_type i = 0, j = 0; i < ext; i++)
543  {
544  for (octave_idx_type k = 0; k < cnt[i]; k++)
545  new_data[j++] = i;
546  }
547  }
548 
549  return new_rep.release ();
550 }
551 
554 {
555  // This is wrapped in auto_ptr so that we don't leak on out-of-memory.
556  std::auto_ptr<idx_vector_rep> new_rep (
557  new idx_vector_rep (0, len, ext, orig_dims, DIRECT));
558 
559  if (ext > len*xlog2 (1.0 + len))
560  {
561  // Use standard sort via octave_sort.
562  idx.clear (orig_dims);
563  octave_idx_type *idx_data = idx.fortran_vec ();
564  for (octave_idx_type i = 0; i < len; i++)
565  idx_data[i] = i;
566 
567  octave_idx_type *new_data = new octave_idx_type [len];
568  new_rep->data = new_data;
569  std::copy (data, data + len, new_data);
570 
572  lsort.set_compare (ASCENDING);
573  lsort.sort (new_data, idx_data, len);
574  }
575  else
576  {
577  // Use two-pass bucket sort.
579 
580  for (octave_idx_type i = 0; i < len; i++)
581  cnt[data[i]]++;
582 
583  idx.clear (orig_dims);
584  octave_idx_type *idx_data = idx.fortran_vec ();
585 
586  octave_idx_type *new_data = new octave_idx_type [len];
587  new_rep->data = new_data;
588 
589  for (octave_idx_type i = 0, k = 0; i < ext; i++)
590  {
591  octave_idx_type j = cnt[i];
592  cnt[i] = k;
593  k += j;
594  }
595 
596  for (octave_idx_type i = 0; i < len; i++)
597  {
598  octave_idx_type j = data[i], k = cnt[j]++;
599  new_data[k] = j;
600  idx_data[k] = i;
601  }
602  }
603 
604  return new_rep.release ();
605 }
606 
607 std::ostream&
608 idx_vector::idx_vector_rep::print (std::ostream& os) const
609 {
610  os << '[';
611 
612  for (octave_idx_type ii = 0; ii < len - 1; ii++)
613  os << data[ii] << ',' << ' ';
614 
615  if (len > 0)
616  os << data[len-1]; os << ']';
617 
618  return os;
619 }
620 
623 {
624  Array<double> retval (orig_dims);
625  for (octave_idx_type i = 0; i < len; i++)
626  retval.xelem (i) = data[i] + 1;
627  return retval;
628 }
629 
632 {
633  if (aowner)
634  return *aowner;
635  else
636  {
637  Array<octave_idx_type> retval (orig_dims);
638  std::memcpy (retval.fortran_vec (), data, len*sizeof (octave_idx_type));
639  // Delete the old copy and share the data instead to save memory.
640  delete [] data;
641  data = retval.fortran_vec ();
642  aowner = new Array<octave_idx_type> (retval);
643  return retval;
644  }
645 }
646 
648 
650  : data (0), len (b ? 1 : 0), ext (0), lsti (-1), lste (-1),
651  aowner (0), orig_dims (len, len)
652 {
653  if (len != 0)
654  {
655  bool *d = new bool [1];
656  d[0] = true;
657  data = d;
658  ext = 1;
659  }
660 }
661 
664  : data (0), len (nnz), ext (bnda.numel ()), lsti (-1), lste (-1),
665  aowner (0), orig_dims ()
666 {
667  if (nnz < 0)
668  len = bnda.nnz ();
669 
670  // We truncate the extent as much as possible. For Matlab
671  // compatibility, but maybe it's not a bad idea anyway.
672  while (ext > 0 && ! bnda(ext-1))
673  ext--;
674 
675  const dim_vector dv = bnda.dims ();
676 
677  if (! dv.all_zero ())
678  orig_dims = ((dv.length () == 2 && dv(0) == 1)
679  ? dim_vector (1, len) : dim_vector (len, 1));
680 
681  aowner = new Array<bool> (bnda);
682  data = bnda.data ();
683 }
684 
686 {
687  if (aowner)
688  delete aowner;
689  else
690  delete [] data;
691 }
692 
695 {
696  if (n == lsti + 1)
697  {
698  lsti = n;
699  while (! data[++lste]) ;
700  }
701  else
702  {
703  lsti = n++;
704  lste = -1;
705  while (n > 0)
706  if (data[++lste]) --n;
707  }
708  return lste;
709 }
710 
713 {
714  if (n < 0 || n >= len)
715  {
717  return 0;
718  }
719 
720  return xelem (n);
721 }
722 
723 std::ostream&
724 idx_vector::idx_mask_rep::print (std::ostream& os) const
725 {
726  os << '[';
727 
728  for (octave_idx_type ii = 0; ii < ext - 1; ii++)
729  os << data[ii] << ',' << ' ';
730 
731  if (ext > 0)
732  os << data[ext-1]; os << ']';
733 
734  return os;
735 }
736 
739 {
740  if (aowner)
741  return *aowner;
742  else
743  {
744  Array<bool> retval (dim_vector (ext, 1));
745  for (octave_idx_type i = 0; i < ext; i++)
746  retval.xelem (i) = data[i];
747  return retval;
748  }
749 }
750 
753 {
754  if (aowner)
755  return aowner->find ().reshape (orig_dims);
756  else
757  {
758  Array<bool> retval (orig_dims);
759  for (octave_idx_type i = 0, j = 0; i < ext; i++)
760  if (data[i])
761  retval.xelem (j++) = i;
762 
763  return retval;
764  }
765 }
766 
769 {
770  idx.clear (len, 1);
771  for (octave_idx_type i = 0; i < len; i++)
772  idx.xelem (i) = i;
773 
774  count++;
775  return this;
776 }
777 
779 
781  : rep (0)
782 {
783  // Convert only if it means saving at least half the memory.
784  static const int factor = (2 * sizeof (octave_idx_type));
785  octave_idx_type nnz = bnda.nnz ();
786  if (nnz <= bnda.numel () / factor)
787  rep = new idx_vector_rep (bnda, nnz);
788  else
789  rep = new idx_mask_rep (bnda, nnz);
790 }
791 
792 bool
794  octave_idx_type nj)
795 {
796  bool reduced = false;
797 
798  // Empty index always reduces.
799  if (rep->length (n) == 0)
800  {
801  *this = idx_vector ();
802  return true;
803  }
804 
805  // Possibly skip singleton dims.
806  if (n == 1 && rep->is_colon_equiv (n))
807  {
808  *this = j;
809  return true;
810  }
811 
812  if (nj == 1 && j.is_colon_equiv (nj))
813  return true;
814 
815  switch (j.idx_class ())
816  {
817  case class_colon:
818  switch (rep->idx_class ())
819  {
820  case class_colon:
821  // (:,:) reduces to (:)
822  reduced = true;
823  break;
824 
825  case class_scalar:
826  {
827  // (i,:) reduces to a range.
828  idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
829  octave_idx_type k = r->get_data ();
830  *this = new idx_range_rep (k, nj, n, DIRECT);
831  reduced = true;
832  }
833  break;
834 
835  case class_range:
836  {
837  // (i:k:end,:) reduces to a range if i <= k and k divides n.
838  idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
839  octave_idx_type s = r->get_start (), l = r->length (n);
840  octave_idx_type t = r->get_step ();
841  if (l*t == n)
842  {
843  *this = new idx_range_rep (s, l * nj, t, DIRECT);
844  reduced = true;
845  }
846  }
847  break;
848 
849  default:
850  break;
851  }
852  break;
853 
854  case class_range:
855  switch (rep->idx_class ())
856  {
857  case class_colon:
858  {
859  // (:,i:j) reduces to a range (the step must be 1)
860  idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
861  if (rj->get_step () == 1)
862  {
863  octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
864  *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);
865  reduced = true;
866  }
867  }
868  break;
869 
870  case class_scalar:
871  {
872  // (k,i:d:j) reduces to a range.
873  idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
874  idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
875  octave_idx_type k = r->get_data ();
876  octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
877  octave_idx_type tj = rj->get_step ();
878  *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
879  reduced = true;
880  }
881  break;
882 
883  case class_range:
884  {
885  // (i:k:end,p:q) reduces to a range if i <= k and k divides n.
886  // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n))
887  idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
888  octave_idx_type s = r->get_start (), l = r->length (n);
889  octave_idx_type t = r->get_step ();
890  idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
891  octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
892  octave_idx_type tj = rj->get_step ();
893  if ((l*t == n && tj == 1) || (t == 0 && tj == 0))
894  {
895  *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
896  reduced = true;
897  }
898  }
899  break;
900 
901  default:
902  break;
903  }
904  break;
905 
906  case class_scalar:
907  switch (rep->idx_class ())
908  {
909  case class_scalar:
910  {
911  // (i,j) reduces to a single index.
912  idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
913  idx_scalar_rep * rj = dynamic_cast<idx_scalar_rep *> (j.rep);
914  octave_idx_type k = r->get_data () + n * rj->get_data ();
915  *this = new idx_scalar_rep (k, DIRECT);
916  reduced = true;
917  }
918  break;
919 
920  case class_range:
921  {
922  // (i:d:j,k) reduces to a range.
923  idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
924  idx_scalar_rep * rj = dynamic_cast<idx_scalar_rep *> (j.rep);
925  octave_idx_type s = r->get_start (), l = r->length (nj);
926  octave_idx_type t = r->get_step ();
927  octave_idx_type k = rj->get_data ();
928  *this = new idx_range_rep (n * k + s, l, t, DIRECT);
929  reduced = true;
930  }
931  break;
932 
933  case class_colon:
934  {
935  // (:,k) reduces to a range.
936  idx_scalar_rep * rj = dynamic_cast<idx_scalar_rep *> (j.rep);
937  octave_idx_type k = rj->get_data ();
938  *this = new idx_range_rep (n * k, n, 1, DIRECT);
939  reduced = true;
940  }
941  break;
942 
943  default:
944  break;
945  }
946  break;
947 
948  default:
949  break;
950  }
951 
952  return reduced;
953 }
954 
955 bool
957  octave_idx_type& l, octave_idx_type& u) const
958 {
959  bool res = false;
960 
961  switch (rep->idx_class ())
962  {
963  case class_colon:
964  l = 0; u = n;
965  res = true;
966  break;
967 
968  case class_range:
969  {
970  idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
971  if (r->get_step () == 1)
972  {
973  l = r->get_start ();
974  u = l + r->length (n);
975  res = true;
976  }
977  }
978  break;
979 
980  case class_scalar:
981  {
982  idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
983  l = r->get_data ();
984  u = l + 1;
985  res = true;
986  }
987  break;
988 
989  case class_mask:
990  {
991  idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep);
992  octave_idx_type ext = r->extent (0), len = r->length (0);
993  if (ext == len)
994  {
995  l = 0;
996  u = len;
997  res = true;
998  }
999  }
1000 
1001  default:
1002  break;
1003  }
1004 
1005  return res;
1006 }
1007 
1010 {
1011  octave_idx_type retval = 0;
1012 
1013  switch (rep->idx_class ())
1014  {
1015  case class_colon:
1016  retval = 1;
1017  break;
1018 
1019  case class_range:
1020  retval = dynamic_cast<idx_range_rep *> (rep) -> get_step ();
1021  break;
1022 
1023  case class_vector:
1024  case class_mask:
1025  {
1026  if (length (0) > 1)
1027  retval = elem (1) - elem (0);
1028  }
1029  break;
1030 
1031  default:
1032  break;
1033  }
1034 
1035  return retval;
1036 }
1037 
1038 const octave_idx_type *
1040 {
1041  if (rep->idx_class () != class_vector)
1042  *this = idx_vector (as_array (), extent (0));
1043 
1044  idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
1045 
1046  assert (r != 0);
1047 
1048  return r->get_data ();
1049 }
1050 
1051 void
1053 {
1054  octave_idx_type len = rep->length (0);
1055 
1056  switch (rep->idx_class ())
1057  {
1058  case class_colon:
1059  current_liboctave_error_handler ("colon not allowed");
1060  break;
1061 
1062  case class_range:
1063  {
1064  idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
1065  octave_idx_type start = r->get_start (), step = r->get_step ();
1066  octave_idx_type i, j;
1067  if (step == 1)
1068  for (i = start, j = start + len; i < j; i++) *data++ = i;
1069  else if (step == -1)
1070  for (i = start, j = start - len; i > j; i--) *data++ = i;
1071  else
1072  for (i = 0, j = start; i < len; i++, j += step) *data++ = j;
1073  }
1074  break;
1075 
1076  case class_scalar:
1077  {
1078  idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
1079  *data = r->get_data ();
1080  }
1081  break;
1082 
1083  case class_vector:
1084  {
1085  idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
1086  const octave_idx_type *rdata = r->get_data ();
1087  copy_or_memcpy (len, rdata, data);
1088  }
1089  break;
1090 
1091  case class_mask:
1092  {
1093  idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep);
1094  const bool *mask = r->get_data ();
1095  octave_idx_type ext = r->extent (0);
1096  for (octave_idx_type i = 0, j = 0; i < ext; i++)
1097  if (mask[i])
1098  data[j++] = i;
1099  }
1100  break;
1101 
1102  default:
1103  assert (false);
1104  break;
1105  }
1106 }
1107 
1108 idx_vector
1110 {
1111  idx_vector retval;
1112  if (extent (n) > n)
1113  (*current_liboctave_error_handler)
1114  ("internal error: out of range complement index requested");
1115 
1116  if (idx_class () == class_mask)
1117  {
1118  idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep);
1119  octave_idx_type nz = r->length (0), ext = r->extent (0);
1120  Array<bool> mask (dim_vector (n, 1));
1121  const bool *data = r->get_data ();
1122  bool *ndata = mask.fortran_vec ();
1123  for (octave_idx_type i = 0; i < ext; i++)
1124  ndata[i] = ! data[i];
1125  for (octave_idx_type i = ext; i < n; i++)
1126  ndata[i] = true;
1127  retval = new idx_mask_rep (mask, n - nz);
1128  }
1129  else
1130  {
1131  Array<bool> mask (dim_vector (n, 1), true);
1132  fill (false, length (n), mask.fortran_vec ());
1133  retval = idx_vector (mask);
1134  }
1135 
1136  return retval;
1137 }
1138 
1139 bool
1141 {
1142  bool retval = false;
1143 
1144  if (is_colon_equiv (n))
1145  retval = true;
1146  else if (length(n) == n && extent(n) == n)
1147  {
1148  OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true);
1149 
1150  retval = true;
1151 
1152  for (octave_idx_type i = 0, len = length (); i < len; i++)
1153  {
1154  octave_idx_type k = xelem (i);
1155  if (left[k])
1156  left[k] = false;
1157  else
1158  {
1159  retval = false;
1160  break;
1161  }
1162  }
1163  }
1164 
1165  return retval;
1166 }
1167 
1168 idx_vector
1170 {
1171  assert (n == length (n));
1172 
1173  idx_vector retval;
1174 
1175  switch (idx_class ())
1176  {
1177  case class_range:
1178  {
1179  if (increment () == -1)
1180  retval = sorted ();
1181  else
1182  retval = *this;
1183  break;
1184  }
1185  case class_vector:
1186  {
1187  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1188  const octave_idx_type *ri = r->get_data ();
1190  for (octave_idx_type i = 0; i < n; i++)
1191  idx.xelem (ri[i]) = i;
1192  retval = new idx_vector_rep (idx, r->extent (0), DIRECT);
1193  break;
1194  }
1195  default:
1196  retval = *this;
1197  break;
1198  }
1199 
1200  return retval;
1201 }
1202 
1203 idx_vector
1205 {
1206  if (idx_class () == class_mask)
1207  {
1208  idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep);
1209  const bool *data = r->get_data ();
1210  octave_idx_type ext = r->extent (0), len = r->length (0);
1211  octave_idx_type *idata = new octave_idx_type [len];
1212 
1213  for (octave_idx_type i = 0, j = 0; i < ext; i++)
1214  if (data[i])
1215  idata[j++] = i;
1216 
1217  ext = len > 0 ? idata[len - 1] + 1 : 0;
1218 
1219  return new idx_vector_rep (idata, len, ext, r->orig_dimensions (),
1220  DIRECT);
1221  }
1222  else
1223  return *this;
1224 }
1225 
1227  double& scalar, Range& range,
1228  Array<double>& array, Array<bool>& mask) const
1229 {
1230  iclass = idx_class ();
1231  switch (iclass)
1232  {
1233  case class_colon:
1234  break;
1235 
1236  case class_range:
1237  {
1238  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
1239  range = r->unconvert ();
1240  }
1241  break;
1242 
1243  case class_scalar:
1244  {
1245  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
1246  scalar = r->unconvert ();
1247  }
1248  break;
1249 
1250  case class_vector:
1251  {
1252  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1253  array = r->unconvert ();
1254  }
1255  break;
1256 
1257  case class_mask:
1258  {
1259  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1260  mask = r->unconvert ();
1261  }
1262  break;
1263 
1264  default:
1265  assert (false);
1266  break;
1267  }
1268 }
1269 
1272 {
1273  return rep->as_array ();
1274 }
1275 
1276 bool
1278 {
1279  return idx_class () != class_vector || orig_dimensions ().is_vector ();
1280 }
1281 
1283 idx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok)
1284 {
1285  if (! resize_ok && extent (z_len) > z_len)
1286  {
1287  (*current_liboctave_error_handler)
1288  ("invalid matrix index = %d", extent (z_len));
1289  rep->err = true;
1290  chkerr ();
1291  }
1292 
1293  return length (z_len);
1294 }
1295 
1298 {
1299  octave_idx_type n = 0;
1300 
1301  if (is_colon ())
1302  n = 1;
1303  else
1304  {
1305  for (octave_idx_type i = 0; i < length (1); i++)
1306  if (xelem (i) == 0)
1307  n++;
1308  }
1309 
1310  return n;
1311 }
1312 
1313 // Instantiate the octave_int constructors we want.
1314 #define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \
1315  template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \
1316  template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);
1317 
1328 
1329 /*
1330 
1331 %!error id=Octave:index-out-of-bounds 1(find ([1,1] != 0))
1332 %!assert ((1:3)(find ([1,0,1] != 0)), [1,3])
1333 
1334 */