GNU Octave  4.0.0
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-2015 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 #ifdef 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.length ();
40 
41  if (n == dimensions.length ())
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.length () - 1;
65  int nda = dimensions.length ();
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 {
82  octave_idx_type retval (-1);
83 
84  int n = idx.length ();
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 {
103  octave_idx_type retval = 0;
104 
105  for (octave_idx_type i = 0; i < ra_idx.length (); 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.length ();
120 
121  if (n == 0)
122  {
123  retval = false;
124  }
125  else
126  {
127  for (int i = 0; i < n; i ++)
128  {
129  if (dim (i) != 1)
130  {
131  retval = false;
132 
133  break;
134  }
135  }
136  }
137  return retval;
138 }
139 
140 bool
141 is_vector (const dim_vector& dim)
142 {
143  int m = 0;
144  int n = dim.length ();
145 
146  if (n == 0)
147  m = 2;
148  else
149  {
150  for (int i = 0; i < n; i ++)
151  if (dim (i) > 1)
152  m++;
153  else if (dim(i) < 1)
154  m += 2;
155  }
156 
157  return (m < 2);
158 }
159 
160 bool
162 {
163  bool retval = false;
164 
165  for (octave_idx_type i = 0; i < arr.length (); i++)
166  {
167  if (arr (i) == 1)
168  {
169  retval = true;
170 
171  break;
172  }
173  }
174  return retval;
175 }
176 
179 {
180  if (n < 0)
182  if (n >= dims.numel ())
183  gripe_index_out_of_range (1, 1, n+1, dims.numel ());
184 
185  return n;
186 }
187 
190 {
191  if (i < 0 || j < 0)
193  if (i >= dims(0))
194  gripe_index_out_of_range (2, 1, i+1, dims(0));
195  if (j >= dims.numel (1))
196  gripe_index_out_of_range (2, 2, j+1, dims.numel (1));
197 
198  return j*dims(0) + i;
199 }
200 
203  const dim_vector& dims)
204 {
205  if (i < 0 || j < 0 || k < 0)
207  if (i >= dims(0))
208  gripe_index_out_of_range (3, 1, i+1, dims(0));
209  if (j >= dims(1))
210  gripe_index_out_of_range (3, 2, j+1, dims(1));
211  if (k >= dims.numel (2))
212  gripe_index_out_of_range (3, 3, k+1, dims.numel (2));
213 
214  return (k*dims(1) + j)*dims(0) + i;
215 }
216 
219 {
220  int nd = ra_idx.length ();
221  const dim_vector dv = dims.redim (nd);
222  for (int d = 0; d < nd; d++)
223  {
224  if (ra_idx(d) < 0)
226  if (ra_idx(d) >= dv(d))
227  gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
228  }
229 
230  return dv.compute_index (ra_idx.data ());
231 }
232 
235 {
236  Array<octave_idx_type> retval (a.dims ());
237 
238  for (octave_idx_type i = 0; i < a.length (); i++)
239  retval(i) = a(i).elem (0);
240 
241  return retval;
242 }
243 
245 conv_to_array (const idx_vector *tmp, const octave_idx_type len)
246 {
247  Array<idx_vector> retval (dim_vector (len, 1));
248 
249  for (octave_idx_type i = 0; i < len; i++)
250  retval(i) = tmp[i];
251 
252  return retval;
253 }
254 
256 freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)
257 {
258  dim_vector retval;
259 
260  int n = ra_idx.length ();
261 
262  assert (n == dimensions.length ());
263 
264  retval.resize (n);
265 
266  static const char *tag[3] = { "row", "column", 0 };
267 
268  for (int i = 0; i < n; i++)
269  retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 3],
270  resize_ok);
271 
272  return retval;
273 }
274 
275 bool
277 {
278  int n = dv.length ();
279 
280  bool found_first = false;
281 
282  for (int i = 0; i < n; i++)
283  {
284  if (dv(i) != 1)
285  {
286  if (! found_first)
287  found_first = true;
288  else
289  return false;
290  }
291  }
292 
293  return true;
294 }
295 
296 bool
298 {
299  bool retval = true;
300 
301  octave_idx_type n = ra_idx.length ();
302 
303  for (octave_idx_type i = 0; i < n; i++)
304  {
305  if (! ra_idx(i))
306  {
307  retval = false;
308  break;
309  }
310  }
311 
312  return retval;
313 }
314 
315 bool
317 {
318  bool retval = false;
319 
320  octave_idx_type n = ra_idx.length ();
321 
322  for (octave_idx_type i = 0; i < n; i++)
323  {
324  if (ra_idx(i).orig_empty ())
325  {
326  retval = true;
327  break;
328  }
329  }
330 
331  return retval;
332 }
333 
334 bool
336  const dim_vector& frozen_lengths)
337 {
338  bool retval = true;
339 
340  octave_idx_type idx_n = ra_idx.length ();
341 
342  int n = frozen_lengths.length ();
343 
344  assert (idx_n == n);
345 
346  for (octave_idx_type i = 0; i < n; i++)
347  {
348  if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))
349  {
350  retval = false;
351  break;
352  }
353  }
354 
355  return retval;
356 }
357 
358 bool
360 {
361  bool retval = true;
362 
363  for (octave_idx_type i = 0; i < arr.length (); i++)
364  {
365  if (arr(i) != 1)
366  {
367  retval = false;
368  break;
369  }
370  }
371 
372  return retval;
373 }
374 
377  const Array<octave_idx_type>& result_idx)
378 {
379  octave_idx_type n = ra_idx.length ();
380 
381  Array<octave_idx_type> retval (dim_vector (n, 1));
382 
383  for (octave_idx_type i = 0; i < n; i++)
384  retval(i) = ra_idx(i).elem (result_idx(i));
385 
386  return retval;
387 }
388 
391 {
392  Array<octave_idx_type> retval;
393 
394  int n_dims = dims.length ();
395 
396  retval.resize (dim_vector (n_dims, 1));
397 
398  for (int i = 0; i < n_dims; i++)
399  retval(i) = 0;
400 
401  assert (idx > 0 || idx < dims.numel ());
402 
403  for (octave_idx_type i = 0; i < idx; i++)
404  increment_index (retval, dims);
405 
406  // FIXME: the solution using increment_index is not efficient.
407 
408 #if 0
409  octave_idx_type var = 1;
410  for (int i = 0; i < n_dims; i++)
411  {
412  std::cout << "idx: " << idx << ", var: " << var
413  << ", dims(" << i << "): " << dims(i) <<"\n";
414  retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
415  idx -= var * retval(i);
416  var = dims(i);
417  }
418 #endif
419 
420  return retval;
421 }
422 
425 {
426  int ial = ia.length ();
427  int rhdvl = rhdv.length ();
428  dim_vector rdv = dim_vector::alloc (ial);
429  bool *scalar = new bool [ial];
430  bool *colon = new bool [ial];
431  // Mark scalars and colons, count non-scalar indices.
432  int nonsc = 0;
433  bool all_colons = true;
434  for (int i = 0; i < ial; i++)
435  {
436  // FIXME: should we check for length() instead?
437  scalar[i] = ia(i).is_scalar ();
438  colon[i] = ia(i).is_colon ();
439  if (! scalar[i]) nonsc++;
440  if (! colon[i]) rdv(i) = ia(i).extent (0);
441  all_colons = all_colons && colon[i];
442  }
443 
444  // If the number of nonscalar indices matches the dimensionality of
445  // RHS, we try an exact match, inquiring even singleton dimensions.
446  if (all_colons)
447  {
448  rdv = rhdv;
449  rdv.resize (ial, 1);
450  }
451  else if (nonsc == rhdvl)
452  {
453  for (int i = 0, j = 0; i < ial; i++)
454  {
455  if (scalar[i]) continue;
456  if (colon[i])
457  rdv(i) = rhdv(j);
458  j++;
459  }
460  }
461  else
462  {
463  dim_vector rhdv0 = rhdv;
464  rhdv0.chop_all_singletons ();
465  int rhdv0l = rhdv0.length ();
466  for (int i = 0, j = 0; i < ial; i++)
467  {
468  if (scalar[i]) continue;
469  if (colon[i])
470  rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
471  }
472  }
473 
474  delete [] scalar;
475  delete [] colon;
476 
477  return rdv;
478 }
479 
482  const dim_vector& rhdv)
483 {
484  bool icol = i.is_colon ();
485  bool jcol = j.is_colon ();
486  dim_vector rdv;
487  if (icol && jcol && rhdv.length () == 2)
488  {
489  rdv(0) = rhdv(0);
490  rdv(1) = rhdv(1);
491  }
492  else if (rhdv.length () == 2
493  && ! i.is_scalar () && ! j.is_scalar ())
494  {
495  rdv(0) = icol ? rhdv(0) : i.extent (0);
496  rdv(1) = jcol ? rhdv(1) : j.extent (0);
497  }
498  else
499  {
500  dim_vector rhdv0 = rhdv;
501  rhdv0.chop_all_singletons ();
502  int k = 0;
503  rdv(0) = i.extent (0);
504  if (icol)
505  rdv(0) = rhdv0(k++);
506  else if (! i.is_scalar ())
507  k++;
508  rdv(1) = j.extent (0);
509  if (jcol)
510  rdv(1) = rhdv0(k++);
511  else if (! j.is_scalar ())
512  k++;
513  }
514 
515  return rdv;
516 }
517 
518 // A helper class.
520 {
522 
524  : ind(_ind), n(_n) { }
525 
526  void operator ()(octave_idx_type k) { (*ind++ *= n) += k; }
527 };
528 
530 sub2ind (const dim_vector& dv, const Array<idx_vector>& idxa)
531 {
532  idx_vector retval;
533  octave_idx_type len = idxa.length ();
534 
535  if (len >= 1)
536  {
537  const dim_vector dvx = dv.redim (len);
538  bool all_ranges = true;
539  octave_idx_type clen = -1;
540 
541  for (octave_idx_type i = 0; i < len; i++)
542  {
543  idx_vector idx = idxa(i);
544  octave_idx_type n = dvx(i);
545 
546  all_ranges = all_ranges && idx.is_range ();
547  if (clen < 0)
548  clen = idx.length (n);
549  else if (clen != idx.length (n))
550  current_liboctave_error_handler ("sub2ind: lengths of indices must match");
551 
552  if (idx.extent (n) > n)
553  current_liboctave_error_handler ("sub2ind: index out of range");
554  }
555 
556  if (len == 1)
557  retval = idxa(0);
558  else if (clen == 1)
559  {
560  // All scalars case - the result is a scalar.
561  octave_idx_type idx = idxa(len-1)(0);
562  for (octave_idx_type i = len - 2; i >= 0; i--)
563  idx = idx * dvx(i) + idxa(i)(0);
564  retval = idx_vector (idx);
565  }
566  else if (all_ranges && clen != 0)
567  {
568  // All ranges case - the result is a range.
569  octave_idx_type start = 0;
570  octave_idx_type step = 0;
571  for (octave_idx_type i = len - 1; i >= 0; i--)
572  {
573  octave_idx_type xstart = idxa(i)(0);
574  octave_idx_type xstep = idxa(i)(1) - xstart;
575  start = start * dvx(i) + xstart;
576  step = step * dvx(i) + xstep;
577  }
578  retval = idx_vector::make_range (start, step, clen);
579  }
580  else
581  {
582  Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
583  octave_idx_type *idx_vec = idx.fortran_vec ();
584 
585  for (octave_idx_type i = len - 1; i >= 0; i--)
586  {
587  if (i < len - 1)
588  idxa(i).loop (clen, sub2ind_helper (idx_vec, dvx(i)));
589  else
590  idxa(i).copy_data (idx_vec);
591  }
592 
593  retval = idx_vector (idx);
594  }
595  }
596  else
597  current_liboctave_error_handler ("sub2ind: needs at least 2 indices");
598 
599  return retval;
600 }
601 
603 ind2sub (const dim_vector& dv, const idx_vector& idx)
604 {
605  octave_idx_type len = idx.length (0);
606  octave_idx_type n = dv.length ();
607  Array<idx_vector> retval (dim_vector (n, 1));
608  octave_idx_type numel = dv.numel ();
609 
610  if (idx.extent (numel) > numel)
611  current_liboctave_error_handler ("ind2sub: index out of range");
612  else
613  {
614  if (idx.is_scalar ())
615  {
616  octave_idx_type k = idx(0);
617  for (octave_idx_type j = 0; j < n; j++)
618  {
619  retval(j) = k % dv(j);
620  k /= dv(j);
621  }
622  }
623  else
624  {
626 
627  dim_vector odv = idx.orig_dimensions ();
628  for (octave_idx_type j = 0; j < n; j++)
629  rdata[j] = Array<octave_idx_type> (odv);
630 
631  for (octave_idx_type i = 0; i < len; i++)
632  {
633  octave_idx_type k = idx(i);
634  for (octave_idx_type j = 0; j < n; j++)
635  {
636  rdata[j](i) = k % dv(j);
637  k /= dv(j);
638  }
639  }
640 
641  for (octave_idx_type j = 0; j < n; j++)
642  retval(j) = rdata[j];
643  }
644 
645 
646  }
647 
648  return retval;
649 }
650 
651 int
652 permute_vector_compare (const void *a, const void *b)
653 {
654  const permute_vector *pva = static_cast<const permute_vector *> (a);
655  const permute_vector *pvb = static_cast<const permute_vector *> (b);
656 
657  return pva->pidx > pvb->pidx;
658 }
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:178
bool all_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:359
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:551
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
bool any_orig_empty(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:316
dim_vector zero_dims_inquire(const Array< idx_vector > &ia, const dim_vector &rhdv)
Definition: Array-util.cc:424
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
bool is_vector(const dim_vector &dim)
Definition: Array-util.cc:141
void operator()(octave_idx_type k)
Definition: Array-util.cc:526
T & elem(octave_idx_type n)
Definition: Array.h:380
bool vector_equivalent(const dim_vector &dv)
Definition: Array-util.cc:276
void gripe_invalid_index(void)
octave_idx_type * ind
Definition: Array-util.cc:521
Array< octave_idx_type > get_ra_idx(octave_idx_type idx, const dim_vector &dims)
Definition: Array-util.cc:390
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
F77_RET_T const double const double double * d
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
dim_vector orig_dimensions(void) const
Definition: idx-vector.h:593
liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
bool any_ones(const Array< octave_idx_type > &arr)
Definition: Array-util.cc:161
idx_vector sub2ind(const dim_vector &dv, const Array< idx_vector > &idxa)
Definition: Array-util.cc:530
void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension)
Definition: Array-util.cc:59
static void gripe_index_out_of_range(void)
Definition: idx-vector.cc:51
void chop_all_singletons(void)
Definition: dim-vector.cc:43
const T * data(void) const
Definition: Array.h:479
int permute_vector_compare(const void *a, const void *b)
Definition: Array-util.cc:652
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
dim_vector freeze(Array< idx_vector > &ra_idx, const dim_vector &dimensions, int resize_ok)
Definition: Array-util.cc:256
dim_vector redim(int n) const
Definition: dim-vector.cc:266
bool all_colon_equiv(const Array< idx_vector > &ra_idx, const dim_vector &frozen_lengths)
Definition: Array-util.cc:335
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:234
static dim_vector alloc(int n)
Definition: dim-vector.h:256
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:603
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:554
bool is_range(void) const
Definition: idx-vector.h:581
octave_idx_type compute_index(const octave_idx_type *idx) const
Compute a linear index from an index tuple.
Definition: dim-vector.h:448
bool all_ok(const Array< idx_vector > &ra_idx)
Definition: Array-util.cc:297
bool is_scalar(void) const
Definition: idx-vector.h:578
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
sub2ind_helper(octave_idx_type *_ind, octave_idx_type _n)
Definition: Array-util.cc:523
octave_idx_type get_scalar_idx(Array< octave_idx_type > &idx, dim_vector &dims)
Definition: Array-util.cc:80
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:245
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:282
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:481
int length(void) const
Definition: dim-vector.h:281
static idx_vector make_range(octave_idx_type start, octave_idx_type step, octave_idx_type len)
Definition: idx-vector.h:476
octave_idx_type n
Definition: Array-util.cc:521
Array< octave_idx_type > get_elt_idx(const Array< idx_vector > &ra_idx, const Array< octave_idx_type > &result_idx)
Definition: Array-util.cc:376
bool is_colon(void) const
Definition: idx-vector.h:575
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:736