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