GNU Octave  4.4.1
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-2018 John W. Eaton
4 Copyright (C) 2009 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include "Array-util.h"
29 #include "lo-error.h"
30 #include "oct-locbuf.h"
31 
32 bool
34  const dim_vector& dimensions)
35 {
36  bool retval = true;
37 
38  int n = ra_idx.numel ();
39 
40  if (n == dimensions.ndims ())
41  {
42  for (int i = 0; i < n; i++)
43  {
44  if (ra_idx(i) < 0 || ra_idx(i) >= dimensions(i))
45  {
46  retval = false;
47  break;
48  }
49  }
50  }
51  else
52  retval = false;
53 
54  return retval;
55 }
56 
57 void
59  int start_dimension)
60 {
61  ra_idx(start_dimension)++;
62 
63  int n = ra_idx.numel () - 1;
64  int nda = dimensions.ndims ();
65 
66  for (int i = start_dimension; i < n; i++)
67  {
68  if (ra_idx(i) < (i < nda ? dimensions(i) : 1))
69  break;
70  else
71  {
72  ra_idx(i) = 0;
73  ra_idx(i+1)++;
74  }
75  }
76 }
77 
80 {
82 
83  int n = idx.numel ();
84 
85  if (n > 0)
86  {
87  retval = idx(--n);
88 
89  while (--n >= 0)
90  {
91  retval *= dims(n);
92 
93  retval += idx(n);
94  }
95  }
96  return retval;
97 }
98 
101 {
103 
104  for (octave_idx_type i = 0; i < ra_idx.numel (); i++)
105  {
106  if (ra_idx(i) == 1)
107  retval++;
108  }
109 
110  return retval;
111 }
112 
113 bool
114 is_scalar (const dim_vector& dim)
115 {
116  bool retval = true;
117 
118  int n = dim.ndims ();
119 
120  if (n == 0)
121  retval = false;
122  else
123  {
124  for (int i = 0; i < n; i++)
125  {
126  if (dim(i) != 1)
127  {
128  retval = false;
129 
130  break;
131  }
132  }
133  }
134  return retval;
135 }
136 
137 bool
138 isvector (const dim_vector& dim)
139 {
140  int m = 0;
141  int n = dim.ndims ();
142 
143  if (n == 0)
144  m = 2;
145  else
146  {
147  for (int i = 0; i < n; i++)
148  if (dim(i) > 1)
149  m++;
150  else if (dim(i) < 1)
151  m += 2;
152  }
153 
154  return (m < 2);
155 }
156 
157 bool
159 {
160  bool retval = false;
161 
162  for (octave_idx_type i = 0; i < arr.numel (); i++)
163  {
164  if (arr (i) == 1)
165  {
166  retval = true;
167 
168  break;
169  }
170  }
171  return retval;
172 }
173 
176 {
177  if (n < 0)
178  octave::err_invalid_index (n, 1, 1);
179  if (n >= dims.numel ())
180  octave::err_index_out_of_range (1, 1, n+1, dims.numel (), dims);
181 
182  return n;
183 }
184 
187 {
188  if (i < 0)
190  if (j < 0)
191  octave::err_invalid_index (j, 2, 2);
192  if (i >= dims(0))
193  octave::err_index_out_of_range (2, 1, i+1, dims(0), dims);
194  if (j >= dims.numel (1))
195  octave::err_index_out_of_range (2, 2, j+1, dims.numel (1), dims);
196 
197  return j*dims(0) + i;
198 }
199 
202  const dim_vector& dims)
203 {
204  if (i < 0)
206  if (j < 0)
207  octave::err_invalid_index (j, 3, 2);
208  if (k < 0)
210  if (i >= dims(0))
211  octave::err_index_out_of_range (3, 1, i+1, dims(0), dims);
212  if (j >= dims(1))
213  octave::err_index_out_of_range (3, 2, j+1, dims(1), dims);
214  if (k >= dims.numel (2))
215  octave::err_index_out_of_range (3, 3, k+1, dims.numel (2), dims);
216 
217  return (k*dims(1) + j)*dims(0) + i;
218 }
219 
222 {
223  int nd = ra_idx.numel ();
224  const dim_vector dv = dims.redim (nd);
225  for (int d = 0; d < nd; d++)
226  {
227  if (ra_idx(d) < 0)
229  if (ra_idx(d) >= dv(d))
231  }
232 
233  return dv.compute_index (ra_idx.data ());
234 }
235 
238 {
239  Array<octave_idx_type> retval (a.dims ());
240 
241  for (octave_idx_type i = 0; i < a.numel (); i++)
242  retval(i) = a(i).elem (0);
243 
244  return retval;
245 }
246 
249 {
251 
252  for (octave_idx_type i = 0; i < len; i++)
253  retval(i) = tmp[i];
254 
255  return retval;
256 }
257 
259 freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)
260 {
262 
263  int n = ra_idx.numel ();
264 
265  assert (n == dimensions.ndims ());
266 
267  retval.resize (n);
268 
269  static const char *tag[3] = { "row", "column", nullptr };
270 
271  for (int i = 0; i < n; i++)
272  retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 2],
273  resize_ok);
274 
275  return retval;
276 }
277 
278 bool
280 {
281  int n = dv.ndims ();
282 
283  bool found_first = false;
284 
285  for (int i = 0; i < n; i++)
286  {
287  if (dv(i) != 1)
288  {
289  if (! found_first)
290  found_first = true;
291  else
292  return false;
293  }
294  }
295 
296  return true;
297 }
298 
299 bool
301 {
302  bool retval = true;
303 
305 
306  for (octave_idx_type i = 0; i < n; i++)
307  {
308  if (! ra_idx(i))
309  {
310  retval = false;
311  break;
312  }
313  }
314 
315  return retval;
316 }
317 
318 bool
320 {
321  bool retval = false;
322 
324 
325  for (octave_idx_type i = 0; i < n; i++)
326  {
327  if (ra_idx(i).orig_empty ())
328  {
329  retval = true;
330  break;
331  }
332  }
333 
334  return retval;
335 }
336 
337 bool
339  const dim_vector& frozen_lengths)
340 {
341  bool retval = true;
342 
343  octave_idx_type idx_n = ra_idx.numel ();
344 
345  int n = frozen_lengths.ndims ();
346 
347  assert (idx_n == n);
348 
349  for (octave_idx_type i = 0; i < n; i++)
350  {
351  if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))
352  {
353  retval = false;
354  break;
355  }
356  }
357 
358  return retval;
359 }
360 
361 bool
363 {
364  bool retval = true;
365 
366  for (octave_idx_type i = 0; i < arr.numel (); i++)
367  {
368  if (arr(i) != 1)
369  {
370  retval = false;
371  break;
372  }
373  }
374 
375  return retval;
376 }
377 
380  const Array<octave_idx_type>& result_idx)
381 {
383 
385 
386  for (octave_idx_type i = 0; i < n; i++)
387  retval(i) = ra_idx(i).elem (result_idx(i));
388 
389  return retval;
390 }
391 
394 {
396 
397  int n_dims = dims.ndims ();
398 
399  retval.resize (dim_vector (n_dims, 1));
400 
401  for (int i = 0; i < n_dims; i++)
402  retval(i) = 0;
403 
404  assert (idx > 0 || idx < dims.numel ());
405 
406  for (octave_idx_type i = 0; i < idx; i++)
408 
409  // FIXME: the solution using increment_index is not efficient.
410 
411 #if 0
412  octave_idx_type var = 1;
413  for (int i = 0; i < n_dims; i++)
414  {
415  std::cout << "idx: " << idx << ", var: " << var
416  << ", dims(" << i << "): " << dims(i) <<"\n";
417  retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
418  idx -= var * retval(i);
419  var = dims(i);
420  }
421 #endif
422 
423  return retval;
424 }
425 
428 {
429  int ial = ia.numel ();
430  int rhdvl = rhdv.ndims ();
431  dim_vector rdv = dim_vector::alloc (ial);
432  bool *scalar = new bool [ial];
433  bool *colon = new bool [ial];
434  // Mark scalars and colons, count non-scalar indices.
435  int nonsc = 0;
436  bool all_colons = true;
437  for (int i = 0; i < ial; i++)
438  {
439  // FIXME: should we check for length() instead?
440  scalar[i] = ia(i).is_scalar ();
441  colon[i] = ia(i).is_colon ();
442  if (! scalar[i]) nonsc++;
443  if (! colon[i]) rdv(i) = ia(i).extent (0);
444  all_colons = all_colons && colon[i];
445  }
446 
447  // If the number of nonscalar indices matches the dimensionality of
448  // RHS, we try an exact match, inquiring even singleton dimensions.
449  if (all_colons)
450  {
451  rdv = rhdv;
452  rdv.resize (ial, 1);
453  }
454  else if (nonsc == rhdvl)
455  {
456  for (int i = 0, j = 0; i < ial; i++)
457  {
458  if (scalar[i]) continue;
459  if (colon[i])
460  rdv(i) = rhdv(j);
461  j++;
462  }
463  }
464  else
465  {
466  dim_vector rhdv0 = rhdv;
467  rhdv0.chop_all_singletons ();
468  int rhdv0l = rhdv0.ndims ();
469  for (int i = 0, j = 0; i < ial; i++)
470  {
471  if (scalar[i]) continue;
472  if (colon[i])
473  rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
474  }
475  }
476 
477  delete [] scalar;
478  delete [] colon;
479 
480  return rdv;
481 }
482 
485  const dim_vector& rhdv)
486 {
487  bool icol = i.is_colon ();
488  bool jcol = j.is_colon ();
489  dim_vector rdv;
490  if (icol && jcol && rhdv.ndims () == 2)
491  {
492  rdv(0) = rhdv(0);
493  rdv(1) = rhdv(1);
494  }
495  else if (rhdv.ndims () == 2
496  && ! i.is_scalar () && ! j.is_scalar ())
497  {
498  rdv(0) = (icol ? rhdv(0) : i.extent (0));
499  rdv(1) = (jcol ? rhdv(1) : j.extent (0));
500  }
501  else
502  {
503  dim_vector rhdv0 = rhdv;
504  rhdv0.chop_all_singletons ();
505  int k = 0;
506  rdv(0) = i.extent (0);
507  if (icol)
508  rdv(0) = rhdv0(k++);
509  else if (! i.is_scalar ())
510  k++;
511  rdv(1) = j.extent (0);
512  if (jcol)
513  rdv(1) = rhdv0(k++);
514  else if (! j.is_scalar ())
515  k++;
516  }
517 
518  return rdv;
519 }
520 
521 // A helper class.
523 {
525 
527  : ind(_ind), n(_n) { }
528 
529  void operator ()(octave_idx_type k) { (*ind++ *= n) += k; }
530 };
531 
533 sub2ind (const dim_vector& dv, const Array<idx_vector>& idxa)
534 {
536  octave_idx_type len = idxa.numel ();
537 
538  if (len == 0)
539  (*current_liboctave_error_handler) ("sub2ind: needs at least 2 indices");
540 
541  const dim_vector dvx = dv.redim (len);
542  bool all_ranges = true;
543  octave_idx_type clen = -1;
544 
545  for (octave_idx_type i = 0; i < len; i++)
546  {
547  try
548  {
549  idx_vector idx = idxa(i);
550  octave_idx_type n = dvx(i);
551 
552  all_ranges = all_ranges && idx.is_range ();
553  if (clen < 0)
554  clen = idx.length (n);
555  else if (clen != idx.length (n))
557  ("sub2ind: lengths of indices must match");
558 
559  if (idx.extent (n) > n)
560  octave::err_index_out_of_range (len, i+1, idx.extent (n), n);
561  }
562  catch (octave::index_exception& e)
563  {
564  e.set_pos_if_unset (len, i+1);
565  e.set_var ();
566  std::string msg = e.message ();
567  (*current_liboctave_error_with_id_handler)
568  (e.err_id (), msg.c_str ());
569  }
570  }
571  // idxa known to be valid.
572  // Shouldn't need to catch index_exception below here.
573 
574  if (len == 1)
575  retval = idxa(0);
576  else if (clen == 1)
577  {
578  // All scalars case - the result is a scalar.
579  octave_idx_type idx = idxa(len-1)(0);
580  for (octave_idx_type i = len - 2; i >= 0; i--)
581  idx = dvx(i) * idx + idxa(i)(0);
582  retval = idx_vector (idx);
583  }
584  else if (all_ranges && clen != 0)
585  {
586  // All ranges case - the result is a range.
588  octave_idx_type step = 0;
589  for (octave_idx_type i = len - 1; i >= 0; i--)
590  {
591  octave_idx_type xstart = idxa(i)(0);
592  octave_idx_type xstep = idxa(i)(1) - xstart;
593  start = dvx(i) * start + xstart;
594  step = dvx(i) * step + xstep;
595  }
596  retval = idx_vector::make_range (start, step, clen);
597  }
598  else
599  {
600  Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
601  octave_idx_type *idx_vec = idx.fortran_vec ();
602 
603  for (octave_idx_type i = len - 1; i >= 0; i--)
604  {
605  if (i < len - 1)
606  idxa(i).loop (clen, sub2ind_helper (idx_vec, dvx(i)));
607  else
608  idxa(i).copy_data (idx_vec);
609  }
610 
611  retval = idx_vector (idx);
612  }
613 
614  return retval;
615 }
616 
618 ind2sub (const dim_vector& dv, const idx_vector& idx)
619 {
620  octave_idx_type len = idx.length (0);
621  octave_idx_type n = dv.ndims ();
624 
625  if (idx.extent (numel) > numel)
626  (*current_liboctave_error_handler) ("ind2sub: index out of range");
627 
628  if (idx.is_scalar ())
629  {
630  octave_idx_type k = idx(0);
631  for (octave_idx_type j = 0; j < n; j++)
632  {
633  retval(j) = k % dv(j);
634  k /= dv(j);
635  }
636  }
637  else
638  {
640 
641  dim_vector odv = idx.orig_dimensions ();
642  for (octave_idx_type j = 0; j < n; j++)
643  rdata[j] = Array<octave_idx_type> (odv);
644 
645  for (octave_idx_type i = 0; i < len; i++)
646  {
647  octave_idx_type k = idx(i);
648  for (octave_idx_type j = 0; j < n; j++)
649  {
650  rdata[j](i) = k % dv(j);
651  k /= dv(j);
652  }
653  }
654 
655  for (octave_idx_type j = 0; j < n; j++)
656  retval(j) = rdata[j];
657  }
658 
659  return retval;
660 }
661 
662 int
663 permute_vector_compare (const void *a, const void *b)
664 {
665  const permute_vector *pva = static_cast<const permute_vector *> (a);
666  const permute_vector *pvb = static_cast<const permute_vector *> (b);
667 
668  return pva->pidx > pvb->pidx;
669 }
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:175
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:593
octave_idx_type compute_index(const octave_idx_type *idx) const
Linear index from an index tuple.
Definition: dim-vector.h:487
bool all_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:362
bool index_in_bounds(const Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition: Array-util.cc:33
const octave_base_value const Array< octave_idx_type > & ra_idx
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
bool any_orig_empty(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:319
dim_vector zero_dims_inquire(const Array< idx_vector > &ia, const dim_vector &rhdv)
Definition: Array-util.cc:427
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
for large enough k
Definition: lu.cc:617
void resize(int n, int fill_value=0)
Definition: dim-vector.h:310
const T * fortran_vec(void) const
Definition: Array.h:584
void err_index_out_of_range(int nd, int dim, octave_idx_type idx, octave_idx_type ext)
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
void operator()(octave_idx_type k)
Definition: Array-util.cc:529
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:139
bool vector_equivalent(const dim_vector &dv)
Definition: Array-util.cc:279
virtual octave_idx_type numel(const octave_value_list &)
Definition: ov-base.cc:193
octave_idx_type * ind
Definition: Array-util.cc:524
i e
Definition: data.cc:2591
Array< octave_idx_type > get_ra_idx(octave_idx_type idx, const dim_vector &dims)
Definition: Array-util.cc:393
var
Definition: givens.cc:88
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_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:511
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool any_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:158
idx_vector sub2ind(const dim_vector &dv, const Array< idx_vector > &idxa)
Definition: Array-util.cc:533
void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension)
Definition: Array-util.cc:58
bool is_range(void) const
Definition: idx-vector.h:581
bool is_colon(void) const
Definition: idx-vector.h:575
void chop_all_singletons(void)
Definition: dim-vector.cc:53
int permute_vector_compare(const void *a, const void *b)
Definition: Array-util.cc:663
double tmp
Definition: data.cc:6252
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:557
octave_value retval
Definition: data.cc:6246
dim_vector freeze(Array< idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:259
bool all_colon_equiv(const Array< idx_vector > &ra_idx, const dim_vector &frozen_lengths)
Definition: Array-util.cc:338
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:237
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
static dim_vector alloc(int n)
Definition: dim-vector.h:264
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:233
bool is_scalar(const dim_vector &dim)
Definition: Array-util.cc:114
bool isvector(const dim_vector &dim)
Definition: Array-util.cc:138
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:125
Array< idx_vector > ind2sub(const dim_vector &dv, const idx_vector &idx)
Definition: Array-util.cc:618
T::size_type numel(const T &str)
Definition: oct-string.cc:61
octave::sys::time start
Definition: graphics.cc:12337
bool all_ok(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:300
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:362
b
Definition: cellfun.cc:400
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
sub2ind_helper(octave_idx_type *_ind, octave_idx_type _n)
Definition: Array-util.cc:526
octave_idx_type get_scalar_idx(Array< octave_idx_type > &idx, dim_vector &dims)
Definition: Array-util.cc:79
for i
Definition: data.cc:5264
octave_idx_type pidx
Definition: Array-util.h:109
Array< idx_vector > conv_to_array(const idx_vector *tmp, const octave_idx_type len)
Definition: Array-util.cc:248
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
octave_idx_type num_ones(const Array< octave_idx_type > &ra_idx)
Definition: Array-util.cc:100
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
bool is_scalar(void) const
Definition: idx-vector.h:578
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:482
dim_vector dv
Definition: sub2ind.cc:263
octave_idx_type n
Definition: Array-util.cc:524
Array< octave_idx_type > get_elt_idx(const Array< idx_vector > &ra_idx, const Array< octave_idx_type > &result_idx)
Definition: Array-util.cc:379