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