GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
idx-vector.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2018 John W. Eaton
4 Copyright (C) 2008-2009 Jaroslav Hajek
5 Copyright (C) 2009-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
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #if defined (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  : idx_base_rep ()
84 {
85  if (c != ':')
86  {
87  (*current_liboctave_error_handler)
88  ("internal error: invalid character converted to idx_vector; must be ':'");
89  // FIXME: this is unreachable now.
90  err = true;
91  }
92 }
93 
96 {
97  if (i < 0)
99 
100  return i;
101 }
102 
105 {
106  (*current_liboctave_error_handler)
107  ("internal error: idx_colon_rep::sort_idx");
108 }
109 
110 std::ostream&
112 {
113  return os << ':';
114 }
115 
117  octave_idx_type _limit,
118  octave_idx_type _step)
119  : idx_base_rep (), start(_start),
120  len (_step ? std::max ((_limit - _start) / _step,
121  static_cast<octave_idx_type> (0))
122  : -1),
123  step (_step)
124 {
125  if (len < 0)
127  if (start < 0)
129  if (step < 0 && start + (len-1)*step < 0)
131 }
132 
134  : idx_base_rep (), start (0), len (r.numel ()), step (1)
135 {
136  if (len < 0)
138 
139  if (len > 0)
140  {
141  if (r.all_elements_are_ints ())
142  {
143  start = static_cast<octave_idx_type> (r.base ()) - 1;
144  step = static_cast<octave_idx_type> (r.inc ());
145  if (start < 0)
147  if (step < 0 && start + (len - 1)*step < 0)
149  }
150  else
151  {
152  // find first non-integer, then gripe about it
153  double b = r.base ();
154  double inc = r.inc ();
155  octave::err_invalid_index (b != std::floor (b) ? b : b + inc);
156  }
157  }
158 }
159 
162 {
163  if (i < 0 || i >= len)
165 
166  return start + i*step;
167 }
168 
171 {
172  if (step < 0)
173  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
174  else
175  {
176  count++;
177  return this;
178  }
179 }
180 
183 {
184  if (step < 0 && len > 0)
185  {
186  idx.clear (1, len);
187  for (octave_idx_type i = 0; i < len; i++)
188  idx.xelem (i) = len - 1 - i;
189  return new idx_range_rep (start + (len - 1)*step, len, -step, DIRECT);
190  }
191  else
192  {
193  idx.clear (1, len);
194  for (octave_idx_type i = 0; i < len; i++)
195  idx.xelem (i) = i;
196  count++;
197  return this;
198  }
199 }
200 
201 std::ostream&
203 {
204  os << start << ':' << step << ':' << start + len*step;
205  return os;
206 }
207 
208 Range
210 {
211  return Range (static_cast<double> (start+1),
212  static_cast<double> (step), len);
213 }
214 
217 {
219  for (octave_idx_type i = 0; i < len; i++)
220  retval.xelem (i) = start + i*step;
221 
222  return retval;
223 }
224 
225 inline octave_idx_type
226 convert_index (octave_idx_type i, bool& conv_error,
227  octave_idx_type& ext)
228 {
229  if (i <= 0 && ! conv_error)
231 
232  if (ext < i)
233  ext = i;
234 
235  return i - 1;
236 }
237 
238 inline octave_idx_type
239 convert_index (double x, bool& conv_error, octave_idx_type& ext)
240 {
241  octave_idx_type i = static_cast<octave_idx_type> (x);
242 
243  if (static_cast<double> (i) != x)
245 
246  return convert_index (i, conv_error, ext);
247 }
248 
249 inline octave_idx_type
250 convert_index (float x, bool& conv_error, octave_idx_type& ext)
251 {
252  return convert_index (static_cast<double> (x), conv_error, ext);
253 }
254 
255 template <typename T>
256 inline octave_idx_type
257 convert_index (octave_int<T> x, bool& conv_error,
258  octave_idx_type& ext)
259 {
261 
262  return convert_index (i, conv_error, ext);
263 }
264 
265 template <typename T>
267  : idx_base_rep (), data (0)
268 {
269  octave_idx_type dummy = 0;
270 
271  data = convert_index (x, err, dummy);
272 }
273 
275  : idx_base_rep (), data (i)
276 {
277  if (data < 0)
279 }
280 
283 {
284  if (i != 0)
286 
287  return data;
288 }
289 
292 {
293  idx.clear (1, 1);
294  idx.fill (0);
295  count++;
296  return this;
297 }
298 
299 std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const
300 {
301  return os << data;
302 }
303 
304 double
306 {
307  return data + 1;
308 }
309 
312 {
313  return Array<octave_idx_type> (dim_vector (1, 1), data);
314 }
315 
316 template <typename T>
318  : idx_base_rep (), data (nullptr), len (nda.numel ()), ext (0),
319  aowner (nullptr), orig_dims (nda.dims ())
320 {
321  if (len != 0)
322  {
323  std::unique_ptr<octave_idx_type []> d (new octave_idx_type [len]);
324 
325  for (octave_idx_type i = 0; i < len; i++)
326  d[i] = convert_index (nda.xelem (i), err, ext);
327 
328  data = d.release ();
329  }
330 }
331 
332 // Note that this makes a shallow copy of the index array.
333 
335  : idx_base_rep (), data (inda.data ()), len (inda.numel ()), ext (0),
336  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
337 {
338  if (len != 0)
339  {
340  octave_idx_type max = -1;
341  for (octave_idx_type i = 0; i < len; i++)
342  {
343  octave_idx_type k = inda.xelem (i);
344  if (k < 0)
345  {
346  if (! err)
348  }
349  else if (k > max)
350  max = k;
351  }
352 
353  ext = max + 1;
354  }
355 }
356 
358  octave_idx_type _ext, direct)
359  : idx_base_rep (), data (inda.data ()), len (inda.numel ()), ext (_ext),
360  aowner (new Array<octave_idx_type> (inda)), orig_dims (inda.dims ())
361 {
362  // No checking.
363  if (ext < 0)
364  {
365  octave_idx_type max = -1;
366  for (octave_idx_type i = 0; i < len; i++)
367  if (data[i] > max)
368  max = data[i];
369 
370  ext = max + 1;
371  }
372 }
373 
375  : idx_base_rep (), data (nullptr), len (b ? 1 : 0), ext (0),
376  aowner (nullptr), orig_dims (len, len)
377 {
378  if (len != 0)
379  {
380  octave_idx_type *d = new octave_idx_type [1];
381  d[0] = 0;
382  data = d;
383  ext = 1;
384  }
385 }
386 
389  : idx_base_rep (), data (nullptr), len (nnz), ext (0), aowner (nullptr),
390  orig_dims ()
391 {
392  if (nnz < 0)
393  len = bnda.nnz ();
394 
395  const dim_vector dv = bnda.dims ();
396 
398 
399  if (len != 0)
400  {
402 
403  octave_idx_type ntot = bnda.numel ();
404 
405  octave_idx_type k = 0;
406  for (octave_idx_type i = 0; i < ntot; i++)
407  if (bnda.xelem (i))
408  d[k++] = i;
409 
410  data = d;
411 
412  ext = d[k-1] + 1;
413  }
414 }
415 
417  : idx_base_rep (), data (nullptr), len (bnda.nnz ()), ext (0),
418  aowner (nullptr), orig_dims ()
419 {
420  const dim_vector dv = bnda.dims ();
421 
423 
424  if (len != 0)
425  {
427 
428  octave_idx_type k = 0;
429  octave_idx_type nc = bnda.cols ();
430  octave_idx_type nr = bnda.rows ();
431 
432  for (octave_idx_type j = 0; j < nc; j++)
433  for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++)
434  if (bnda.data (i))
435  d[k++] = j * nr + bnda.ridx (i);
436 
437  data = d;
438 
439  ext = d[k-1] + 1;
440  }
441 }
442 
444 {
445  if (aowner)
446  delete aowner;
447  else
448  delete [] data;
449 }
450 
453 {
454  if (n < 0 || n >= len)
456 
457  return xelem (n);
458 }
459 
462 {
463  if (len == 0)
464  {
465  count++;
466  return this;
467  }
468 
469  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
470  std::unique_ptr<idx_vector_rep> new_rep (
471  new idx_vector_rep (nullptr, len, ext, orig_dims, DIRECT));
472 
473  if (ext > len*octave::math::log2 (1.0 + len))
474  {
475  // Use standard sort via octave_sort.
476  octave_idx_type *new_data = new octave_idx_type [len];
477  new_rep->data = new_data;
478 
479  std::copy_n (data, len, new_data);
481  lsort.set_compare (ASCENDING);
482  lsort.sort (new_data, len);
483 
484  if (uniq)
485  {
486  octave_idx_type new_len = std::unique (new_data, new_data + len)
487  - new_data;
488  new_rep->len = new_len;
489  if (new_rep->orig_dims.ndims () == 2 && new_rep->orig_dims(0) == 1)
490  new_rep->orig_dims = dim_vector (1, new_len);
491  else
492  new_rep->orig_dims = dim_vector (new_len, 1);
493  }
494  }
495  else if (uniq)
496  {
497  // Use two-pass bucket sort (only a mask array needed).
498  OCTAVE_LOCAL_BUFFER_INIT (bool, has, ext, false);
499  for (octave_idx_type i = 0; i < len; i++)
500  has[data[i]] = true;
501 
502  octave_idx_type new_len = 0;
503  for (octave_idx_type i = 0; i < ext; i++)
504  new_len += has[i];
505 
506  new_rep->len = new_len;
507  if (new_rep->orig_dims.ndims () == 2 && new_rep->orig_dims(0) == 1)
508  new_rep->orig_dims = dim_vector (1, new_len);
509  else
510  new_rep->orig_dims = dim_vector (new_len, 1);
511 
512  octave_idx_type *new_data = new octave_idx_type [new_len];
513  new_rep->data = new_data;
514 
515  for (octave_idx_type i = 0, j = 0; i < ext; i++)
516  if (has[i])
517  new_data[j++] = i;
518  }
519  else
520  {
521  // Use two-pass bucket sort.
523  for (octave_idx_type i = 0; i < len; i++)
524  cnt[data[i]]++;
525 
526  octave_idx_type *new_data = new octave_idx_type [len];
527  new_rep->data = new_data;
528 
529  for (octave_idx_type i = 0, j = 0; i < ext; i++)
530  {
531  for (octave_idx_type k = 0; k < cnt[i]; k++)
532  new_data[j++] = i;
533  }
534  }
535 
536  return new_rep.release ();
537 }
538 
541 {
542  // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
543  std::unique_ptr<idx_vector_rep> new_rep (
544  new idx_vector_rep (nullptr, len, ext, orig_dims, DIRECT));
545 
546  if (ext > len*octave::math::log2 (1.0 + len))
547  {
548  // Use standard sort via octave_sort.
549  idx.clear (orig_dims);
550  octave_idx_type *idx_data = idx.fortran_vec ();
551  for (octave_idx_type i = 0; i < len; i++)
552  idx_data[i] = i;
553 
554  octave_idx_type *new_data = new octave_idx_type [len];
555  new_rep->data = new_data;
556  std::copy_n (data, len, new_data);
557 
559  lsort.set_compare (ASCENDING);
560  lsort.sort (new_data, idx_data, len);
561  }
562  else
563  {
564  // Use two-pass bucket sort.
566 
567  for (octave_idx_type i = 0; i < len; i++)
568  cnt[data[i]]++;
569 
570  idx.clear (orig_dims);
571  octave_idx_type *idx_data = idx.fortran_vec ();
572 
573  octave_idx_type *new_data = new octave_idx_type [len];
574  new_rep->data = new_data;
575 
576  for (octave_idx_type i = 0, k = 0; i < ext; i++)
577  {
578  octave_idx_type j = cnt[i];
579  cnt[i] = k;
580  k += j;
581  }
582 
583  for (octave_idx_type i = 0; i < len; i++)
584  {
585  octave_idx_type j = data[i];
586  octave_idx_type k = cnt[j]++;
587  new_data[k] = j;
588  idx_data[k] = i;
589  }
590  }
591 
592  return new_rep.release ();
593 }
594 
595 std::ostream&
597 {
598  os << '[';
599 
600  for (octave_idx_type i = 0; i < len - 1; i++)
601  os << data[i] << ',' << ' ';
602 
603  if (len > 0)
604  os << data[len-1];
605 
606  os << ']';
607 
608  return os;
609 }
610 
613 {
614  Array<double> retval (orig_dims);
615  for (octave_idx_type i = 0; i < len; i++)
616  retval.xelem (i) = data[i] + 1;
617  return retval;
618 }
619 
622 {
623  if (aowner)
624  return *aowner;
625  else
626  {
627  Array<octave_idx_type> retval (orig_dims);
628 
629  if (data)
630  {
631  std::memcpy (retval.fortran_vec (), data, len*sizeof (octave_idx_type));
632  // Delete the old copy and share the data instead to save memory.
633  delete [] data;
634  }
635 
636  data = retval.fortran_vec ();
637  aowner = new Array<octave_idx_type> (retval);
638 
639  return retval;
640  }
641 }
642 
644  : idx_base_rep (), data (nullptr), len (b ? 1 : 0), ext (0),
645  lsti (-1), lste (-1), aowner (nullptr), orig_dims (len, len)
646 {
647  if (len != 0)
648  {
649  bool *d = new bool [1];
650  d[0] = true;
651  data = d;
652  ext = 1;
653  }
654 }
655 
658  : idx_base_rep (), data (nullptr), len (nnz), ext (bnda.numel ()),
659  lsti (-1), lste (-1), aowner (nullptr), orig_dims ()
660 {
661  if (nnz < 0)
662  len = bnda.nnz ();
663 
664  // We truncate the extent as much as possible. For Matlab
665  // compatibility, but maybe it's not a bad idea anyway.
666  while (ext > 0 && ! bnda(ext-1))
667  ext--;
668 
669  const dim_vector dv = bnda.dims ();
670 
672 
673  aowner = new Array<bool> (bnda);
674  data = bnda.data ();
675 }
676 
678 {
679  if (aowner)
680  delete aowner;
681  else
682  delete [] data;
683 }
684 
687 {
688  if (n == lsti + 1)
689  {
690  lsti = n;
691  while (! data[++lste]) ;
692  }
693  else
694  {
695  lsti = n++;
696  lste = -1;
697  while (n > 0)
698  if (data[++lste]) --n;
699  }
700  return lste;
701 }
702 
705 {
706  if (n < 0 || n >= len)
708 
709  return xelem (n);
710 }
711 
712 std::ostream&
713 idx_vector::idx_mask_rep::print (std::ostream& os) const
714 {
715  os << '[';
716 
717  for (octave_idx_type i = 0; i < ext - 1; i++)
718  os << data[i] << ',' << ' ';
719 
720  if (ext > 0)
721  os << data[ext-1];
722 
723  os << ']';
724 
725  return os;
726 }
727 
730 {
731  if (aowner)
732  return *aowner;
733  else
734  {
735  Array<bool> retval (dim_vector (ext, 1));
736  for (octave_idx_type i = 0; i < ext; i++)
737  retval.xelem (i) = data[i];
738  return retval;
739  }
740 }
741 
744 {
745  if (aowner)
746  return aowner->find ().reshape (orig_dims);
747  else
748  {
749  Array<bool> retval (orig_dims);
750  for (octave_idx_type i = 0, j = 0; i < ext; i++)
751  if (data[i])
752  retval.xelem (j++) = i;
753 
754  return retval;
755  }
756 }
757 
760 {
761  idx.clear (len, 1);
762  for (octave_idx_type i = 0; i < len; i++)
763  idx.xelem (i) = i;
764 
765  count++;
766  return this;
767 }
768 
770 
772  : rep (nullptr)
773 {
774  // Convert only if it means saving at least half the memory.
775  static const int factor = (2 * sizeof (octave_idx_type));
776  octave_idx_type nnz = bnda.nnz ();
777  if (nnz <= bnda.numel () / factor)
778  rep = new idx_vector_rep (bnda, nnz);
779  else
780  rep = new idx_mask_rep (bnda, nnz);
781 }
782 
783 bool
785  octave_idx_type nj)
786 {
787  bool reduced = false;
788 
789  // Empty index always reduces.
790  if (rep->length (n) == 0)
791  {
792  *this = idx_vector ();
793  return true;
794  }
795 
796  // Possibly skip singleton dims.
797  if (n == 1 && rep->is_colon_equiv (n))
798  {
799  *this = j;
800  return true;
801  }
802 
803  if (nj == 1 && j.is_colon_equiv (nj))
804  return true;
805 
806  switch (j.idx_class ())
807  {
808  case class_colon:
809  switch (rep->idx_class ())
810  {
811  case class_colon:
812  // (:,:) reduces to (:)
813  reduced = true;
814  break;
815 
816  case class_scalar:
817  {
818  // (i,:) reduces to a range.
819  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
820  octave_idx_type k = r->get_data ();
821  *this = new idx_range_rep (k, nj, n, DIRECT);
822  reduced = true;
823  }
824  break;
825 
826  case class_range:
827  {
828  // (i:k:end,:) reduces to a range if i <= k and k divides n.
829  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
830  octave_idx_type s = r->get_start ();
831  octave_idx_type l = r->length (n);
832  octave_idx_type t = r->get_step ();
833  if (l*t == n)
834  {
835  *this = new idx_range_rep (s, l * nj, t, DIRECT);
836  reduced = true;
837  }
838  }
839  break;
840 
841  default:
842  break;
843  }
844  break;
845 
846  case class_range:
847  switch (rep->idx_class ())
848  {
849  case class_colon:
850  {
851  // (:,i:j) reduces to a range (the step must be 1)
852  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
853  if (rj->get_step () == 1)
854  {
855  octave_idx_type sj = rj->get_start ();
856  octave_idx_type lj = rj->length (nj);
857  *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);
858  reduced = true;
859  }
860  }
861  break;
862 
863  case class_scalar:
864  {
865  // (k,i:d:j) reduces to a range.
866  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
867  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
868  octave_idx_type k = r->get_data ();
869  octave_idx_type sj = rj->get_start ();
870  octave_idx_type lj = rj->length (nj);
871  octave_idx_type tj = rj->get_step ();
872  *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
873  reduced = true;
874  }
875  break;
876 
877  case class_range:
878  {
879  // (i:k:end,p:q) reduces to a range if i <= k and k divides n.
880  // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n))
881  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
882  octave_idx_type s = r->get_start ();
883  octave_idx_type l = r->length (n);
884  octave_idx_type t = r->get_step ();
885  idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.rep);
886  octave_idx_type sj = rj->get_start ();
887  octave_idx_type lj = rj->length (nj);
888  octave_idx_type tj = rj->get_step ();
889  if ((l*t == n && tj == 1) || (t == 0 && tj == 0))
890  {
891  *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
892  reduced = true;
893  }
894  }
895  break;
896 
897  default:
898  break;
899  }
900  break;
901 
902  case class_scalar:
903  switch (rep->idx_class ())
904  {
905  case class_scalar:
906  {
907  // (i,j) reduces to a single index.
908  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
909  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
910  octave_idx_type k = r->get_data () + n * rj->get_data ();
911  *this = new idx_scalar_rep (k, DIRECT);
912  reduced = true;
913  }
914  break;
915 
916  case class_range:
917  {
918  // (i:d:j,k) reduces to a range.
919  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
920  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
921  octave_idx_type s = r->get_start ();
922  octave_idx_type l = r->length (nj);
923  octave_idx_type t = r->get_step ();
924  octave_idx_type k = rj->get_data ();
925  *this = new idx_range_rep (n * k + s, l, t, DIRECT);
926  reduced = true;
927  }
928  break;
929 
930  case class_colon:
931  {
932  // (:,k) reduces to a range.
933  idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.rep);
934  octave_idx_type k = rj->get_data ();
935  *this = new idx_range_rep (n * k, n, 1, DIRECT);
936  reduced = true;
937  }
938  break;
939 
940  default:
941  break;
942  }
943  break;
944 
945  default:
946  break;
947  }
948 
949  return reduced;
950 }
951 
952 bool
954  octave_idx_type& l, octave_idx_type& u) const
955 {
956  bool res = false;
957 
958  switch (rep->idx_class ())
959  {
960  case class_colon:
961  l = 0; u = n;
962  res = true;
963  break;
964 
965  case class_range:
966  {
967  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
968  if (r->get_step () == 1)
969  {
970  l = r->get_start ();
971  u = l + r->length (n);
972  res = true;
973  }
974  }
975  break;
976 
977  case class_scalar:
978  {
979  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
980  l = r->get_data ();
981  u = l + 1;
982  res = true;
983  }
984  break;
985 
986  case class_mask:
987  {
988  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
989  octave_idx_type ext = r->extent (0);
990  octave_idx_type len = r->length (0);
991  if (ext == len)
992  {
993  l = 0;
994  u = len;
995  res = true;
996  }
997  }
998 
999  default:
1000  break;
1001  }
1002 
1003  return res;
1004 }
1005 
1008 {
1009  octave_idx_type retval = 0;
1010 
1011  switch (rep->idx_class ())
1012  {
1013  case class_colon:
1014  retval = 1;
1015  break;
1016 
1017  case class_range:
1018  retval = dynamic_cast<idx_range_rep *> (rep) -> get_step ();
1019  break;
1020 
1021  case class_vector:
1022  case class_mask:
1023  {
1024  if (length (0) > 1)
1025  retval = elem (1) - elem (0);
1026  }
1027  break;
1028 
1029  default:
1030  break;
1031  }
1032 
1033  return retval;
1034 }
1035 
1036 const octave_idx_type *
1038 {
1039  if (rep->idx_class () != class_vector)
1040  *this = idx_vector (as_array (), extent (0));
1041 
1042  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1043 
1044  assert (r != nullptr);
1045 
1046  return r->get_data ();
1047 }
1048 
1049 void
1051 {
1052  octave_idx_type len = rep->length (0);
1053 
1054  switch (rep->idx_class ())
1055  {
1056  case class_colon:
1057  (*current_liboctave_error_handler) ("colon not allowed");
1058  break;
1059 
1060  case class_range:
1061  {
1062  idx_range_rep *r = dynamic_cast<idx_range_rep *> (rep);
1064  octave_idx_type step = r->get_step ();
1065  octave_idx_type i, j;
1066  if (step == 1)
1067  for (i = start, j = start + len; i < j; i++) *data++ = i;
1068  else if (step == -1)
1069  for (i = start, j = start - len; i > j; i--) *data++ = i;
1070  else
1071  for (i = 0, j = start; i < len; i++, j += step) *data++ = j;
1072  }
1073  break;
1074 
1075  case class_scalar:
1076  {
1077  idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (rep);
1078  *data = r->get_data ();
1079  }
1080  break;
1081 
1082  case class_vector:
1083  {
1084  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1085  const octave_idx_type *rdata = r->get_data ();
1086  std::copy_n (rdata, len, data);
1087  }
1088  break;
1089 
1090  case class_mask:
1091  {
1092  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1093  const bool *mask = r->get_data ();
1094  octave_idx_type ext = r->extent (0);
1095  for (octave_idx_type i = 0, j = 0; i < ext; i++)
1096  if (mask[i])
1097  data[j++] = i;
1098  }
1099  break;
1100 
1101  default:
1102  assert (false);
1103  break;
1104  }
1105 }
1106 
1107 idx_vector
1109 {
1111  if (extent (n) > n)
1112  (*current_liboctave_error_handler)
1113  ("internal error: out of range complement index requested");
1114 
1115  if (idx_class () == class_mask)
1116  {
1117  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1118  octave_idx_type nz = r->length (0);
1119  octave_idx_type 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  std::fill_n (ndata + ext, n - ext, true);
1126  retval = new idx_mask_rep (mask, n - nz);
1127  }
1128  else
1129  {
1130  Array<bool> mask (dim_vector (n, 1), true);
1131  fill (false, length (n), mask.fortran_vec ());
1132  retval = idx_vector (mask);
1133  }
1134 
1135  return retval;
1136 }
1137 
1138 bool
1140 {
1141  bool retval = false;
1142 
1143  if (is_colon_equiv (n))
1144  retval = true;
1145  else if (length(n) == n && extent(n) == n)
1146  {
1147  OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true);
1148 
1149  retval = true;
1150 
1151  for (octave_idx_type i = 0, len = length (); i < len; i++)
1152  {
1153  octave_idx_type k = xelem (i);
1154  if (left[k])
1155  left[k] = false;
1156  else
1157  {
1158  retval = false;
1159  break;
1160  }
1161  }
1162  }
1163 
1164  return retval;
1165 }
1166 
1167 idx_vector
1169 {
1170  assert (n == length (n));
1171 
1173 
1174  switch (idx_class ())
1175  {
1176  case class_range:
1177  {
1178  if (increment () == -1)
1179  retval = sorted ();
1180  else
1181  retval = *this;
1182  break;
1183  }
1184  case class_vector:
1185  {
1186  idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (rep);
1187  const octave_idx_type *ri = r->get_data ();
1189  for (octave_idx_type i = 0; i < n; i++)
1190  idx.xelem (ri[i]) = i;
1191  retval = new idx_vector_rep (idx, r->extent (0), DIRECT);
1192  break;
1193  }
1194  default:
1195  retval = *this;
1196  break;
1197  }
1198 
1199  return retval;
1200 }
1201 
1202 idx_vector
1204 {
1205  if (idx_class () == class_mask)
1206  {
1207  idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (rep);
1208  const bool *data = r->get_data ();
1209  octave_idx_type ext = r->extent (0);
1210  octave_idx_type 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 ().isvector ();
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  // FIXME: Should we call this before calling error_handler?
1290  rep->err = true;
1291  chkerr ();
1292  }
1293 
1294  return length (z_len);
1295 }
1296 
1299 {
1300  octave_idx_type n = 0;
1301 
1302  if (is_colon ())
1303  n = 1;
1304  else
1305  {
1306  for (octave_idx_type i = 0; i < length (1); i++)
1307  if (xelem (i) == 0)
1308  n++;
1309  }
1310 
1311  return n;
1312 }
1313 
1314 // Instantiate the octave_int constructors we want.
1315 #define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \
1316  template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \
1317  template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);
1318 
1329 
1330 /*
1331 
1332 %!error id=Octave:index-out-of-bounds 1(find ([1,1] != 0))
1333 %!assert ((1:3)(find ([1,0,1] != 0)), [1,3])
1334 
1335 */
octave_idx_type len
Definition: idx-vector.h:419
const octave_idx_type * get_data(void) const
Definition: idx-vector.h:335
octave_idx_type data
Definition: idx-vector.h:276
virtual Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:73
idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:170
octave_idx_type step
Definition: idx-vector.h:220
static int left
Definition: randmtzig.cc:184
T * data(void)
Definition: Sparse.h:486
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:593
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:202
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:182
Range unconvert(void) const
Definition: idx-vector.cc:209
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:161
idx_class_type idx_class(void) const
Definition: idx-vector.h:555
static void err_index_out_of_range(void)
Definition: idx-vector.cc:51
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:713
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:759
#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)
Definition: oct-locbuf.h:47
const FloatComplex * data(void) const
Definition: Array.h:582
nd group nd example oindent but is performed more efficiently If only and it is a scalar
Definition: data.cc:5264
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:560
static const idx_vector colon
Definition: idx-vector.h:498
void fill(const T &val)
Definition: Array.cc:72
octave_idx_type max(void) const
Definition: idx-vector.h:1047
bool all_elements_are_ints(void) const
Definition: Range.cc:39
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:743
static idx_vector_rep * err_rep(void)
Definition: idx-vector.cc:65
idx_colon_rep(void)=default
Array< bool > unconvert(void) const
Definition: idx-vector.cc:729
octave_idx_type xelem(octave_idx_type n) const
Definition: idx-vector.h:563
void set_compare(compare_fcn_type comp)
Definition: oct-sort.h:128
Array< double > unconvert(void) const
Definition: idx-vector.cc:612
octave_idx_type * cidx(void)
Definition: Sparse.h:508
dim_vector make_nd_vector(octave_idx_type n) const
Definition: dim-vector.h:452
octave_idx_type ones_count(void) const
Definition: idx-vector.cc:1298
for large enough k
Definition: lu.cc:617
const T * fortran_vec(void) const
Definition: Array.h:584
Definition: Range.h:33
double unconvert(void) const
Definition: idx-vector.cc:305
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:139
idx_vector inverse_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1168
STL namespace.
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:442
void unconvert(idx_class_type &iclass, double &scalar, Range &range, Array< double > &array, Array< bool > &mask) const
Definition: idx-vector.cc:1226
u
Definition: lu.cc:138
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:997
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:324
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:704
bool is_cont_range(octave_idx_type n, octave_idx_type &l, octave_idx_type &u) const
Definition: idx-vector.cc:953
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
virtual idx_class_type idx_class(void) const
Definition: idx-vector.h:99
Complex log2(const Complex &x)
Definition: lo-mappers.cc:137
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:188
const bool * get_data(void) const
Definition: idx-vector.h:408
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:621
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE 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:226
octave_idx_type elem(octave_idx_type n) const
Definition: idx-vector.h:1033
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:291
double base(void) const
Definition: Range.h:78
Array< T > reshape(octave_idx_type nr, octave_idx_type nc) const
Definition: Array.h:549
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1139
octave_idx_type nnz(void) const
Count nonzero elements.
Definition: Array.cc:2212
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
Array< bool > * aowner
Definition: idx-vector.h:434
virtual bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:107
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:391
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:403
idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:461
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:393
bool is_colon(void) const
Definition: idx-vector.h:575
void copy_data(octave_idx_type *data) const
Definition: idx-vector.cc:1050
octave_idx_type ext
Definition: idx-vector.h:420
idx_base_rep * rep
Definition: idx-vector.h:1051
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:452
static idx_vector_rep * nil_rep(void)
Definition: idx-vector.cc:58
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.cc:686
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:557
octave_value retval
Definition: data.cc:6246
octave_idx_type increment(void) const
Definition: idx-vector.cc:1007
idx_vector sorted(bool uniq=false) const
Definition: idx-vector.h:587
idx_vector(void)
Definition: idx-vector.h:464
octave_idx_type * ridx(void)
Definition: Sparse.h:495
bool isvector(void) const
Definition: idx-vector.cc:1277
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:216
#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T)
Definition: idx-vector.cc:1315
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
OCTAVE_NORETURN idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:104
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:299
octave_idx_type get_step(void) const
Definition: idx-vector.h:210
T & xelem(octave_idx_type n)
Definition: Array.h:458
octave_idx_type get_start(void) const
Definition: idx-vector.h:208
octave_idx_type get_data(void) const
Definition: idx-vector.h:266
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:5264
octave_idx_type cols(void) const
Definition: Sparse.h:259
void clear(void)
Definition: Array.cc:86
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:220
octave::sys::time start
Definition: graphics.cc:12337
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:584
octave_idx_type start
Definition: idx-vector.h:220
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:596
bool isvector(void) const
Definition: dim-vector.h:422
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
Definition: idx-vector.h:767
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:282
b
Definition: cellfun.cc:400
idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:540
const octave_idx_type * data
Definition: idx-vector.h:345
idx_vector unmask(void) const
Definition: idx-vector.cc:1203
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:2227
bool maybe_reduce(octave_idx_type n, const idx_vector &j, octave_idx_type nj)
Definition: idx-vector.cc:784
std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:111
void chkerr(void)
Definition: idx-vector.h:450
dim_vector dims(void) const
Definition: Sparse.h:278
for i
Definition: data.cc:5264
idx_vector complement(octave_idx_type n) const
Definition: idx-vector.cc:1108
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
octave_idx_type freeze(octave_idx_type z_len, const char *tag, bool resize_ok=false)
Definition: idx-vector.cc:1283
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
Array< octave_idx_type > as_array(void) const
Definition: idx-vector.cc:1271
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
const octave_idx_type * raw(void)
Definition: idx-vector.cc:1037
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:95
nd group nd example For each display the value
Definition: sysdep.cc:866
dim_vector dv
Definition: sub2ind.cc:263
virtual octave_idx_type length(octave_idx_type n) const =0
octave::stream os
Definition: file-io.cc:627
octave_idx_type rows(void) const
Definition: Sparse.h:258
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
double inc(void) const
Definition: Range.h:80
Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:311
static OCTAVE_NORETURN void err_invalid_range(void)
Definition: idx-vector.cc:45