GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Array-util.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2003-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 "Array-util.h"
31#include "lo-error.h"
32#include "oct-locbuf.h"
33
34bool
36 const dim_vector& dimensions)
37{
38 bool retval = true;
39
40 int n = ra_idx.numel ();
41
42 if (n == dimensions.ndims ())
43 {
44 for (int i = 0; i < n; i++)
45 {
46 if (ra_idx(i) < 0 || ra_idx(i) >= dimensions(i))
47 {
48 retval = false;
49 break;
50 }
51 }
52 }
53 else
54 retval = false;
55
56 return retval;
57}
58
59void
61 int start_dimension)
62{
63 ra_idx(start_dimension)++;
64
65 int n = ra_idx.numel () - 1;
66 int nda = dimensions.ndims ();
67
68 for (int i = start_dimension; i < n; i++)
69 {
70 if (ra_idx(i) < (i < nda ? dimensions(i) : 1))
71 break;
72 else
73 {
74 ra_idx(i) = 0;
75 ra_idx(i+1)++;
76 }
77 }
78}
79
82{
83 octave_idx_type retval (-1);
84
85 int n = idx.numel ();
86
87 if (n > 0)
88 {
89 retval = idx(--n);
90
91 while (--n >= 0)
92 {
93 retval *= dims(n);
94
95 retval += idx(n);
96 }
97 }
98 return retval;
99}
100
103{
104 octave_idx_type retval = 0;
105
106 for (octave_idx_type i = 0; i < ra_idx.numel (); i++)
107 {
108 if (ra_idx(i) == 1)
109 retval++;
110 }
111
112 return retval;
113}
114
115bool
117{
118 bool retval = true;
119
120 int n = dim.ndims ();
121
122 if (n == 0)
123 retval = false;
124 else
125 {
126 for (int i = 0; i < n; i++)
127 {
128 if (dim(i) != 1)
129 {
130 retval = false;
131
132 break;
133 }
134 }
135 }
136 return retval;
137}
138
139bool
141{
142 int m = 0;
143 int n = dim.ndims ();
144
145 if (n == 0)
146 m = 2;
147 else
148 {
149 for (int i = 0; i < n; i++)
150 if (dim(i) > 1)
151 m++;
152 else if (dim(i) < 1)
153 m += 2;
154 }
155
156 return (m < 2);
157}
158
159bool
161{
162 bool retval = false;
163
164 for (octave_idx_type i = 0; i < arr.numel (); i++)
165 {
166 if (arr (i) == 1)
167 {
168 retval = true;
169
170 break;
171 }
172 }
173 return retval;
174}
175
178{
179 if (n < 0)
181 if (n >= dims.numel ())
182 octave::err_index_out_of_range (1, 1, n+1, dims.numel (), dims);
183
184 return n;
185}
186
189{
190 if (i < 0)
192 if (j < 0)
194 if (i >= dims(0))
195 octave::err_index_out_of_range (2, 1, i+1, dims(0), dims);
196 if (j >= dims.numel (1))
197 octave::err_index_out_of_range (2, 2, j+1, dims.numel (1), dims);
198
199 return j*dims(0) + i;
200}
201
204 const dim_vector& dims)
205{
206 if (i < 0)
208 if (j < 0)
210 if (k < 0)
212 if (i >= dims(0))
213 octave::err_index_out_of_range (3, 1, i+1, dims(0), dims);
214 if (j >= dims(1))
215 octave::err_index_out_of_range (3, 2, j+1, dims(1), dims);
216 if (k >= dims.numel (2))
217 octave::err_index_out_of_range (3, 3, k+1, dims.numel (2), dims);
218
219 return (k*dims(1) + j)*dims(0) + i;
220}
221
224{
225 int nd = ra_idx.numel ();
226 const dim_vector dv = dims.redim (nd);
227 for (int d = 0; d < nd; d++)
228 {
229 if (ra_idx(d) < 0)
231 if (ra_idx(d) >= dv(d))
232 octave::err_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d), dims);
233 }
234
235 return dv.compute_index (ra_idx.data ());
236}
237
240{
241 Array<octave_idx_type> retval (a.dims ());
242
243 for (octave_idx_type i = 0; i < a.numel (); i++)
244 retval(i) = a(i).elem (0);
245
246 return retval;
247}
248
251{
253
254 for (octave_idx_type i = 0; i < len; i++)
255 retval(i) = tmp[i];
256
257 return retval;
258}
259
261freeze (Array<octave::idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)
262{
263 dim_vector retval;
264
265 int n = ra_idx.numel ();
266
267 assert (n == dimensions.ndims ());
268
269 retval.resize (n);
270
271 static const char *tag[3] = { "row", "column", nullptr };
272
273 for (int i = 0; i < n; i++)
274 retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 2],
275 resize_ok);
276
277 return retval;
278}
279
280bool
282{
283 int n = dv.ndims ();
284
285 bool found_first = false;
286
287 for (int i = 0; i < n; i++)
288 {
289 if (dv(i) != 1)
290 {
291 if (! found_first)
292 found_first = true;
293 else
294 return false;
295 }
296 }
297
298 return true;
299}
300
301bool
303{
304 bool retval = true;
305
307
308 for (octave_idx_type i = 0; i < n; i++)
309 {
310 if (! ra_idx(i))
311 {
312 retval = false;
313 break;
314 }
315 }
316
317 return retval;
318}
319
320bool
322{
323 bool retval = false;
324
326
327 for (octave_idx_type i = 0; i < n; i++)
328 {
329 if (ra_idx(i).orig_empty ())
330 {
331 retval = true;
332 break;
333 }
334 }
335
336 return retval;
337}
338
339bool
341 const dim_vector& frozen_lengths)
342{
343 bool retval = true;
344
345 octave_idx_type idx_n = ra_idx.numel ();
346
347 int n = frozen_lengths.ndims ();
348
349 assert (idx_n == n);
350
351 for (octave_idx_type i = 0; i < n; i++)
352 {
353 if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))
354 {
355 retval = false;
356 break;
357 }
358 }
359
360 return retval;
361}
362
363bool
365{
366 bool retval = true;
367
368 for (octave_idx_type i = 0; i < arr.numel (); i++)
369 {
370 if (arr(i) != 1)
371 {
372 retval = false;
373 break;
374 }
375 }
376
377 return retval;
378}
379
382 const Array<octave_idx_type>& result_idx)
383{
385
386 Array<octave_idx_type> retval (dim_vector (n, 1));
387
388 for (octave_idx_type i = 0; i < n; i++)
389 retval(i) = ra_idx(i).elem (result_idx(i));
390
391 return retval;
392}
393
396{
398
399 int n_dims = dims.ndims ();
400
401 retval.resize (dim_vector (n_dims, 1));
402
403 for (int i = 0; i < n_dims; i++)
404 retval(i) = 0;
405
406 assert (idx > 0 || idx < dims.numel ());
407
408 for (octave_idx_type i = 0; i < idx; i++)
409 increment_index (retval, dims);
410
411 // FIXME: the solution using increment_index is not efficient.
412
413#if 0
414 octave_idx_type var = 1;
415 for (int i = 0; i < n_dims; i++)
416 {
417 std::cout << "idx: " << idx << ", var: " << var
418 << ", dims(" << i << "): " << dims(i) <<"\n";
419 retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
420 idx -= var * retval(i);
421 var = dims(i);
422 }
423#endif
424
425 return retval;
426}
427
430{
431 int ial = ia.numel ();
432 int rhdvl = rhdv.ndims ();
433 dim_vector rdv = dim_vector::alloc (ial);
434 bool *scalar = new bool [ial];
435 bool *colon = new bool [ial];
436 // Mark scalars and colons, count non-scalar indices.
437 int nonsc = 0;
438 bool all_colons = true;
439 for (int i = 0; i < ial; i++)
440 {
441 // FIXME: should we check for length() instead?
442 scalar[i] = ia(i).is_scalar ();
443 colon[i] = ia(i).is_colon ();
444 if (! scalar[i]) nonsc++;
445 if (! colon[i]) rdv(i) = ia(i).extent (0);
446 all_colons = all_colons && colon[i];
447 }
448
449 // If the number of nonscalar indices matches the dimensionality of
450 // RHS, we try an exact match, inquiring even singleton dimensions.
451 if (all_colons)
452 {
453 rdv = rhdv;
454 rdv.resize (ial, 1);
455 }
456 else if (nonsc == rhdvl)
457 {
458 for (int i = 0, j = 0; i < ial; i++)
459 {
460 if (scalar[i]) continue;
461 if (colon[i])
462 rdv(i) = rhdv(j);
463 j++;
464 }
465 }
466 else
467 {
468 dim_vector rhdv0 = rhdv;
469 rhdv0.chop_all_singletons ();
470 int rhdv0l = rhdv0.ndims ();
471 for (int i = 0, j = 0; i < ial; i++)
472 {
473 if (scalar[i]) continue;
474 if (colon[i])
475 rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
476 }
477 }
478
479 delete [] scalar;
480 delete [] colon;
481
482 return rdv;
483}
484
487 const dim_vector& rhdv)
488{
489 bool icol = i.is_colon ();
490 bool jcol = j.is_colon ();
491 dim_vector rdv;
492 if (icol && jcol && rhdv.ndims () == 2)
493 {
494 rdv(0) = rhdv(0);
495 rdv(1) = rhdv(1);
496 }
497 else if (rhdv.ndims () == 2
498 && ! i.is_scalar () && ! j.is_scalar ())
499 {
500 rdv(0) = (icol ? rhdv(0) : i.extent (0));
501 rdv(1) = (jcol ? rhdv(1) : j.extent (0));
502 }
503 else
504 {
505 dim_vector rhdv0 = rhdv;
506 rhdv0.chop_all_singletons ();
507 int k = 0;
508 rdv(0) = i.extent (0);
509 if (icol)
510 rdv(0) = rhdv0(k++);
511 else if (! i.is_scalar ())
512 k++;
513 rdv(1) = j.extent (0);
514 if (jcol)
515 rdv(1) = rhdv0(k++);
516 else if (! j.is_scalar ())
517 k++;
518 }
519
520 return rdv;
521}
522
525{
526 octave::idx_vector retval;
527 octave_idx_type len = idxa.numel ();
528
529 if (len == 0)
530 (*current_liboctave_error_handler) ("sub2ind: needs at least 2 indices");
531
532 const dim_vector dvx = dv.redim (len);
533 bool all_ranges = true;
534 octave_idx_type clen = -1;
535
536 for (octave_idx_type i = 0; i < len; i++)
537 {
538 try
539 {
540 octave::idx_vector idx = idxa(i);
541 octave_idx_type n = dvx(i);
542
543 all_ranges = all_ranges && idx.is_range ();
544 if (clen < 0)
545 clen = idx.length (n);
546 else if (clen != idx.length (n))
547 (*current_liboctave_error_handler)
548 ("sub2ind: lengths of indices must match");
549
550 if (idx.extent (n) > n)
551 octave::err_index_out_of_range (len, i+1, idx.extent (n), n, dv);
552 }
553 catch (octave::index_exception& ie)
554 {
555 ie.set_pos_if_unset (len, i+1);
556 ie.set_var ();
557 std::string msg = ie.message ();
558 (*current_liboctave_error_with_id_handler)
559 (ie.err_id (), "%s", msg.c_str ());
560 }
561 }
562 // idxa known to be valid.
563 // Shouldn't need to catch index_exception below here.
564
565 if (len == 1)
566 retval = idxa(0);
567 else if (clen == 1)
568 {
569 // All scalars case - the result is a scalar.
570 octave_idx_type idx = idxa(len-1)(0);
571 for (octave_idx_type i = len - 2; i >= 0; i--)
572 idx = dvx(i) * idx + idxa(i)(0);
573 retval = octave::idx_vector (idx);
574 }
575 else if (all_ranges && clen != 0)
576 {
577 // All ranges case - the result is a range.
578 octave_idx_type start = 0;
579 octave_idx_type step = 0;
580 for (octave_idx_type i = len - 1; i >= 0; i--)
581 {
582 octave_idx_type xstart = idxa(i)(0);
583 octave_idx_type xstep = idxa(i)(1) - xstart;
584 start = dvx(i) * start + xstart;
585 step = dvx(i) * step + xstep;
586 }
587 retval = octave::idx_vector::make_range (start, step, clen);
588 }
589 else
590 {
591 Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
592
593 for (octave_idx_type i = len - 1; i >= 0; i--)
594 {
595 // Initialized inside the loop so that each call to
596 // idx_vector::loop operates from the beginning of IDX_VEC.
597
598 octave_idx_type *idx_vec = idx.fortran_vec ();
599
600 if (i < len - 1)
601 {
602 octave_idx_type n = dvx(i);
603
604 idxa(i).loop (clen, [=, &idx_vec] (octave_idx_type k) {
605 (*idx_vec++ *= n) += k;
606 });
607 }
608 else
609 idxa(i).copy_data (idx_vec);
610 }
611
612 retval = octave::idx_vector (idx);
613 }
614
615 return retval;
616}
617
619ind2sub (const dim_vector& dv, const octave::idx_vector& idx)
620{
621 octave_idx_type len = idx.length (0);
622 octave_idx_type n = dv.ndims ();
625
626 if (idx.extent (numel) > numel)
627 (*current_liboctave_error_handler) ("ind2sub: index out of range");
628
629 if (idx.is_scalar ())
630 {
631 octave_idx_type k = idx(0);
632 for (octave_idx_type j = 0; j < n; j++)
633 {
634 retval(j) = k % dv(j);
635 k /= dv(j);
636 }
637 }
638 else
639 {
641
642 dim_vector odv = idx.orig_dimensions ();
643 for (octave_idx_type j = 0; j < n; j++)
644 rdata[j] = Array<octave_idx_type> (odv);
645
646 for (octave_idx_type i = 0; i < len; i++)
647 {
648 octave_idx_type k = idx(i);
649 for (octave_idx_type j = 0; j < n; j++)
650 {
651 rdata[j](i) = k % dv(j);
652 k /= dv(j);
653 }
654 }
655
656 for (octave_idx_type j = 0; j < n; j++)
657 retval(j) = rdata[j];
658 }
659
660 return retval;
661}
662
663int
664permute_vector_compare (const void *a, const void *b)
665{
666 const permute_vector *pva = static_cast<const permute_vector *> (a);
667 const permute_vector *pvb = static_cast<const permute_vector *> (b);
668
669 return pva->pidx > pvb->pidx;
670}
Array< octave_idx_type > get_ra_idx(octave_idx_type idx, const dim_vector &dims)
Definition: Array-util.cc:395
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:177
bool is_scalar(const dim_vector &dim)
Definition: Array-util.cc:116
int permute_vector_compare(const void *a, const void *b)
Definition: Array-util.cc:664
dim_vector zero_dims_inquire(const Array< octave::idx_vector > &ia, const dim_vector &rhdv)
Definition: Array-util.cc:429
octave::idx_vector sub2ind(const dim_vector &dv, const Array< octave::idx_vector > &idxa)
Definition: Array-util.cc:524
bool all_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:364
octave_idx_type num_ones(const Array< octave_idx_type > &ra_idx)
Definition: Array-util.cc:102
bool all_colon_equiv(const Array< octave::idx_vector > &ra_idx, const dim_vector &frozen_lengths)
Definition: Array-util.cc:340
bool vector_equivalent(const dim_vector &dv)
Definition: Array-util.cc:281
bool any_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:160
Array< octave::idx_vector > conv_to_array(const octave::idx_vector *tmp, const octave_idx_type len)
Definition: Array-util.cc:250
dim_vector freeze(Array< octave::idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:261
bool any_orig_empty(const Array< octave::idx_vector > &ra_idx)
Definition: Array-util.cc:321
Array< octave::idx_vector > ind2sub(const dim_vector &dv, const octave::idx_vector &idx)
Definition: Array-util.cc:619
bool isvector(const dim_vector &dim)
Definition: Array-util.cc:140
Array< octave_idx_type > get_elt_idx(const Array< octave::idx_vector > &ra_idx, const Array< octave_idx_type > &result_idx)
Definition: Array-util.cc:381
bool index_in_bounds(const Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition: Array-util.cc:35
bool all_ok(const Array< octave::idx_vector > &ra_idx)
Definition: Array-util.cc:302
Array< octave_idx_type > conv_to_int_array(const Array< octave::idx_vector > &a)
Definition: Array-util.cc:239
void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension)
Definition: Array-util.cc:60
octave_idx_type get_scalar_idx(Array< octave_idx_type > &idx, dim_vector &dims)
Definition: Array-util.cc:81
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
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:534
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array.cc:1744
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
OCTAVE_API void chop_all_singletons(void)
Definition: dim-vector.cc:50
octave_idx_type compute_index(const octave_idx_type *idx) const
Linear index from an index tuple.
Definition: dim-vector.h:456
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:335
void resize(int n, int fill_value=0)
Definition: dim-vector.h:272
static dim_vector alloc(int n)
Definition: dim-vector.h:202
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
OCTAVE_API dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:226
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:469
bool is_colon(void) const
Definition: idx-vector.h:556
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:540
bool is_scalar(void) const
Definition: idx-vector.h:559
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:574
bool is_range(void) const
Definition: idx-vector.h:562
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:537
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
virtual const char * err_id(void) const =0
void set_var(const std::string &var_arg="")
virtual octave_idx_type numel(void) const
Definition: ov-base.h:365
octave::idx_vector idx_vector
Definition: idx-vector.h:1037
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:130
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 &)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
T::size_type numel(const T &str)
Definition: oct-string.cc:71
const octave_base_value const Array< octave_idx_type > & ra_idx
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:679
octave_idx_type pidx
Definition: Array-util.h:114
F77_RET_T len
Definition: xerbla.cc:61