GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Array-util.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2003-2017 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 the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 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 <http://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 "dim-vector.h"
30 #include "lo-error.h"
31 #include "oct-locbuf.h"
32 
33 bool
35  const dim_vector& dimensions)
36 {
37  bool retval = true;
38 
39  int n = ra_idx.numel ();
40 
41  if (n == dimensions.ndims ())
42  {
43  for (int i = 0; i < n; i++)
44  {
45  if (ra_idx(i) < 0 || ra_idx(i) >= dimensions(i))
46  {
47  retval = false;
48  break;
49  }
50  }
51  }
52  else
53  retval = false;
54 
55  return retval;
56 }
57 
58 void
60  int start_dimension)
61 {
62  ra_idx(start_dimension)++;
63 
64  int n = ra_idx.numel () - 1;
65  int nda = dimensions.ndims ();
66 
67  for (int i = start_dimension; i < n; i++)
68  {
69  if (ra_idx(i) < (i < nda ? dimensions(i) : 1))
70  break;
71  else
72  {
73  ra_idx(i) = 0;
74  ra_idx(i+1)++;
75  }
76  }
77 }
78 
81 {
83 
84  int n = idx.numel ();
85 
86  if (n > 0)
87  {
88  retval = idx(--n);
89 
90  while (--n >= 0)
91  {
92  retval *= dims(n);
93 
94  retval += idx(n);
95  }
96  }
97  return retval;
98 }
99 
102 {
104 
105  for (octave_idx_type i = 0; i < ra_idx.numel (); i++)
106  {
107  if (ra_idx(i) == 1)
108  retval++;
109  }
110 
111  return retval;
112 }
113 
114 bool
115 is_scalar (const dim_vector& dim)
116 {
117  bool retval = true;
118 
119  int n = dim.ndims ();
120 
121  if (n == 0)
122  retval = false;
123  else
124  {
125  for (int i = 0; i < n; i++)
126  {
127  if (dim(i) != 1)
128  {
129  retval = false;
130 
131  break;
132  }
133  }
134  }
135  return retval;
136 }
137 
138 bool
139 is_vector (const dim_vector& dim)
140 {
141  int m = 0;
142  int n = dim.ndims ();
143 
144  if (n == 0)
145  m = 2;
146  else
147  {
148  for (int i = 0; i < n; i++)
149  if (dim(i) > 1)
150  m++;
151  else if (dim(i) < 1)
152  m += 2;
153  }
154 
155  return (m < 2);
156 }
157 
158 bool
160 {
161  bool retval = false;
162 
163  for (octave_idx_type i = 0; i < arr.numel (); i++)
164  {
165  if (arr (i) == 1)
166  {
167  retval = true;
168 
169  break;
170  }
171  }
172  return retval;
173 }
174 
177 {
178  if (n < 0)
179  octave::err_invalid_index (n, 1, 1);
180  if (n >= dims.numel ())
181  octave::err_index_out_of_range (1, 1, n+1, dims.numel (), dims);
182 
183  return n;
184 }
185 
188 {
189  if (i < 0)
190  octave::err_invalid_index (i, 2, 1);
191  if (j < 0)
192  octave::err_invalid_index (j, 2, 2);
193  if (i >= dims(0))
194  octave::err_index_out_of_range (2, 1, i+1, dims(0), dims);
195  if (j >= dims.numel (1))
196  octave::err_index_out_of_range (2, 2, j+1, dims.numel (1), dims);
197 
198  return j*dims(0) + i;
199 }
200 
203  const dim_vector& dims)
204 {
205  if (i < 0)
206  octave::err_invalid_index (i, 3, 1);
207  if (j < 0)
208  octave::err_invalid_index (j, 3, 2);
209  if (k < 0)
210  octave::err_invalid_index (k, 3, 3);
211  if (i >= dims(0))
212  octave::err_index_out_of_range (3, 1, i+1, dims(0), dims);
213  if (j >= dims(1))
214  octave::err_index_out_of_range (3, 2, j+1, dims(1), dims);
215  if (k >= dims.numel (2))
216  octave::err_index_out_of_range (3, 3, k+1, dims.numel (2), dims);
217 
218  return (k*dims(1) + j)*dims(0) + i;
219 }
220 
223 {
224  int nd = ra_idx.numel ();
225  const dim_vector dv = dims.redim (nd);
226  for (int d = 0; d < nd; d++)
227  {
228  if (ra_idx(d) < 0)
230  if (ra_idx(d) >= dv(d))
231  octave::err_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d), dims);
232  }
233 
234  return dv.compute_index (ra_idx.data ());
235 }
236 
239 {
241 
242  for (octave_idx_type i = 0; i < a.numel (); i++)
243  retval(i) = a(i).elem (0);
244 
245  return retval;
246 }
247 
250 {
252 
253  for (octave_idx_type i = 0; i < len; i++)
254  retval(i) = tmp[i];
255 
256  return retval;
257 }
258 
260 freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)
261 {
263 
264  int n = ra_idx.numel ();
265 
266  assert (n == dimensions.ndims ());
267 
268  retval.resize (n);
269 
270  static const char *tag[3] = { "row", "column", 0 };
271 
272  for (int i = 0; i < n; i++)
273  retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 2],
274  resize_ok);
275 
276  return retval;
277 }
278 
279 bool
281 {
282  int n = dv.ndims ();
283 
284  bool found_first = false;
285 
286  for (int i = 0; i < n; i++)
287  {
288  if (dv(i) != 1)
289  {
290  if (! found_first)
291  found_first = true;
292  else
293  return false;
294  }
295  }
296 
297  return true;
298 }
299 
300 bool
302 {
303  bool retval = true;
304 
305  octave_idx_type n = ra_idx.numel ();
306 
307  for (octave_idx_type i = 0; i < n; i++)
308  {
309  if (! ra_idx(i))
310  {
311  retval = false;
312  break;
313  }
314  }
315 
316  return retval;
317 }
318 
319 bool
321 {
322  bool retval = false;
323 
324  octave_idx_type n = ra_idx.numel ();
325 
326  for (octave_idx_type i = 0; i < n; i++)
327  {
328  if (ra_idx(i).orig_empty ())
329  {
330  retval = true;
331  break;
332  }
333  }
334 
335  return retval;
336 }
337 
338 bool
340  const dim_vector& frozen_lengths)
341 {
342  bool retval = true;
343 
344  octave_idx_type idx_n = ra_idx.numel ();
345 
346  int n = frozen_lengths.ndims ();
347 
348  assert (idx_n == n);
349 
350  for (octave_idx_type i = 0; i < n; i++)
351  {
352  if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))
353  {
354  retval = false;
355  break;
356  }
357  }
358 
359  return retval;
360 }
361 
362 bool
364 {
365  bool retval = true;
366 
367  for (octave_idx_type i = 0; i < arr.numel (); i++)
368  {
369  if (arr(i) != 1)
370  {
371  retval = false;
372  break;
373  }
374  }
375 
376  return retval;
377 }
378 
381  const Array<octave_idx_type>& result_idx)
382 {
383  octave_idx_type n = ra_idx.numel ();
384 
386 
387  for (octave_idx_type i = 0; i < n; i++)
388  retval(i) = ra_idx(i).elem (result_idx(i));
389 
390  return retval;
391 }
392 
395 {
397 
398  int n_dims = dims.ndims ();
399 
400  retval.resize (dim_vector (n_dims, 1));
401 
402  for (int i = 0; i < n_dims; i++)
403  retval(i) = 0;
404 
405  assert (idx > 0 || idx < dims.numel ());
406 
407  for (octave_idx_type i = 0; i < idx; i++)
408  increment_index (retval, dims);
409 
410  // FIXME: the solution using increment_index is not efficient.
411 
412 #if 0
413  octave_idx_type var = 1;
414  for (int i = 0; i < n_dims; i++)
415  {
416  std::cout << "idx: " << idx << ", var: " << var
417  << ", dims(" << i << "): " << dims(i) <<"\n";
418  retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
419  idx -= var * retval(i);
420  var = dims(i);
421  }
422 #endif
423 
424  return retval;
425 }
426 
429 {
430  int ial = ia.numel ();
431  int rhdvl = rhdv.ndims ();
432  dim_vector rdv = dim_vector::alloc (ial);
433  bool *scalar = new bool [ial];
434  bool *colon = new bool [ial];
435  // Mark scalars and colons, count non-scalar indices.
436  int nonsc = 0;
437  bool all_colons = true;
438  for (int i = 0; i < ial; i++)
439  {
440  // FIXME: should we check for length() instead?
441  scalar[i] = ia(i).is_scalar ();
442  colon[i] = ia(i).is_colon ();
443  if (! scalar[i]) nonsc++;
444  if (! colon[i]) rdv(i) = ia(i).extent (0);
445  all_colons = all_colons && colon[i];
446  }
447 
448  // If the number of nonscalar indices matches the dimensionality of
449  // RHS, we try an exact match, inquiring even singleton dimensions.
450  if (all_colons)
451  {
452  rdv = rhdv;
453  rdv.resize (ial, 1);
454  }
455  else if (nonsc == rhdvl)
456  {
457  for (int i = 0, j = 0; i < ial; i++)
458  {
459  if (scalar[i]) continue;
460  if (colon[i])
461  rdv(i) = rhdv(j);
462  j++;
463  }
464  }
465  else
466  {
467  dim_vector rhdv0 = rhdv;
468  rhdv0.chop_all_singletons ();
469  int rhdv0l = rhdv0.ndims ();
470  for (int i = 0, j = 0; i < ial; i++)
471  {
472  if (scalar[i]) continue;
473  if (colon[i])
474  rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
475  }
476  }
477 
478  delete [] scalar;
479  delete [] colon;
480 
481  return rdv;
482 }
483 
486  const dim_vector& rhdv)
487 {
488  bool icol = i.is_colon ();
489  bool jcol = j.is_colon ();
490  dim_vector rdv;
491  if (icol && jcol && rhdv.ndims () == 2)
492  {
493  rdv(0) = rhdv(0);
494  rdv(1) = rhdv(1);
495  }
496  else if (rhdv.ndims () == 2
497  && ! i.is_scalar () && ! j.is_scalar ())
498  {
499  rdv(0) = icol ? rhdv(0) : i.extent (0);
500  rdv(1) = jcol ? rhdv(1) : j.extent (0);
501  }
502  else
503  {
504  dim_vector rhdv0 = rhdv;
505  rhdv0.chop_all_singletons ();
506  int k = 0;
507  rdv(0) = i.extent (0);
508  if (icol)
509  rdv(0) = rhdv0(k++);
510  else if (! i.is_scalar ())
511  k++;
512  rdv(1) = j.extent (0);
513  if (jcol)
514  rdv(1) = rhdv0(k++);
515  else if (! j.is_scalar ())
516  k++;
517  }
518 
519  return rdv;
520 }
521 
522 // A helper class.
524 {
526 
528  : ind(_ind), n(_n) { }
529 
530  void operator ()(octave_idx_type k) { (*ind++ *= n) += k; }
531 };
532 
534 sub2ind (const dim_vector& dv, const Array<idx_vector>& idxa)
535 {
537  octave_idx_type len = idxa.numel ();
538 
539  if (len == 0)
540  (*current_liboctave_error_handler) ("sub2ind: needs at least 2 indices");
541 
542  const dim_vector dvx = dv.redim (len);
543  bool all_ranges = true;
544  octave_idx_type clen = -1;
545 
546  for (octave_idx_type i = 0; i < len; i++)
547  {
548  try
549  {
550  idx_vector idx = idxa(i);
551  octave_idx_type n = dvx(i);
552 
553  all_ranges = all_ranges && idx.is_range ();
554  if (clen < 0)
555  clen = idx.length (n);
556  else if (clen != idx.length (n))
558  ("sub2ind: lengths of indices must match");
559 
560  if (idx.extent (n) > n)
561  octave::err_index_out_of_range (len, i+1, idx.extent (n), n);
562  }
563  catch (octave::index_exception& e)
564  {
565  e.set_pos_if_unset (len, i+1);
566  e.set_var ();
567  std::string msg = e.message ();
568  (*current_liboctave_error_with_id_handler)
569  (e.err_id (), msg.c_str ());
570  }
571  }
572  // idxa known to be valid.
573  // Shouldn't need to catch index_exception below here.
574 
575  if (len == 1)
576  retval = idxa(0);
577  else if (clen == 1)
578  {
579  // All scalars case - the result is a scalar.
580  octave_idx_type idx = idxa(len-1)(0);
581  for (octave_idx_type i = len - 2; i >= 0; i--)
582  idx = dvx(i) * idx + idxa(i)(0);
583  retval = idx_vector (idx);
584  }
585  else if (all_ranges && clen != 0)
586  {
587  // All ranges case - the result is a range.
589  octave_idx_type step = 0;
590  for (octave_idx_type i = len - 1; i >= 0; i--)
591  {
592  octave_idx_type xstart = idxa(i)(0);
593  octave_idx_type xstep = idxa(i)(1) - xstart;
594  start = dvx(i) * start + xstart;
595  step = dvx(i) * step + xstep;
596  }
597  retval = idx_vector::make_range (start, step, clen);
598  }
599  else
600  {
601  Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
602  octave_idx_type *idx_vec = idx.fortran_vec ();
603 
604  for (octave_idx_type i = len - 1; i >= 0; i--)
605  {
606  if (i < len - 1)
607  idxa(i).loop (clen, sub2ind_helper (idx_vec, dvx(i)));
608  else
609  idxa(i).copy_data (idx_vec);
610  }
611 
612  retval = idx_vector (idx);
613  }
614 
615  return retval;
616 }
617 
619 ind2sub (const dim_vector& dv, const idx_vector& idx)
620 {
621  octave_idx_type len = idx.length (0);
622  octave_idx_type n = dv.ndims ();
624  octave_idx_type numel = dv.numel ();
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 
663 int
664 permute_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 }
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:176
bool all_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:363
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:541
bool index_in_bounds(const Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition: Array-util.cc:34
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:5342
bool any_orig_empty(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:320
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
in that an updated permutation matrix is returned Note that if var
Definition: lu.cc:606
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
dim_vector zero_dims_inquire(const Array< idx_vector > &ia, const dim_vector &rhdv)
Definition: Array-util.cc:428
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
for large enough k
Definition: lu.cc:606
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
bool is_vector(const dim_vector &dim)
Definition: Array-util.cc:139
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:530
bool vector_equivalent(const dim_vector &dv)
Definition: Array-util.cc:280
octave_idx_type * ind
Definition: Array-util.cc:525
i e
Definition: data.cc:2724
Array< octave_idx_type > get_ra_idx(octave_idx_type idx, const dim_vector &dims)
Definition: Array-util.cc:394
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:389
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
virtual std::string message(void) const
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:398
void set_var(const std::string &var_arg="")
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:439
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:583
bool any_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:159
idx_vector sub2ind(const dim_vector &dv, const Array< idx_vector > &idxa)
Definition: Array-util.cc:534
virtual const char * err_id(void) const =0
void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension)
Definition: Array-util.cc:59
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
void chop_all_singletons(void)
Definition: dim-vector.cc:53
const T * data(void) const
Definition: Array.h:582
int permute_vector_compare(const void *a, const void *b)
Definition: Array-util.cc:664
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1028
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
dim_vector freeze(Array< idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:260
dim_vector redim(int n) const
Definition: dim-vector.cc:275
bool all_colon_equiv(const Array< idx_vector > &ra_idx, const dim_vector &frozen_lengths)
Definition: Array-util.cc:339
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:238
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:270
bool is_scalar(const dim_vector &dim)
Definition: Array-util.cc:115
Array< idx_vector > ind2sub(const dim_vector &dv, const idx_vector &idx)
Definition: Array-util.cc:619
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:544
bool is_range(void) const
Definition: idx-vector.h:571
T::size_type numel(const T &str)
Definition: oct-string.cc:61
octave_idx_type compute_index(const octave_idx_type *idx) const
Linear index from an index tuple.
Definition: dim-vector.h:475
octave::sys::time start
Definition: graphics.cc:11731
bool all_ok(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:301
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
bool is_scalar(void) const
Definition: idx-vector.h:568
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
b
Definition: cellfun.cc:398
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
sub2ind_helper(octave_idx_type *_ind, octave_idx_type _n)
Definition: Array-util.cc:527
octave_idx_type get_scalar_idx(Array< octave_idx_type > &idx, dim_vector &dims)
Definition: Array-util.cc:80
double floor(double x)
Definition: lo-mappers.cc:330
octave_idx_type pidx
Definition: Array-util.h:111
Array< idx_vector > conv_to_array(const idx_vector *tmp, const octave_idx_type len)
Definition: Array-util.cc:249
octave_idx_type num_ones(const Array< octave_idx_type > &ra_idx)
Definition: Array-util.cc:101
const T * fortran_vec(void) const
Definition: Array.h:584
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
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:854
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:466
dim_vector dv
Definition: sub2ind.cc:263
octave_idx_type n
Definition: Array-util.cc:525
Array< octave_idx_type > get_elt_idx(const Array< idx_vector > &ra_idx, const Array< octave_idx_type > &result_idx)
Definition: Array-util.cc:380
bool is_colon(void) const
Definition: idx-vector.h:565