GNU Octave  3.8.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-2013 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 
218 compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims)
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
297 all_ok (const Array<idx_vector>& ra_idx)
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 (), rhdvl = rhdv.length ();
427  dim_vector rdv = dim_vector::alloc (ial);
428  bool *scalar = new bool [ial], *colon = new bool [ial];
429  // Mark scalars and colons, count non-scalar indices.
430  int nonsc = 0;
431  bool all_colons = true;
432  for (int i = 0; i < ial; i++)
433  {
434  // FIXME: should we check for length() instead?
435  scalar[i] = ia(i).is_scalar ();
436  colon[i] = ia(i).is_colon ();
437  if (! scalar[i]) nonsc++;
438  if (! colon[i]) rdv(i) = ia(i).extent (0);
439  all_colons = all_colons && colon[i];
440  }
441 
442  // If the number of nonscalar indices matches the dimensionality of
443  // RHS, we try an exact match, inquiring even singleton dimensions.
444  if (all_colons)
445  {
446  rdv = rhdv;
447  rdv.resize (ial, 1);
448  }
449  else if (nonsc == rhdvl)
450  {
451  for (int i = 0, j = 0; i < ial; i++)
452  {
453  if (scalar[i]) continue;
454  if (colon[i])
455  rdv(i) = rhdv(j);
456  j++;
457  }
458  }
459  else
460  {
461  dim_vector rhdv0 = rhdv;
462  rhdv0.chop_all_singletons ();
463  int rhdv0l = rhdv0.length ();
464  for (int i = 0, j = 0; i < ial; i++)
465  {
466  if (scalar[i]) continue;
467  if (colon[i])
468  rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
469  }
470  }
471 
472  delete [] scalar;
473  delete [] colon;
474 
475  return rdv;
476 }
477 
480  const dim_vector& rhdv)
481 {
482  bool icol = i.is_colon (), jcol = j.is_colon ();
483  dim_vector rdv;
484  if (icol && jcol && rhdv.length () == 2)
485  {
486  rdv(0) = rhdv(0);
487  rdv(1) = rhdv(1);
488  }
489  else if (rhdv.length () == 2
490  && ! i.is_scalar () && ! j.is_scalar ())
491  {
492  rdv(0) = icol ? rhdv(0) : i.extent (0);
493  rdv(1) = jcol ? rhdv(1) : j.extent (0);
494  }
495  else
496  {
497  dim_vector rhdv0 = rhdv;
498  rhdv0.chop_all_singletons ();
499  int k = 0;
500  rdv(0) = i.extent (0);
501  if (icol)
502  rdv(0) = rhdv0(k++);
503  else if (! i.is_scalar ())
504  k++;
505  rdv(1) = j.extent (0);
506  if (jcol)
507  rdv(1) = rhdv0(k++);
508  else if (! j.is_scalar ())
509  k++;
510  }
511 
512  return rdv;
513 }
514 
515 // A helper class.
517 {
519 
521  : ind(_ind), n(_n) { }
522 
523  void operator ()(octave_idx_type k) { (*ind++ *= n) += k; }
524 };
525 
527 sub2ind (const dim_vector& dv, const Array<idx_vector>& idxa)
528 {
529  idx_vector retval;
530  octave_idx_type len = idxa.length ();
531 
532  if (len >= 1)
533  {
534  const dim_vector dvx = dv.redim (len);
535  bool all_ranges = true;
536  octave_idx_type clen = -1;
537 
538  for (octave_idx_type i = 0; i < len; i++)
539  {
540  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 ("sub2ind: lengths of indices must match");
548 
549  if (idx.extent (n) > n)
550  current_liboctave_error_handler ("sub2ind: index out of range");
551  }
552 
553  if (len == 1)
554  retval = idxa(0);
555  else if (clen == 1)
556  {
557  // All scalars case - the result is a scalar.
558  octave_idx_type idx = idxa(len-1)(0);
559  for (octave_idx_type i = len - 2; i >= 0; i--)
560  idx = idx * dvx(i) + idxa(i)(0);
561  retval = idx_vector (idx);
562  }
563  else if (all_ranges && clen != 0)
564  {
565  // All ranges case - the result is a range.
566  octave_idx_type start = 0, step = 0;
567  for (octave_idx_type i = len - 1; i >= 0; i--)
568  {
569  octave_idx_type xstart = idxa(i)(0), xstep = idxa(i)(1) - xstart;
570  start = start * dvx(i) + xstart;
571  step = step * dvx(i) + xstep;
572  }
573  retval = idx_vector::make_range (start, step, clen);
574  }
575  else
576  {
577  Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
578  octave_idx_type *idx_vec = idx.fortran_vec ();
579 
580  for (octave_idx_type i = len - 1; i >= 0; i--)
581  {
582  if (i < len - 1)
583  idxa(i).loop (clen, sub2ind_helper (idx_vec, dvx(i)));
584  else
585  idxa(i).copy_data (idx_vec);
586  }
587 
588  retval = idx_vector (idx);
589  }
590  }
591  else
592  current_liboctave_error_handler ("sub2ind: needs at least 2 indices");
593 
594  return retval;
595 }
596 
598 ind2sub (const dim_vector& dv, const idx_vector& idx)
599 {
600  octave_idx_type len = idx.length (0), n = dv.length ();
601  Array<idx_vector> retval (dim_vector (n, 1));
602  octave_idx_type numel = dv.numel ();
603 
604  if (idx.extent (numel) > numel)
605  current_liboctave_error_handler ("ind2sub: index out of range");
606  else
607  {
608  if (idx.is_scalar ())
609  {
610  octave_idx_type k = idx(0);
611  for (octave_idx_type j = 0; j < n; j++)
612  {
613  retval(j) = k % dv(j);
614  k /= dv(j);
615  }
616  }
617  else
618  {
620 
621  dim_vector odv = idx.orig_dimensions ();
622  for (octave_idx_type j = 0; j < n; j++)
623  rdata[j] = Array<octave_idx_type> (odv);
624 
625  for (octave_idx_type i = 0; i < len; i++)
626  {
627  octave_idx_type k = idx(i);
628  for (octave_idx_type j = 0; j < n; j++)
629  {
630  rdata[j](i) = k % dv(j);
631  k /= dv(j);
632  }
633  }
634 
635  for (octave_idx_type j = 0; j < n; j++)
636  retval(j) = rdata[j];
637  }
638 
639 
640  }
641 
642  return retval;
643 }
644 
645 int
646 permute_vector_compare (const void *a, const void *b)
647 {
648  const permute_vector *pva = static_cast<const permute_vector *> (a);
649  const permute_vector *pvb = static_cast<const permute_vector *> (b);
650 
651  return pva->pidx > pvb->pidx;
652 }