GNU Octave 7.1.0
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-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cinttypes>
31#include <cstdlib>
32
33#include <ostream>
34
35#include "idx-vector.h"
36#include "Array.h"
37#include "Array-util.h"
38#include "Sparse.h"
39#include "Range.h"
40
41#include "oct-locbuf.h"
42#include "lo-error.h"
43#include "lo-mappers.h"
44
45namespace octave
46{
47 OCTAVE_NORETURN static void err_invalid_range (void)
48 {
49 (*current_liboctave_error_handler) ("invalid range used as index");
50 }
51
52 OCTAVE_NORETURN static void err_index_out_of_range (void)
53 {
54 (*current_liboctave_error_handler)
55 ("internal error: idx_vector index out of range");
56 }
57
59 {
60 static idx_vector_rep ivr;
61 return &ivr;
62 }
63
65 {
66 (*current_liboctave_error_handler)
67 ("internal error: as_array not allowed for this index class");
68
69 // Never actually executed, but required to silence compiler warning
70 return Array<octave_idx_type> ();
71 }
72
74 : idx_base_rep ()
75 {
76 if (c != ':')
77 (*current_liboctave_error_handler)
78 ("internal error: invalid character converted to idx_vector; must be ':'");
79 }
80
83 {
84 if (i < 0)
86
87 return i;
88 }
89
92 {
93 (*current_liboctave_error_handler)
94 ("internal error: idx_colon_rep::sort_idx");
95 }
96
97 std::ostream& idx_vector::idx_colon_rep::print (std::ostream& os) const
98 {
99 return os << ':';
100 }
101
103 octave_idx_type limit,
104 octave_idx_type step)
105 : idx_base_rep (), m_start(start),
106 m_len (step ? std::max ((limit - start) / step,
107 static_cast<octave_idx_type> (0))
108 : -1),
109 m_step (step)
110 {
111 if (m_len < 0)
113 if (m_start < 0)
115 if (m_step < 0 && m_start + (m_len-1)*m_step < 0)
117 }
118
120 : idx_base_rep (), m_start (0), m_len (r.numel ()), m_step (1)
121 {
122 if (m_len < 0)
124
125 if (m_len > 0)
126 {
127 if (r.all_elements_are_ints ())
128 {
129 m_start = static_cast<octave_idx_type> (r.base ()) - 1;
130 m_step = static_cast<octave_idx_type> (r.increment ());
131 if (m_start < 0)
133 if (m_step < 0 && m_start + (m_len - 1)*m_step < 0)
135 }
136 else
137 {
138 // find first non-integer, then gripe about it
139 double b = r.base ();
140 double inc = r.increment ();
141 err_invalid_index (b != std::trunc (b) ? b : b + inc);
142 }
143 }
144 }
145
148 {
149 if (i < 0 || i >= m_len)
151
152 return m_start + i*m_step;
153 }
154
156 {
157 if (m_step < 0)
158 return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);
159 else
160 {
161 m_count++;
162 return this;
163 }
164 }
165
168 {
169 if (m_step < 0 && m_len > 0)
170 {
171 idx.clear (1, m_len);
172 for (octave_idx_type i = 0; i < m_len; i++)
173 idx.xelem (i) = m_len - 1 - i;
174 return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT);
175 }
176 else
177 {
178 idx.clear (1, m_len);
179 for (octave_idx_type i = 0; i < m_len; i++)
180 idx.xelem (i) = i;
181 m_count++;
182 return this;
183 }
184 }
185
186 std::ostream& idx_vector::idx_range_rep::print (std::ostream& os) const
187 {
188 os << m_start << ':' << m_step << ':' << m_start + m_len*m_step;
189 return os;
190 }
191
192 range<double> idx_vector::idx_range_rep::unconvert (void) const
193 {
194 return range<double>::make_n_element_range
195 (static_cast<double> (m_start+1), static_cast<double> (m_step), m_len);
196 }
197
199 {
201 for (octave_idx_type i = 0; i < m_len; i++)
202 retval.xelem (i) = m_start + i*m_step;
203
204 return retval;
205 }
206
208 {
209 if (i <= 0)
210 err_invalid_index (i-1);
211
212 if (ext < i)
213 ext = i;
214
215 return i - 1;
216 }
217
219 {
220 octave_idx_type i = static_cast<octave_idx_type> (x);
221
222 if (static_cast<double> (i) != x)
224
225 return convert_index (i, ext);
226 }
227
229 {
230 return convert_index (static_cast<double> (x), ext);
231 }
232
233 template <typename T>
235 {
237
238 return convert_index (i, ext);
239 }
240
241 template <typename T>
243 : idx_base_rep (), m_data (0)
244 {
245 octave_idx_type dummy = 0;
246
247 m_data = convert_index (x, dummy);
248 }
249
251 : idx_base_rep (), m_data (i)
252 {
253 if (m_data < 0)
255 }
256
259 {
260 if (i != 0)
262
263 return m_data;
264 }
265
268 {
269 idx.clear (1, 1);
270 idx.fill (0);
271 m_count++;
272 return this;
273 }
274
275 std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const
276 {
277 return os << m_data;
278 }
279
281 {
282 return m_data + 1;
283 }
284
286 {
288 }
289
290 template <typename T>
292 : idx_base_rep (), m_data (nullptr), m_len (nda.numel ()), m_ext (0),
293 m_aowner (nullptr), m_orig_dims (nda.dims ())
294 {
295 if (m_len != 0)
296 {
297 std::unique_ptr<octave_idx_type []> d (new octave_idx_type [m_len]);
298
299 for (octave_idx_type i = 0; i < m_len; i++)
300 d[i] = convert_index (nda.xelem (i), m_ext);
301
302 m_data = d.release ();
303 }
304 }
305
306 // Note that this makes a shallow copy of the index array.
307
309 : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), m_ext (0),
310 m_aowner (new Array<octave_idx_type> (inda)), m_orig_dims (inda.dims ())
311 {
312 if (m_len != 0)
313 {
314 octave_idx_type max = -1;
315 for (octave_idx_type i = 0; i < m_len; i++)
316 {
317 octave_idx_type k = inda.xelem (i);
318 if (k < 0)
320 else if (k > max)
321 max = k;
322 }
323
324 m_ext = max + 1;
325 }
326 }
327
330 : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()),
331 m_ext (ext), m_aowner (new Array<octave_idx_type> (inda)),
332 m_orig_dims (inda.dims ())
333 {
334 // No checking.
335 if (m_ext < 0)
336 {
337 octave_idx_type max = -1;
338 for (octave_idx_type i = 0; i < m_len; i++)
339 if (m_data[i] > max)
340 max = m_data[i];
341
342 m_ext = max + 1;
343 }
344 }
345
347 : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),
348 m_aowner (nullptr), m_orig_dims (m_len, m_len)
349 {
350 if (m_len != 0)
351 {
353 d[0] = 0;
354 m_data = d;
355 m_ext = 1;
356 }
357 }
358
360 octave_idx_type nnz)
361 : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (0),
362 m_aowner (nullptr), m_orig_dims ()
363 {
364 if (nnz < 0)
365 m_len = bnda.nnz ();
366
367 const dim_vector dv = bnda.dims ();
368
370
371 if (m_len != 0)
372 {
374
375 octave_idx_type ntot = bnda.numel ();
376
377 octave_idx_type k = 0;
378 for (octave_idx_type i = 0; i < ntot; i++)
379 if (bnda.xelem (i))
380 d[k++] = i;
381
382 m_data = d;
383
384 m_ext = d[k-1] + 1;
385 }
386 }
387
389 : idx_base_rep (), m_data (nullptr), m_len (bnda.nnz ()), m_ext (0),
390 m_aowner (nullptr), m_orig_dims ()
391 {
392 const dim_vector dv = bnda.dims ();
393
395
396 if (m_len != 0)
397 {
399
400 octave_idx_type k = 0;
401 octave_idx_type nc = bnda.cols ();
402 octave_idx_type nr = bnda.rows ();
403
404 for (octave_idx_type j = 0; j < nc; j++)
405 for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++)
406 if (bnda.data (i))
407 d[k++] = j * nr + bnda.ridx (i);
408
409 m_data = d;
410
411 m_ext = d[k-1] + 1;
412 }
413 }
414
416 {
417 if (m_aowner)
418 delete m_aowner;
419 else
420 delete [] m_data;
421 }
422
425 {
426 if (n < 0 || n >= m_len)
428
429 return xelem (n);
430 }
431
434 {
435 if (m_len == 0)
436 {
437 m_count++;
438 return this;
439 }
440
441 // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
442 std::unique_ptr<idx_vector_rep> new_rep
443 (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT));
444
445 if (m_ext > m_len*math::log2 (1.0 + m_len))
446 {
447 // Use standard sort via octave_sort.
448 octave_idx_type *new_data = new octave_idx_type [m_len];
449 new_rep->m_data = new_data;
450
451 std::copy_n (m_data, m_len, new_data);
453 lsort.set_compare (ASCENDING);
454 lsort.sort (new_data, m_len);
455
456 if (uniq)
457 {
458 octave_idx_type new_len = std::unique (new_data, new_data + m_len)
459 - new_data;
460 new_rep->m_len = new_len;
461 if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)
462 new_rep->m_orig_dims = dim_vector (1, new_len);
463 else
464 new_rep->m_orig_dims = dim_vector (new_len, 1);
465 }
466 }
467 else if (uniq)
468 {
469 // Use two-pass bucket sort (only a mask array needed).
470 OCTAVE_LOCAL_BUFFER_INIT (bool, has, m_ext, false);
471 for (octave_idx_type i = 0; i < m_len; i++)
472 has[m_data[i]] = true;
473
474 octave_idx_type new_len = 0;
475 for (octave_idx_type i = 0; i < m_ext; i++)
476 new_len += has[i];
477
478 new_rep->m_len = new_len;
479 if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1)
480 new_rep->m_orig_dims = dim_vector (1, new_len);
481 else
482 new_rep->m_orig_dims = dim_vector (new_len, 1);
483
484 octave_idx_type *new_data = new octave_idx_type [new_len];
485 new_rep->m_data = new_data;
486
487 for (octave_idx_type i = 0, j = 0; i < m_ext; i++)
488 if (has[i])
489 new_data[j++] = i;
490 }
491 else
492 {
493 // Use two-pass bucket sort.
495 for (octave_idx_type i = 0; i < m_len; i++)
496 cnt[m_data[i]]++;
497
498 octave_idx_type *new_data = new octave_idx_type [m_len];
499 new_rep->m_data = new_data;
500
501 for (octave_idx_type i = 0, j = 0; i < m_ext; i++)
502 {
503 for (octave_idx_type k = 0; k < cnt[i]; k++)
504 new_data[j++] = i;
505 }
506 }
507
508 return new_rep.release ();
509 }
510
513 {
514 // This is wrapped in unique_ptr so that we don't leak on out-of-memory.
515 std::unique_ptr<idx_vector_rep> new_rep
516 (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT));
517
518 if (m_ext > m_len*math::log2 (1.0 + m_len))
519 {
520 // Use standard sort via octave_sort.
521 idx.clear (m_orig_dims);
522 octave_idx_type *idx_data = idx.fortran_vec ();
523 for (octave_idx_type i = 0; i < m_len; i++)
524 idx_data[i] = i;
525
526 octave_idx_type *new_data = new octave_idx_type [m_len];
527 new_rep->m_data = new_data;
528 std::copy_n (m_data, m_len, new_data);
529
531 lsort.set_compare (ASCENDING);
532 lsort.sort (new_data, idx_data, m_len);
533 }
534 else
535 {
536 // Use two-pass bucket sort.
538
539 for (octave_idx_type i = 0; i < m_len; i++)
540 cnt[m_data[i]]++;
541
542 idx.clear (m_orig_dims);
543 octave_idx_type *idx_data = idx.fortran_vec ();
544
545 octave_idx_type *new_data = new octave_idx_type [m_len];
546 new_rep->m_data = new_data;
547
548 for (octave_idx_type i = 0, k = 0; i < m_ext; i++)
549 {
550 octave_idx_type j = cnt[i];
551 cnt[i] = k;
552 k += j;
553 }
554
555 for (octave_idx_type i = 0; i < m_len; i++)
556 {
557 octave_idx_type j = m_data[i];
558 octave_idx_type k = cnt[j]++;
559 new_data[k] = j;
560 idx_data[k] = i;
561 }
562 }
563
564 return new_rep.release ();
565 }
566
567 std::ostream& idx_vector::idx_vector_rep::print (std::ostream& os) const
568 {
569 os << '[';
570
571 for (octave_idx_type i = 0; i < m_len - 1; i++)
572 os << m_data[i] << ',' << ' ';
573
574 if (m_len > 0)
575 os << m_data[m_len-1];
576
577 os << ']';
578
579 return os;
580 }
581
583 {
584 Array<double> retval (m_orig_dims);
585 for (octave_idx_type i = 0; i < m_len; i++)
586 retval.xelem (i) = m_data[i] + 1;
587 return retval;
588 }
589
591 {
592 if (m_aowner)
593 return *m_aowner;
594 else
595 {
597
598 if (m_data)
599 {
600 std::memcpy (retval.fortran_vec (), m_data, m_len*sizeof (octave_idx_type));
601 // Delete the old copy and share the m_data instead to save memory.
602 delete [] m_data;
603 }
604
605 m_data = retval.fortran_vec ();
606 m_aowner = new Array<octave_idx_type> (retval);
607
608 return retval;
609 }
610 }
611
613 : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0),
614 m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (m_len, m_len)
615 {
616 if (m_len != 0)
617 {
618 bool *d = new bool [1];
619 d[0] = true;
620 m_data = d;
621 m_ext = 1;
622 }
623 }
624
626 octave_idx_type nnz)
627 : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (bnda.numel ()),
628 m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims ()
629 {
630 if (nnz < 0)
631 m_len = bnda.nnz ();
632
633 // We truncate the extent as much as possible. For Matlab
634 // compatibility, but maybe it's not a bad idea anyway.
635 while (m_ext > 0 && ! bnda(m_ext-1))
636 m_ext--;
637
638 const dim_vector dv = bnda.dims ();
639
641
642 m_aowner = new Array<bool> (bnda);
643 m_data = bnda.data ();
644 }
645
647 {
648 if (m_aowner)
649 delete m_aowner;
650 else
651 delete [] m_data;
652 }
653
655 {
656 if (n == m_lsti + 1)
657 {
658 m_lsti = n;
659 while (! m_data[++m_lste]) ;
660 }
661 else
662 {
663 m_lsti = n++;
664 m_lste = -1;
665 while (n > 0)
666 if (m_data[++m_lste]) --n;
667 }
668 return m_lste;
669 }
670
672 {
673 if (n < 0 || n >= m_len)
675
676 return xelem (n);
677 }
678
679 std::ostream& idx_vector::idx_mask_rep::print (std::ostream& os) const
680 {
681 os << '[';
682
683 for (octave_idx_type i = 0; i < m_ext - 1; i++)
684 os << m_data[i] << ',' << ' ';
685
686 if (m_ext > 0)
687 os << m_data[m_ext-1];
688
689 os << ']';
690
691 return os;
692 }
693
695 {
696 if (m_aowner)
697 return *m_aowner;
698 else
699 {
700 Array<bool> retval (dim_vector (m_ext, 1));
701 for (octave_idx_type i = 0; i < m_ext; i++)
702 retval.xelem (i) = m_data[i];
703 return retval;
704 }
705 }
706
708 {
709 if (m_aowner)
710 return m_aowner->find ().reshape (m_orig_dims);
711 else
712 {
713 Array<bool> retval (m_orig_dims);
714 for (octave_idx_type i = 0, j = 0; i < m_ext; i++)
715 if (m_data[i])
716 retval.xelem (j++) = i;
717
718 return retval;
719 }
720 }
721
724 {
725 idx.clear (m_len, 1);
726 for (octave_idx_type i = 0; i < m_len; i++)
727 idx.xelem (i) = i;
728
729 m_count++;
730 return this;
731 }
732
734
736 : m_rep (nullptr)
737 {
738 // Convert only if it means saving at least half the memory.
739 static const int factor = (2 * sizeof (octave_idx_type));
740 octave_idx_type nnz = bnda.nnz ();
741 if (nnz <= bnda.numel () / factor)
742 m_rep = new idx_vector_rep (bnda, nnz);
743 else
744 m_rep = new idx_mask_rep (bnda, nnz);
745 }
746
749 {
750 bool reduced = false;
751
752 // Empty index always reduces.
753 if (m_rep->length (n) == 0)
754 {
755 *this = idx_vector ();
756 return true;
757 }
758
759 // Possibly skip singleton dims.
760 if (n == 1 && m_rep->is_colon_equiv (n))
761 {
762 *this = j;
763 return true;
764 }
765
766 if (nj == 1 && j.is_colon_equiv (nj))
767 return true;
768
769 switch (j.idx_class ())
770 {
771 case class_colon:
772 switch (m_rep->idx_class ())
773 {
774 case class_colon:
775 // (:,:) reduces to (:)
776 reduced = true;
777 break;
778
779 case class_scalar:
780 {
781 // (i,:) reduces to a range.
782 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
783 octave_idx_type k = r->get_data ();
784 *this = new idx_range_rep (k, nj, n, DIRECT);
785 reduced = true;
786 }
787 break;
788
789 case class_range:
790 {
791 // (i:k:end,:) reduces to a range if i <= k and k divides n.
792 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
793 octave_idx_type s = r->get_start ();
794 octave_idx_type l = r->length (n);
795 octave_idx_type t = r->get_step ();
796 if (l*t == n)
797 {
798 *this = new idx_range_rep (s, l * nj, t, DIRECT);
799 reduced = true;
800 }
801 }
802 break;
803
804 default:
805 break;
806 }
807 break;
808
809 case class_range:
810 switch (m_rep->idx_class ())
811 {
812 case class_colon:
813 {
814 // (:,i:j) reduces to a range (the m_step must be 1)
815 idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);
816 if (rj->get_step () == 1)
817 {
818 octave_idx_type sj = rj->get_start ();
819 octave_idx_type lj = rj->length (nj);
820 *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);
821 reduced = true;
822 }
823 }
824 break;
825
826 case class_scalar:
827 {
828 // (k,i:d:j) reduces to a range.
829 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
830 idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);
831 octave_idx_type k = r->get_data ();
832 octave_idx_type sj = rj->get_start ();
833 octave_idx_type lj = rj->length (nj);
834 octave_idx_type tj = rj->get_step ();
835 *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
836 reduced = true;
837 }
838 break;
839
840 case class_range:
841 {
842 // (i:k:end,p:q) reduces to a range if i <= k and k divides n.
843 // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n))
844 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
845 octave_idx_type s = r->get_start ();
846 octave_idx_type l = r->length (n);
847 octave_idx_type t = r->get_step ();
848 idx_range_rep *rj = dynamic_cast<idx_range_rep *> (j.m_rep);
849 octave_idx_type sj = rj->get_start ();
850 octave_idx_type lj = rj->length (nj);
851 octave_idx_type tj = rj->get_step ();
852 if ((l*t == n && tj == 1) || (t == 0 && tj == 0))
853 {
854 *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
855 reduced = true;
856 }
857 }
858 break;
859
860 default:
861 break;
862 }
863 break;
864
865 case class_scalar:
866 switch (m_rep->idx_class ())
867 {
868 case class_scalar:
869 {
870 // (i,j) reduces to a single index.
871 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
872 idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);
873 octave_idx_type k = r->get_data () + n * rj->get_data ();
874 *this = new idx_scalar_rep (k, DIRECT);
875 reduced = true;
876 }
877 break;
878
879 case class_range:
880 {
881 // (i:d:j,k) reduces to a range.
882 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
883 idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);
884 octave_idx_type s = r->get_start ();
885 octave_idx_type l = r->length (nj);
886 octave_idx_type t = r->get_step ();
887 octave_idx_type k = rj->get_data ();
888 *this = new idx_range_rep (n * k + s, l, t, DIRECT);
889 reduced = true;
890 }
891 break;
892
893 case class_colon:
894 {
895 // (:,k) reduces to a range.
896 idx_scalar_rep *rj = dynamic_cast<idx_scalar_rep *> (j.m_rep);
897 octave_idx_type k = rj->get_data ();
898 *this = new idx_range_rep (n * k, n, 1, DIRECT);
899 reduced = true;
900 }
901 break;
902
903 default:
904 break;
905 }
906 break;
907
908 default:
909 break;
910 }
911
912 return reduced;
913 }
914
916 octave_idx_type& u) const
917 {
918 bool res = false;
919
920 switch (m_rep->idx_class ())
921 {
922 case class_colon:
923 l = 0; u = n;
924 res = true;
925 break;
926
927 case class_range:
928 {
929 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
930 if (r->get_step () == 1)
931 {
932 l = r->get_start ();
933 u = l + r->length (n);
934 res = true;
935 }
936 }
937 break;
938
939 case class_scalar:
940 {
941 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
942 l = r->get_data ();
943 u = l + 1;
944 res = true;
945 }
946 break;
947
948 case class_mask:
949 {
950 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
951 octave_idx_type m_ext = r->extent (0);
952 octave_idx_type m_len = r->length (0);
953 if (m_ext == m_len)
954 {
955 l = 0;
956 u = m_len;
957 res = true;
958 }
959 }
960
961 default:
962 break;
963 }
964
965 return res;
966 }
967
969 {
970 octave_idx_type retval = 0;
971
972 switch (m_rep->idx_class ())
973 {
974 case class_colon:
975 retval = 1;
976 break;
977
978 case class_range:
979 retval = dynamic_cast<idx_range_rep *> (m_rep) -> get_step ();
980 break;
981
982 case class_vector:
983 case class_mask:
984 {
985 if (length (0) > 1)
986 retval = elem (1) - elem (0);
987 }
988 break;
989
990 default:
991 break;
992 }
993
994 return retval;
995 }
996
998 {
999 if (m_rep->idx_class () != class_vector)
1000 *this = idx_vector (as_array (), extent (0));
1001
1002 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
1003
1004 assert (r != nullptr);
1005
1006 return r->get_data ();
1007 }
1008
1010 {
1011 octave_idx_type m_len = m_rep->length (0);
1012
1013 switch (m_rep->idx_class ())
1014 {
1015 case class_colon:
1016 (*current_liboctave_error_handler) ("colon not allowed");
1017 break;
1018
1019 case class_range:
1020 {
1021 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
1022 octave_idx_type m_start = r->get_start ();
1023 octave_idx_type m_step = r->get_step ();
1024 octave_idx_type i, j;
1025 if (m_step == 1)
1026 for (i = m_start, j = m_start + m_len; i < j; i++) *m_data++ = i;
1027 else if (m_step == -1)
1028 for (i = m_start, j = m_start - m_len; i > j; i--) *m_data++ = i;
1029 else
1030 for (i = 0, j = m_start; i < m_len; i++, j += m_step) *m_data++ = j;
1031 }
1032 break;
1033
1034 case class_scalar:
1035 {
1036 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
1037 *m_data = r->get_data ();
1038 }
1039 break;
1040
1041 case class_vector:
1042 {
1043 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
1044 const octave_idx_type *rdata = r->get_data ();
1045 std::copy_n (rdata, m_len, m_data);
1046 }
1047 break;
1048
1049 case class_mask:
1050 {
1051 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
1052 const bool *mask = r->get_data ();
1053 octave_idx_type m_ext = r->extent (0);
1054 for (octave_idx_type i = 0, j = 0; i < m_ext; i++)
1055 if (mask[i])
1056 m_data[j++] = i;
1057 }
1058 break;
1059
1060 default:
1061 assert (false);
1062 break;
1063 }
1064 }
1065
1067 {
1068 idx_vector retval;
1069 if (extent (n) > n)
1070 (*current_liboctave_error_handler)
1071 ("internal error: out of range complement index requested");
1072
1073 if (idx_class () == class_mask)
1074 {
1075 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
1076 octave_idx_type nz = r->length (0);
1077 octave_idx_type m_ext = r->extent (0);
1078 Array<bool> mask (dim_vector (n, 1));
1079 const bool *m_data = r->get_data ();
1080 bool *ndata = mask.fortran_vec ();
1081 for (octave_idx_type i = 0; i < m_ext; i++)
1082 ndata[i] = ! m_data[i];
1083 std::fill_n (ndata + m_ext, n - m_ext, true);
1084 retval = new idx_mask_rep (mask, n - nz);
1085 }
1086 else
1087 {
1088 Array<bool> mask (dim_vector (n, 1), true);
1089 fill (false, length (n), mask.fortran_vec ());
1090 retval = idx_vector (mask);
1091 }
1092
1093 return retval;
1094 }
1095
1097 {
1098 bool retval = false;
1099
1100 if (is_colon_equiv (n))
1101 retval = true;
1102 else if (length(n) == n && extent(n) == n)
1103 {
1104 OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true);
1105
1106 retval = true;
1107
1108 for (octave_idx_type i = 0, m_len = length (); i < m_len; i++)
1109 {
1110 octave_idx_type k = xelem (i);
1111 if (left[k])
1112 left[k] = false;
1113 else
1114 {
1115 retval = false;
1116 break;
1117 }
1118 }
1119 }
1120
1121 return retval;
1122 }
1123
1125 {
1126 assert (n == length (n));
1127
1128 idx_vector retval;
1129
1130 switch (idx_class ())
1131 {
1132 case class_range:
1133 {
1134 if (increment () == -1)
1135 retval = sorted ();
1136 else
1137 retval = *this;
1138 break;
1139 }
1140 case class_vector:
1141 {
1142 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
1143 const octave_idx_type *ri = r->get_data ();
1145 for (octave_idx_type i = 0; i < n; i++)
1146 idx.xelem (ri[i]) = i;
1147 retval = new idx_vector_rep (idx, r->extent (0), DIRECT);
1148 break;
1149 }
1150 default:
1151 retval = *this;
1152 break;
1153 }
1154
1155 return retval;
1156 }
1157
1159 {
1160 if (idx_class () == class_mask)
1161 {
1162 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
1163 const bool *m_data = r->get_data ();
1164 octave_idx_type m_ext = r->extent (0);
1165 octave_idx_type m_len = r->length (0);
1166 octave_idx_type *idata = new octave_idx_type [m_len];
1167
1168 for (octave_idx_type i = 0, j = 0; i < m_ext; i++)
1169 if (m_data[i])
1170 idata[j++] = i;
1171
1172 m_ext = (m_len > 0 ? idata[m_len - 1] + 1 : 0);
1173
1174 return new idx_vector_rep (idata, m_len, m_ext, r->orig_dimensions (),
1175 DIRECT);
1176 }
1177 else
1178 return *this;
1179 }
1180
1182 double& scalar, range<double>& range,
1183 Array<double>& array, Array<bool>& mask) const
1184 {
1185 iclass = idx_class ();
1186 switch (iclass)
1187 {
1188 case class_colon:
1189 break;
1190
1191 case class_range:
1192 {
1193 idx_range_rep *r = dynamic_cast<idx_range_rep *> (m_rep);
1194 range = r->unconvert ();
1195 }
1196 break;
1197
1198 case class_scalar:
1199 {
1200 idx_scalar_rep *r = dynamic_cast<idx_scalar_rep *> (m_rep);
1201 scalar = r->unconvert ();
1202 }
1203 break;
1204
1205 case class_vector:
1206 {
1207 idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
1208 array = r->unconvert ();
1209 }
1210 break;
1211
1212 case class_mask:
1213 {
1214 idx_mask_rep *r = dynamic_cast<idx_mask_rep *> (m_rep);
1215 mask = r->unconvert ();
1216 }
1217 break;
1218
1219 default:
1220 assert (false);
1221 break;
1222 }
1223 }
1224
1226 {
1227 return m_rep->as_array ();
1228 }
1229
1230 bool idx_vector::isvector (void) const
1231 {
1232 return idx_class () != class_vector || orig_dimensions ().isvector ();
1233 }
1234
1236 idx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok)
1237 {
1238 if (! resize_ok && extent (z_len) > z_len)
1239 (*current_liboctave_error_handler)
1240 ("invalid matrix index = %" OCTAVE_IDX_TYPE_FORMAT, extent (z_len));
1241
1242 return length (z_len);
1243 }
1244
1246 {
1247 octave_idx_type n = 0;
1248
1249 if (is_colon ())
1250 n = 1;
1251 else
1252 {
1253 for (octave_idx_type i = 0; i < length (1); i++)
1254 if (xelem (i) == 0)
1255 n++;
1256 }
1257
1258 return n;
1259 }
1260
1261 // Instantiate the octave_int constructors we want.
1262#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \
1263 template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \
1264 template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>&);
1265
1276}
1277
1278/*
1279
1280%!error id=Octave:index-out-of-bounds 1(find ([1,1] != 0))
1281%!assert ((1:3)(find ([1,0,1] != 0)), [1,3])
1282
1283*/
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:504
OCTARRAY_API void clear(void)
Definition: Array.cc:87
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:487
OCTARRAY_API octave_idx_type nnz(void) const
Count nonzero elements.
Definition: Array.cc:2203
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:616
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array.cc:1744
OCTARRAY_API 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:2218
Array< T, Alloc > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
Definition: Array.h:595
OCTARRAY_API void fill(const T &val)
Definition: Array.cc:73
octave_idx_type rows(void) const
Definition: Sparse.h:351
T * data(void)
Definition: Sparse.h:574
dim_vector dims(void) const
Definition: Sparse.h:371
octave_idx_type * ridx(void)
Definition: Sparse.h:583
octave_idx_type * cidx(void)
Definition: Sparse.h:596
octave_idx_type cols(void) const
Definition: Sparse.h:352
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
bool isvector(void) const
Definition: dim-vector.h:395
dim_vector make_nd_vector(octave_idx_type n) const
Definition: dim-vector.h:421
virtual Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:64
virtual bool is_colon_equiv(octave_idx_type) const
Definition: idx-vector.h:112
virtual octave_idx_type length(octave_idx_type n) const =0
refcount< octave_idx_type > m_count
Definition: idx-vector.h:122
virtual idx_class_type idx_class(void) const
Definition: idx-vector.h:104
OCTAVE_API octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:82
OCTAVE_NORETURN idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:91
OCTAVE_API std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:97
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.cc:654
OCTAVE_API idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:723
OCTAVE_API std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:679
OCTAVE_API Array< bool > unconvert(void) const
Definition: idx-vector.cc:694
const bool * get_data(void) const
Definition: idx-vector.h:408
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:391
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:671
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:393
OCTAVE_API Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:707
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:403
OCTAVE_API range< double > unconvert(void) const
Definition: idx-vector.cc:192
OCTAVE_API idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:155
OCTAVE_API std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:186
OCTAVE_API Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:198
octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:147
octave_idx_type length(octave_idx_type) const
Definition: idx-vector.h:191
OCTAVE_API idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:167
octave_idx_type get_start(void) const
Definition: idx-vector.h:210
octave_idx_type get_step(void) const
Definition: idx-vector.h:212
OCTAVE_API idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:267
octave_idx_type get_data(void) const
Definition: idx-vector.h:267
OCTAVE_API double unconvert(void) const
Definition: idx-vector.cc:280
OCTAVE_API Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:285
OCTAVE_API std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:275
OCTAVE_API octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:258
const octave_idx_type * get_data(void) const
Definition: idx-vector.h:335
OCTAVE_API Array< double > unconvert(void) const
Definition: idx-vector.cc:582
idx_base_rep * sort_uniq_clone(bool uniq=false)
Definition: idx-vector.cc:433
Array< octave_idx_type > * m_aowner
Definition: idx-vector.h:356
const octave_idx_type * m_data
Definition: idx-vector.h:345
octave_idx_type xelem(octave_idx_type i) const
Definition: idx-vector.h:318
OCTAVE_API Array< octave_idx_type > as_array(void)
Definition: idx-vector.cc:590
OCTAVE_API idx_base_rep * sort_idx(Array< octave_idx_type > &)
Definition: idx-vector.cc:512
OCTAVE_API std::ostream & print(std::ostream &os) const
Definition: idx-vector.cc:567
OCTAVE_API octave_idx_type checkelem(octave_idx_type i) const
Definition: idx-vector.cc:424
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:324
OCTAVE_API void copy_data(octave_idx_type *data) const
Definition: idx-vector.cc:1009
OCTAVE_API octave_idx_type freeze(octave_idx_type z_len, const char *tag, bool resize_ok=false)
Definition: idx-vector.cc:1236
bool is_colon(void) const
Definition: idx-vector.h:556
OCTAVE_API Array< octave_idx_type > as_array(void) const
Definition: idx-vector.cc:1225
idx_vector sorted(bool uniq=false) const
Definition: idx-vector.h:568
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:540
OCTAVE_API idx_vector inverse_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1124
idx_base_rep * m_rep
Definition: idx-vector.h:1029
octave_idx_type max(void) const
Definition: idx-vector.h:1025
octave_idx_type xelem(octave_idx_type n) const
Definition: idx-vector.h:543
idx_class_type idx_class(void) const
Definition: idx-vector.h:535
OCTAVE_API idx_vector complement(octave_idx_type n) const
Definition: idx-vector.cc:1066
OCTAVE_API bool maybe_reduce(octave_idx_type n, const idx_vector &j, octave_idx_type nj)
Definition: idx-vector.cc:747
octave_idx_type elem(octave_idx_type n) const
Definition: idx-vector.h:1011
OCTAVE_API octave_idx_type ones_count(void) const
Definition: idx-vector.cc:1245
OCTAVE_API bool isvector(void) const
Definition: idx-vector.cc:1230
OCTAVE_API bool is_cont_range(octave_idx_type n, octave_idx_type &l, octave_idx_type &u) const
Definition: idx-vector.cc:915
static OCTAVE_API idx_vector_rep * nil_rep(void)
Definition: idx-vector.cc:58
static const idx_vector colon
Definition: idx-vector.h:483
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:574
octave_idx_type fill(const T &val, octave_idx_type n, T *dest) const
Definition: idx-vector.h:748
OCTAVE_API idx_vector unmask(void) const
Definition: idx-vector.cc:1158
OCTAVE_API octave_idx_type increment(void) const
Definition: idx-vector.cc:968
OCTAVE_API void unconvert(idx_class_type &iclass, double &scalar, range< double > &range, Array< double > &array, Array< bool > &mask) const
Definition: idx-vector.cc:1181
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:537
OCTAVE_API bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1096
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:565
const OCTAVE_API octave_idx_type * raw(void)
Definition: idx-vector.cc:997
T value(void) const
Definition: oct-inttypes.h:830
void set_compare(const compare_fcn_type &comp)
Definition: oct-sort.h:121
void sort(T *data, octave_idx_type nel)
Definition: oct-sort.cc:1520
#define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T)
Definition: idx-vector.cc:1262
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
std::complex< T > trunc(const std::complex< T > &x)
Definition: lo-mappers.h:111
Complex log2(const Complex &x)
Definition: lo-mappers.cc:139
static OCTAVE_NORETURN void err_index_out_of_range(void)
Definition: idx-vector.cc:52
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
octave_idx_type convert_index(octave_idx_type i, octave_idx_type &ext)
Definition: idx-vector.cc:207
class OCTAVE_API range
Definition: range-fwd.h:33
static int left
Definition: randmtzig.cc:193
static OCTAVE_NORETURN void err_invalid_range(void)
Definition: idx-vector.cc:47
STL namespace.
#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)
Definition: oct-locbuf.h:50
@ ASCENDING
Definition: oct-sort.h:97
T::size_type numel(const T &str)
Definition: oct-string.cc:71
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:679