GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Array.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2018 John W. Eaton
4 Copyright (C) 2008-2009 Jaroslav Hajek
5 Copyright (C) 2010 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #if ! defined (octave_Array_h)
26 #define octave_Array_h 1
27 
28 #include "octave-config.h"
29 
30 #include <cassert>
31 #include <cstddef>
32 
33 #include <algorithm>
34 #include <iosfwd>
35 #include <string>
36 
37 #include "dim-vector.h"
38 #include "idx-vector.h"
39 #include "lo-error.h"
40 #include "lo-traits.h"
41 #include "lo-utils.h"
42 #include "oct-refcount.h"
43 #include "oct-sort.h"
44 #include "quit.h"
45 
46 //! N Dimensional Array with copy-on-write semantics.
47 //!
48 //! The Array class is at the root of Octave. It provides a container
49 //! with an arbitrary number of dimensions. The operator () provides
50 //! access to individual elements via subscript and linear indexing.
51 //! Indexing starts at 0. Arrays are column-major order as in Fortran.
52 //!
53 //! @code{.cc}
54 //! // 3 D Array with 10 rows, 20 columns, and 5 pages, filled with 7.0
55 //! Array<double> A Array<double (dim_vector (10, 20, 5), 7.0);
56 //!
57 //! // set value for row 0, column 10, and page 3
58 //! A(0, 10, 3) = 2.5;
59 //!
60 //! // get value for row 1, column 2, and page 0
61 //! double v = A(1, 2, 0);
62 //!
63 //! // get value for 25th element (row 4, column 3, page 1)
64 //! double v = A(24);
65 //! @endcode
66 //!
67 //! ## Notes on STL compatibility
68 //!
69 //! ### size() and length()
70 //!
71 //! To access the total number of elements in an Array, use numel()
72 //! which is short for number of elements and is equivalent to the
73 //! Octave function with same name.
74 //!
75 //! @code{.cc}
76 //! Array<int> A (dim_vector (10, 20, 4), 1);
77 //!
78 //! octave_idx_type n = A.numel (); // returns 800 (10x20x4)
79 //!
80 //! octave_idx_type nr = A.size (0); // returns 10 (number of rows/dimension 0)
81 //! octave_idx_type nc = A.size (1); // returns 20 (number of columns)
82 //! octave_idx_type nc = A.size (2); // returns 4 (size of dimension 3)
83 //! octave_idx_type l6 = A.size (6); // returns 1 (implicit singleton dimension)
84 //!
85 //! // Alternatively, get a dim_vector which represents the dimensions.
86 //! dim_vector dims = A.dims ();
87 //! @endcode
88 //!
89 //! The methods size() and length() as they exist in the STL cause
90 //! confusion in the context of a N dimensional array.
91 //!
92 //! The size() of an array is the length of all dimensions. In Octave,
93 //! the size() function returns a row vector with the length of each
94 //! dimension, or the size of a specific dimension. Only the latter is
95 //! present in liboctave.
96 //!
97 //! Since there is more than 1 dimension, length() would not make sense
98 //! without expliciting which dimension. If the function existed, which
99 //! length should it return? Octave length() function returns the length
100 //! of the longest dimension which is an odd definition, only useful for
101 //! vectors and square matrices. The alternatives numel(), rows(),
102 //! columns(), and size(d) are more explict and recommended.
103 //!
104 //! ### size_type
105 //!
106 //! Array::size_type is `octave_idx_type` which is a typedef for `int`
107 //! or `long int`, depending whether Octave was configured for 64-bit
108 //! indexing.
109 //!
110 //! This is a signed integer which may cause problems when mixed with
111 //! STL containers. The reason is that Octave interacts with Fortran
112 //! routines, providing an interface many Fortran numeric libraries.
113 //!
114 //! ## Subclasses
115 //!
116 //! The following subclasses specializations, will be of most use:
117 //! - Matrix: Array<double> with only 2 dimensions
118 //! - ComplexMatrix: Array<std::complex<double>> with only 2 dimensions
119 //! - boolNDArray: N dimensional Array<bool>
120 //! - ColumnVector: Array<double> with 1 column
121 //! - string_vector: Array<std::string> with 1 column
122 //! - Cell: Array<octave_value>, equivalent to an Octave cell.
123 
124 template <typename T>
125 class
126 Array
127 {
128 protected:
129 
130  //! The real representation of all arrays.
131  class ArrayRep
132  {
133  public:
134 
135  T *data;
138 
140  : data (new T [l]), len (l), count (1)
141  {
142  std::copy_n (d, l, data);
143  }
144 
145  template <typename U>
147  : data (new T [l]), len (l), count (1)
148  {
149  std::copy_n (d, l, data);
150  }
151 
152  // Use new instead of setting data to 0 so that fortran_vec and
153  // data always return valid addresses, even for zero-size arrays.
154 
155  ArrayRep (void) : data (new T [0]), len (0), count (1) { }
156 
158  : data (new T [n]), len (n), count (1) { }
159 
160  explicit ArrayRep (octave_idx_type n, const T& val)
161  : data (new T [n]), len (n), count (1)
162  {
163  std::fill_n (data, n, val);
164  }
165 
166  ArrayRep (const ArrayRep& a)
167  : data (new T [a.len]), len (a.len), count (1)
168  {
169  std::copy_n (a.data, a.len, data);
170  }
171 
172  ~ArrayRep (void) { delete [] data; }
173 
174  octave_idx_type numel (void) const { return len; }
175 
176  private:
177 
178  // No assignment!
179 
180  ArrayRep& operator = (const ArrayRep& a);
181  };
182 
183  //--------------------------------------------------------------------
184 
185 public:
186 
187  void make_unique (void)
188  {
189  if (rep->count > 1)
190  {
191  ArrayRep *r = new ArrayRep (slice_data, slice_len);
192 
193  if (--rep->count == 0)
194  delete rep;
195 
196  rep = r;
197  slice_data = rep->data;
198  }
199  }
200 
201  typedef T element_type;
202 
203  typedef T value_type;
204 
205  //! Used for operator(), and returned by numel() and size()
206  //! (beware: signed integer)
208 
209  typedef typename ref_param<T>::type crefT;
210 
211  typedef bool (*compare_fcn_type) (typename ref_param<T>::type,
212  typename ref_param<T>::type);
213 
214 protected:
215 
217 
219 
220  // Rationale:
221  // slice_data is a pointer to rep->data, denoting together with slice_len the
222  // actual portion of the data referenced by this Array<T> object. This
223  // allows to make shallow copies not only of a whole array, but also of
224  // contiguous subranges. Every time rep is directly manipulated, slice_data
225  // and slice_len need to be properly updated.
226 
229 
230  //! slice constructor
231  Array (const Array<T>& a, const dim_vector& dv,
233  : dimensions (dv), rep(a.rep), slice_data (a.slice_data+l), slice_len (u-l)
234  {
235  rep->count++;
236  dimensions.chop_trailing_singletons ();
237  }
238 
239 private:
240 
241  static typename Array<T>::ArrayRep *nil_rep (void);
242 
243 protected:
244 
245  //! For jit support
246  Array (T *sdata, octave_idx_type slen, octave_idx_type *adims, void *arep)
247  : dimensions (adims),
248  rep (reinterpret_cast<typename Array<T>::ArrayRep *> (arep)),
249  slice_data (sdata), slice_len (slen) { }
250 
251 public:
252 
253  //! Empty ctor (0 by 0).
254  Array (void)
255  : dimensions (), rep (nil_rep ()), slice_data (rep->data),
256  slice_len (rep->len)
257  {
258  rep->count++;
259  }
260 
261  //! nD uninitialized ctor.
262  explicit Array (const dim_vector& dv)
263  : dimensions (dv),
264  rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
265  slice_data (rep->data), slice_len (rep->len)
266  {
267  dimensions.chop_trailing_singletons ();
268  }
269 
270  //! nD initialized ctor.
271  explicit Array (const dim_vector& dv, const T& val)
272  : dimensions (dv),
273  rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
274  slice_data (rep->data), slice_len (rep->len)
275  {
276  fill (val);
277  dimensions.chop_trailing_singletons ();
278  }
279 
280  //! Reshape constructor.
281  Array (const Array<T>& a, const dim_vector& dv);
282 
283  //! Constructor from standard library sequence containers.
284  template<template <typename...> class Container>
285  Array (const Container<T>& a, const dim_vector& dv);
286 
287  //! Type conversion case.
288  template <typename U>
289  Array (const Array<U>& a)
290  : dimensions (a.dims ()),
291  rep (new typename Array<T>::ArrayRep (a.data (), a.numel ())),
292  slice_data (rep->data), slice_len (rep->len)
293  { }
294 
295  //! No type conversion case.
296  Array (const Array<T>& a)
297  : dimensions (a.dimensions), rep (a.rep), slice_data (a.slice_data),
298  slice_len (a.slice_len)
299  {
300  rep->count++;
301  }
302 
303 public:
304 
305  virtual ~Array (void)
306  {
307  if (--rep->count == 0)
308  delete rep;
309  }
310 
311  Array<T>& operator = (const Array<T>& a)
312  {
313  if (this != &a)
314  {
315  if (--rep->count == 0)
316  delete rep;
317 
318  rep = a.rep;
319  rep->count++;
320 
321  dimensions = a.dimensions;
322  slice_data = a.slice_data;
323  slice_len = a.slice_len;
324  }
325 
326  return *this;
327  }
328 
329  void fill (const T& val);
330 
331  void clear (void);
332  void clear (const dim_vector& dv);
333 
335  { clear (dim_vector (r, c)); }
336 
337  // Number of elements in the array. These are all synonyms.
338  //@{
339  //! Number of elements in the array.
340  //! Synonymous with numel().
341  //! @note This method is deprecated in favour of numel().
342  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
343  octave_idx_type capacity (void) const { return numel (); }
344 
345  //! Number of elements in the array.
346  //!
347  //! Synonymous with numel().
348  //! @note This method is deprecated in favour of numel().
349  //!
350  //! @note
351  //! This is @em not the same as @c %length() at the Octave interpreter.
352  //! At the Octave interpreter, the function @c %length() returns the
353  //! length of the greatest dimension. This method returns the total
354  //! number of elements.
355 
356  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
357  octave_idx_type length (void) const { return numel (); }
358 
359  //! Number of elements in the array.
360  //! Synonymous with numel().
361  //! @note This method is deprecated in favour of numel().
362  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
363  octave_idx_type nelem (void) const { return numel (); }
364 
365  //! Number of elements in the array.
366  octave_idx_type numel (void) const { return slice_len; }
367  //@}
368 
369  //! Return the array as a column vector.
370  Array<T> as_column (void) const
371  {
372  Array<T> retval (*this);
373  if (dimensions.ndims () != 2 || dimensions(1) != 1)
374  retval.dimensions = dim_vector (numel (), 1);
375 
376  return retval;
377  }
378 
379  //! Return the array as a row vector.
380  Array<T> as_row (void) const
381  {
382  Array<T> retval (*this);
383  if (dimensions.ndims () != 2 || dimensions(0) != 1)
384  retval.dimensions = dim_vector (1, numel ());
385 
386  return retval;
387  }
388 
389  //! Return the array as a matrix.
390  Array<T> as_matrix (void) const
391  {
392  Array<T> retval (*this);
393  if (dimensions.ndims () != 2)
394  retval.dimensions = dimensions.redim (2);
395 
396  return retval;
397  }
398 
399  //! @name First dimension
400  //!
401  //! Get the first dimension of the array (number of rows)
402  //@{
403  octave_idx_type dim1 (void) const { return dimensions(0); }
404  octave_idx_type rows (void) const { return dim1 (); }
405  //@}
406 
407  //! @name Second dimension
408  //!
409  //! Get the second dimension of the array (number of columns)
410  //@{
411  octave_idx_type dim2 (void) const { return dimensions(1); }
412  octave_idx_type cols (void) const { return dim2 (); }
413  octave_idx_type columns (void) const { return dim2 (); }
414  //@}
415 
416  //! @name Third dimension
417  //!
418  //! Get the third dimension of the array (number of pages)
419  //@{
420  octave_idx_type dim3 (void) const { return dimensions(2); }
421  octave_idx_type pages (void) const { return dim3 (); }
422  //@}
423 
424  //! Size of the specified dimension.
425  //!
426  //! Dimensions beyond the Array number of dimensions return 1 as
427  //! those are implicit singleton dimensions.
428  //!
429  //! Equivalent to Octave's `size (A, DIM)`
430 
431  size_type size (const size_type d) const
432  {
433  // Should we throw for negative values?
434  // Should >= ndims () be handled by dim_vector operator() instead ?
435  return d >= ndims () ? 1 : dimensions(d);
436  }
437 
438  size_t byte_size (void) const
439  { return static_cast<size_t> (numel ()) * sizeof (T); }
440 
441  //! Return a const-reference so that dims ()(i) works efficiently.
442  const dim_vector& dims (void) const { return dimensions; }
443 
444  //! Chop off leading singleton dimensions
445  Array<T> squeeze (void) const;
446 
449  octave_idx_type k) const;
451 
453  const
454  { return dimensions.compute_index (ra_idx.data (), ra_idx.numel ()); }
455 
456  // No checking, even for multiple references, ever.
457 
458  T& xelem (octave_idx_type n) { return slice_data[n]; }
459  crefT xelem (octave_idx_type n) const { return slice_data[n]; }
460 
462  { return xelem (dim1 ()*j+i); }
464  { return xelem (dim1 ()*j+i); }
465 
467  { return xelem (i, dim2 ()*k+j); }
469  { return xelem (i, dim2 ()*k+j); }
470 
472  { return xelem (compute_index_unchecked (ra_idx)); }
473 
475  { return xelem (compute_index_unchecked (ra_idx)); }
476 
477  // FIXME: would be nice to fix this so that we don't unnecessarily force
478  // a copy, but that is not so easy, and I see no clean way to do it.
479 
480  T& checkelem (octave_idx_type n);
481 
482  T& checkelem (octave_idx_type i, octave_idx_type j);
483 
485 
486  T& checkelem (const Array<octave_idx_type>& ra_idx);
487 
489  {
490  make_unique ();
491  return xelem (n);
492  }
493 
494  T& elem (octave_idx_type i, octave_idx_type j) { return elem (dim1 ()*j+i); }
495 
497  { return elem (i, dim2 ()*k+j); }
498 
500  { return Array<T>::elem (compute_index_unchecked (ra_idx)); }
501 
502  T& operator () (octave_idx_type n) { return elem (n); }
503  T& operator () (octave_idx_type i, octave_idx_type j) { return elem (i, j); }
505  { return elem (i, j, k); }
506  T& operator () (const Array<octave_idx_type>& ra_idx)
507  { return elem (ra_idx); }
508 
509  crefT checkelem (octave_idx_type n) const;
510 
511  crefT checkelem (octave_idx_type i, octave_idx_type j) const;
512 
513  crefT checkelem (octave_idx_type i, octave_idx_type j,
514  octave_idx_type k) const;
515 
516  crefT checkelem (const Array<octave_idx_type>& ra_idx) const;
517 
518  crefT elem (octave_idx_type n) const { return xelem (n); }
519 
521  { return xelem (i, j); }
522 
524  { return xelem (i, j, k); }
525 
527  { return Array<T>::xelem (compute_index_unchecked (ra_idx)); }
528 
529  crefT operator () (octave_idx_type n) const { return elem (n); }
530  crefT operator () (octave_idx_type i, octave_idx_type j) const
531  { return elem (i, j); }
533  octave_idx_type k) const
534  { return elem (i, j, k); }
535  crefT operator () (const Array<octave_idx_type>& ra_idx) const
536  { return elem (ra_idx); }
537 
538  // Fast extractors. All of these produce shallow copies.
539 
540  //! Extract column: A(:,k+1).
542  //! Extract page: A(:,:,k+1).
543  Array<T> page (octave_idx_type k) const;
544 
545  //! Extract a slice from this array as a column vector: A(:)(lo+1:up).
546  //! Must be 0 <= lo && up <= numel. May be up < lo.
547  Array<T> linear_slice (octave_idx_type lo, octave_idx_type up) const;
548 
550  { return Array<T> (*this, dim_vector (nr, nc)); }
551 
552  Array<T> reshape (const dim_vector& new_dims) const
553  { return Array<T> (*this, new_dims); }
554 
555  Array<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
557  { return permute (vec, true); }
558 
559  bool issquare (void) const { return (dim1 () == dim2 ()); }
560 
561  OCTAVE_DEPRECATED (4.4, "use 'issquare' instead")
562  bool is_square (void) const
563  { return issquare (); }
564 
565  bool isempty (void) const { return numel () == 0; }
566 
567  OCTAVE_DEPRECATED (4.4, "use 'isempty' instead")
568  bool is_empty (void) const
569  { return isempty (); }
570 
571  bool isvector (void) const { return dimensions.isvector (); }
572 
573  OCTAVE_DEPRECATED (4.4, "use 'isvector' instead")
574  bool is_vector (void) const
575  { return isvector (); }
576 
577  bool is_nd_vector (void) const { return dimensions.is_nd_vector (); }
578 
579  Array<T> transpose (void) const;
580  Array<T> hermitian (T (*fcn) (const T&) = nullptr) const;
581 
582  const T * data (void) const { return slice_data; }
583 
584  const T * fortran_vec (void) const { return data (); }
585 
586  T * fortran_vec (void);
587 
588  bool is_shared (void) { return rep->count > 1; }
589 
590  int ndims (void) const { return dimensions.ndims (); }
591 
592  //@{
593  //! Indexing without resizing.
594  Array<T> index (const idx_vector& i) const;
595 
596  Array<T> index (const idx_vector& i, const idx_vector& j) const;
597 
598  Array<T> index (const Array<idx_vector>& ia) const;
599  //@}
600 
601  virtual T resize_fill_value (void) const;
602 
603  //@{
604  //! Resizing (with fill).
605  void resize2 (octave_idx_type nr, octave_idx_type nc, const T& rfv);
607  {
608  resize2 (nr, nc, resize_fill_value ());
609  }
610 
611  void resize1 (octave_idx_type n, const T& rfv);
612  void resize1 (octave_idx_type n) { resize1 (n, resize_fill_value ()); }
613 
614  void resize (const dim_vector& dv, const T& rfv);
615  void resize (const dim_vector& dv) { resize (dv, resize_fill_value ()); }
616  //@}
617 
618  //@{
619  //! Indexing with possible resizing and fill
620 
621  // FIXME: this is really a corner case, that should better be
622  // handled directly in liboctinterp.
623 
624  Array<T> index (const idx_vector& i, bool resize_ok, const T& rfv) const;
625  Array<T> index (const idx_vector& i, bool resize_ok) const
626  {
627  return index (i, resize_ok, resize_fill_value ());
628  }
629 
630  Array<T> index (const idx_vector& i, const idx_vector& j, bool resize_ok,
631  const T& rfv) const;
632  Array<T> index (const idx_vector& i, const idx_vector& j,
633  bool resize_ok) const
634  {
635  return index (i, j, resize_ok, resize_fill_value ());
636  }
637 
638  Array<T> index (const Array<idx_vector>& ia, bool resize_ok,
639  const T& rfv) const;
640  Array<T> index (const Array<idx_vector>& ia, bool resize_ok) const
641  {
642  return index (ia, resize_ok, resize_fill_value ());
643  }
644  //@}
645 
646  //@{
647  //! Indexed assignment (always with resize & fill).
648  void assign (const idx_vector& i, const Array<T>& rhs, const T& rfv);
649  void assign (const idx_vector& i, const Array<T>& rhs)
650  {
651  assign (i, rhs, resize_fill_value ());
652  }
653 
654  void assign (const idx_vector& i, const idx_vector& j, const Array<T>& rhs,
655  const T& rfv);
656  void assign (const idx_vector& i, const idx_vector& j, const Array<T>& rhs)
657  {
658  assign (i, j, rhs, resize_fill_value ());
659  }
660 
661  void assign (const Array<idx_vector>& ia, const Array<T>& rhs, const T& rfv);
662  void assign (const Array<idx_vector>& ia, const Array<T>& rhs)
663  {
664  assign (ia, rhs, resize_fill_value ());
665  }
666  //@}
667 
668  //@{
669  //! Deleting elements.
670 
671  //! A(I) = [] (with a single subscript)
672  void delete_elements (const idx_vector& i);
673 
674  //! A(:,...,I,...,:) = [] (>= 2 subscripts, one of them is non-colon)
675  void delete_elements (int dim, const idx_vector& i);
676 
677  //! Dispatcher to the above two.
678  void delete_elements (const Array<idx_vector>& ia);
679  //@}
680 
681  //! Insert an array into another at a specified position. If
682  //! size (a) is [d1 d2 ... dN] and idx is [i1 i2 ... iN], this
683  //! method is equivalent to x(i1:i1+d1-1, i2:i2+d2-1, ... ,
684  //! iN:iN+dN-1) = a.
685  Array<T>& insert (const Array<T>& a, const Array<octave_idx_type>& idx);
686 
687  //! This is just a special case for idx = [r c 0 ...]
688  Array<T>& insert (const Array<T>& a, octave_idx_type r, octave_idx_type c);
689 
690  void maybe_economize (void)
691  {
692  if (rep->count == 1 && slice_len != rep->len)
693  {
694  ArrayRep *new_rep = new ArrayRep (slice_data, slice_len);
695  delete rep;
696  rep = new_rep;
697  slice_data = rep->data;
698  }
699  }
700 
701  void print_info (std::ostream& os, const std::string& prefix) const;
702 
703  //! Give a pointer to the data in mex format. Unsafe. This function
704  //! exists to support the MEX interface. You should not use it
705  //! anywhere else.
706  void * mex_get_data (void) const { return const_cast<T *> (data ()); }
707 
708  Array<T> sort (int dim = 0, sortmode mode = ASCENDING) const;
709  Array<T> sort (Array<octave_idx_type> &sidx, int dim = 0,
710  sortmode mode = ASCENDING) const;
711 
712  //! Ordering is auto-detected or can be specified.
713  sortmode issorted (sortmode mode = UNSORTED) const;
714 
715  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
716  sortmode is_sorted (sortmode mode = UNSORTED) const
717  { return issorted (mode); }
718 
719  //! Sort by rows returns only indices.
720  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;
721 
722  //! Ordering is auto-detected or can be specified.
723  sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
724 
725  //! Do a binary lookup in a sorted array. Must not contain NaNs.
726  //! Mode can be specified or is auto-detected by comparing 1st and last element.
727  octave_idx_type lookup (const T& value, sortmode mode = UNSORTED) const;
728 
729  //! Ditto, but for an array of values, specializing on the case when values
730  //! are sorted. NaNs get the value N.
732  sortmode mode = UNSORTED) const;
733 
734  //! Count nonzero elements.
735  octave_idx_type nnz (void) const;
736 
737  //! Find indices of (at most n) nonzero elements. If n is specified,
738  //! backward specifies search from backward.
740  bool backward = false) const;
741 
742  //! Returns the n-th element in increasing order, using the same
743  //! ordering as used for sort. n can either be a scalar index or a
744  //! contiguous range.
745  Array<T> nth_element (const idx_vector& n, int dim = 0) const;
746 
747  //! Get the kth super or subdiagonal. The zeroth diagonal is the
748  //! ordinary diagonal.
749  Array<T> diag (octave_idx_type k = 0) const;
750 
751  Array<T> diag (octave_idx_type m, octave_idx_type n) const;
752 
753  //! Concatenation along a specified (0-based) dimension, equivalent
754  //! to cat(). dim = -1 corresponds to dim = 0 and dim = -2
755  //! corresponds to dim = 1, but apply the looser matching rules of
756  //! vertcat/horzcat.
757  static Array<T>
758  cat (int dim, octave_idx_type n, const Array<T> *array_list);
759 
760  //! Apply function fcn to each element of the Array<T>. This function
761  //! is optimized with a manually unrolled loop.
762  template <typename U, typename F>
763  Array<U>
764  map (F fcn) const
765  {
766  octave_idx_type len = numel ();
767 
768  const T *m = data ();
769 
770  Array<U> result (dims ());
771  U *p = result.fortran_vec ();
772 
774  for (i = 0; i < len - 3; i += 4)
775  {
776  octave_quit ();
777 
778  p[i] = fcn (m[i]);
779  p[i+1] = fcn (m[i+1]);
780  p[i+2] = fcn (m[i+2]);
781  p[i+3] = fcn (m[i+3]);
782  }
783 
784  octave_quit ();
785 
786  for (; i < len; i++)
787  p[i] = fcn (m[i]);
788 
789  return result;
790  }
791 
792  //@{
793  //! Overloads for function references.
794  template <typename U>
795  Array<U>
796  map (U (&fcn) (T)) const
797  { return map<U, U (&) (T)> (fcn); }
798 
799  template <typename U>
800  Array<U>
801  map (U (&fcn) (const T&)) const
802  { return map<U, U (&) (const T&)> (fcn); }
803  //@}
804 
805  //! Generic any/all test functionality with arbitrary predicate.
806  template <typename F, bool zero>
807  bool test (F fcn) const
808  {
809  return any_all_test<F, T, zero> (fcn, data (), numel ());
810  }
811 
812  //@{
813  //! Simpler calls.
814  template <typename F>
815  bool test_any (F fcn) const
816  { return test<F, false> (fcn); }
817 
818  template <typename F>
819  bool test_all (F fcn) const
820  { return test<F, true> (fcn); }
821  //@}
822 
823  //@{
824  //! Overloads for function references.
825  bool test_any (bool (&fcn) (T)) const
826  { return test<bool (&) (T), false> (fcn); }
827 
828  bool test_any (bool (&fcn) (const T&)) const
829  { return test<bool (&) (const T&), false> (fcn); }
830 
831  bool test_all (bool (&fcn) (T)) const
832  { return test<bool (&) (T), true> (fcn); }
833 
834  bool test_all (bool (&fcn) (const T&)) const
835  { return test<bool (&) (const T&), true> (fcn); }
836  //@}
837 
838  template <typename U> friend class Array;
839 
840  //! Returns true if this->dims () == dv, and if so, replaces this->dimensions
841  //! by a shallow copy of dv. This is useful for maintaining several arrays
842  //! with supposedly equal dimensions (e.g. structs in the interpreter).
843  bool optimize_dimensions (const dim_vector& dv);
844 
845  //@{
846  //! WARNING: Only call these functions from jit
847 
848  int * jit_ref_count (void) { return rep->count.get (); }
849 
850  T * jit_slice_data (void) const { return slice_data; }
851 
852  octave_idx_type * jit_dimensions (void) const { return dimensions.to_jit (); }
853 
854  void * jit_array_rep (void) const { return rep; }
855  //@}
856 
857 private:
858  static void instantiation_guard ();
859 };
860 
861 // We use a variadic template for template template parameter so that
862 // we don't have to specify all the template parameters and limit this
863 // to Container<T>. http://stackoverflow.com/a/20499809/1609556
864 template<typename T>
865 template<template <typename...> class Container>
866 Array<T>::Array (const Container<T>& a, const dim_vector& dv)
867  : dimensions (dv), rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
868  slice_data (rep->data), slice_len (rep->len)
869 {
870  if (dimensions.safe_numel () != octave_idx_type (a.size ()))
871  {
872  std::string new_dims_str = dimensions.str ();
873 
874  (*current_liboctave_error_handler)
875  ("reshape: can't reshape %i elements into %s array",
876  a.size (), new_dims_str.c_str ());
877  }
878 
879  octave_idx_type i = 0;
880  for (const T& x : a)
881  slice_data[i++] = x;
882 
884 }
885 
886 //! This is a simple wrapper template that will subclass an Array<T>
887 //! type or any later type derived from it and override the default
888 //! non-const operator() to not check for the array's uniqueness. It
889 //! is, however, the user's responsibility to ensure the array is
890 //! actually unaliased whenever elements are accessed.
891 template <typename ArrayClass>
892 class NoAlias : public ArrayClass
893 {
894  typedef typename ArrayClass::element_type T;
895 public:
896  NoAlias () : ArrayClass () { }
897 
898  // FIXME: this would be simpler once C++0x is available
899  template <typename X>
900  explicit NoAlias (X x) : ArrayClass (x) { }
901 
902  template <typename X, typename Y>
903  explicit NoAlias (X x, Y y) : ArrayClass (x, y) { }
904 
905  template <typename X, typename Y, typename Z>
906  explicit NoAlias (X x, Y y, Z z) : ArrayClass (x, y, z) { }
907 
909  { return ArrayClass::xelem (n); }
911  { return ArrayClass::xelem (i, j); }
913  { return ArrayClass::xelem (i, j, k); }
915  { return ArrayClass::xelem (ra_idx); }
916 };
917 
918 template <typename T>
919 std::ostream&
920 operator << (std::ostream& os, const Array<T>& a);
921 
922 #endif
dim_vector dimensions
Definition: Array.h:216
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:175
T & elem(octave_idx_type i, octave_idx_type j, octave_idx_type k)
Definition: Array.h:496
octave_idx_type rows(void) const
Definition: Array.h:404
std::string str(char sep='x') const
Definition: dim-vector.cc:73
octave_idx_type pages(void) const
Definition: Array.h:421
bool test_any(F fcn) const
Simpler calls.
Definition: Array.h:815
Array(T *sdata, octave_idx_type slen, octave_idx_type *adims, void *arep)
For jit support.
Definition: Array.h:246
octave_idx_type compute_index(const octave_idx_type *idx) const
Linear index from an index tuple.
Definition: dim-vector.h:487
OCTAVE_EXPORT octave_value_list column
Definition: sparse.cc:123
Array< T > reshape(const dim_vector &new_dims) const
Definition: Array.h:552
octave_idx_type dim3(void) const
Definition: Array.h:420
Array(void)
Empty ctor (0 by 0).
Definition: Array.h:254
ref_param< T >::type crefT
Definition: Array.h:209
octave_idx_type dim1(void) const
Definition: Array.h:403
const octave_base_value const Array< octave_idx_type > & ra_idx
void resize(const dim_vector &dv)
Resizing (with fill).
Definition: Array.h:615
NoAlias(X x, Y y, Z z)
Definition: Array.h:906
const T * data(void) const
Definition: Array.h:582
octave_idx_type len
Definition: Array.h:136
NoAlias()
Definition: Array.h:896
void assign(const Array< idx_vector > &ia, const Array< T > &rhs)
Indexed assignment (always with resize & fill).
Definition: Array.h:662
bool isempty(void) const
Definition: Array.h:565
sortmode
Definition: oct-sort.h:105
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
ArrayRep(octave_idx_type n, const T &val)
Definition: Array.h:160
octave_idx_type safe_numel(void) const
The following function will throw a std::bad_alloc () exception if the requested size is larger than ...
Definition: dim-vector.cc:103
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6348
bool isvector(void) const
Definition: Array.h:571
T & operator()(octave_idx_type n)
Definition: Array.h:908
ArrayRep(U *d, octave_idx_type l)
Definition: Array.h:146
octave_idx_type * jit_dimensions(void) const
WARNING: Only call these functions from jit.
Definition: Array.h:852
for large enough k
Definition: lu.cc:617
OCTAVE_EXPORT octave_value_list page
Definition: sub2ind.cc:107
const T * fortran_vec(void) const
Definition: Array.h:584
Array(const Array< T > &a, const dim_vector &dv, octave_idx_type l, octave_idx_type u)
slice constructor
Definition: Array.h:231
static void transpose(octave_idx_type N, const octave_idx_type *ridx, const octave_idx_type *cidx, octave_idx_type *ridx2, octave_idx_type *cidx2)
Definition: symrcm.cc:386
virtual ~Array(void)
Definition: Array.h:305
Array(const Array< T > &a)
No type conversion case.
Definition: Array.h:296
cat(2, A, B) esult
Definition: data.cc:2278
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:442
Array< T > ipermute(const Array< octave_idx_type > &vec) const
Definition: Array.h:556
Array(const dim_vector &dv, const T &val)
nD initialized ctor.
Definition: Array.h:271
bool test_any(bool(&fcn)(T)) const
Overloads for function references.
Definition: Array.h:825
octave_idx_type columns(void) const
Definition: Array.h:413
T & elem(octave_idx_type n)
Definition: Array.h:488
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
F77_RET_T const F77_INT const F77_INT const F77_INT F77_DBLE const F77_INT F77_DBLE const F77_INT F77_DBLE const F77_INT F77_DBLE * Z
u
Definition: lu.cc:138
T & xelem(octave_idx_type i, octave_idx_type j, octave_idx_type k)
Definition: Array.h:466
void * mex_get_data(void) const
Give a pointer to the data in mex format.
Definition: Array.h:706
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
The real representation of all arrays.
Definition: Array.h:131
virtual octave_idx_type numel(const octave_value_list &)
Definition: ov-base.cc:193
Array< T > as_matrix(void) const
Return the array as a matrix.
Definition: Array.h:390
Array(const dim_vector &dv)
nD uninitialized ctor.
Definition: Array.h:262
ArrayRep(const ArrayRep &a)
Definition: Array.h:166
Array< U > map(U(&fcn)(const T &)) const
Overloads for function references.
Definition: Array.h:801
Array< T > index(const idx_vector &i, const idx_vector &j, bool resize_ok) const
Indexing with possible resizing and fill.
Definition: Array.h:632
octave_function * fcn
Definition: ov-class.cc:1754
void clear(octave_idx_type r, octave_idx_type c)
Definition: Array.h:334
octave_idx_type numel(void) const
Definition: Array.h:174
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
Array< U > map(U(&fcn)(T)) const
Overloads for function references.
Definition: Array.h:796
octave_idx_type cols(void) const
Definition: Array.h:412
cell array If invoked with two or more scalar integer or a vector of integer values
Definition: ov-cell.cc:1241
Array< T > reshape(octave_idx_type nr, octave_idx_type nc) const
Definition: Array.h:549
bool optimize_dimensions(const dim_vector &dv)
Returns true if this->dims () == dv, and if so, replaces this->dimensions by a shallow copy of dv...
Definition: Array.cc:2751
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
static void instantiation_guard()
Definition: Array.cc:2761
void resize1(octave_idx_type n)
Resizing (with fill).
Definition: Array.h:612
int * jit_ref_count(void)
WARNING: Only call these functions from jit.
Definition: Array.h:848
bool issquare(void) const
Definition: Array.h:559
Array< T > as_column(void) const
Return the array as a column vector.
Definition: Array.h:370
octave_idx_type * to_jit(void) const
Definition: dim-vector.h:242
void assign(const idx_vector &i, const Array< T > &rhs)
Indexed assignment (always with resize & fill).
Definition: Array.h:649
count_type * get(void)
Definition: oct-refcount.h:114
void make_unique(void)
Definition: Array.h:187
T & xelem(const Array< octave_idx_type > &ra_idx)
Definition: Array.h:471
Array< T > index(const idx_vector &i, bool resize_ok) const
Indexing with possible resizing and fill.
Definition: Array.h:625
octave_idx_type compute_index_unchecked(const Array< octave_idx_type > &ra_idx) const
Definition: Array.h:452
crefT elem(octave_idx_type i, octave_idx_type j) const
Definition: Array.h:520
T & xelem(octave_idx_type i, octave_idx_type j)
Definition: Array.h:461
octave_idx_type dim2(void) const
Definition: Array.h:411
ArrayClass::element_type T
Definition: Array.h:894
ArrayRep(T *d, octave_idx_type l)
Definition: Array.h:139
static int elem
Definition: __contourc__.cc:47
ArrayRep(void)
Definition: Array.h:155
T value_type
Definition: Array.h:203
bool test_any(bool(&fcn)(const T &)) const
Overloads for function references.
Definition: Array.h:828
octave_value retval
Definition: data.cc:6246
size_type size(const size_type d) const
Size of the specified dimension.
Definition: Array.h:431
T * jit_slice_data(void) const
WARNING: Only call these functions from jit.
Definition: Array.h:850
octave_idx_type slice_len
Definition: Array.h:228
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
NoAlias(X x, Y y)
Definition: Array.h:903
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:233
With real return the complex result
Definition: data.cc:3260
if_then_else< is_class_type< T >::no, T, T const & >::result type
Definition: lo-traits.h:118
bool isvector(const dim_vector &dim)
Definition: Array-util.cc:138
crefT xelem(const Array< octave_idx_type > &ra_idx) const
Definition: Array.h:474
T & elem(octave_idx_type i, octave_idx_type j)
Definition: Array.h:494
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
Definition: colamd.cc:103
T & xelem(octave_idx_type n)
Definition: Array.h:458
bool test_all(F fcn) const
Simpler calls.
Definition: Array.h:819
Array< T > as_row(void) const
Return the array as a row vector.
Definition: Array.h:380
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:125
bool is_nd_vector(void) const
Definition: Array.h:577
T * slice_data
Definition: Array.h:227
T::size_type numel(const T &str)
Definition: oct-string.cc:61
This is a simple wrapper template that will subclass an Array<T> type or any later type derived from ...
Definition: Array.h:892
bool is_shared(void)
Definition: Array.h:588
bool test_all(bool(&fcn)(T)) const
Overloads for function references.
Definition: Array.h:831
crefT elem(const Array< octave_idx_type > &ra_idx) const
Definition: Array.h:526
Array< U > map(F fcn) const
Apply function fcn to each element of the Array<T>.
Definition: Array.h:764
T element_type
Definition: Array.h:201
crefT elem(octave_idx_type n) const
Definition: Array.h:518
crefT xelem(octave_idx_type i, octave_idx_type j, octave_idx_type k) const
Definition: Array.h:468
octave_idx_type size_type
Used for operator(), and returned by numel() and size() (beware: signed integer)
Definition: Array.h:207
p
Definition: lu.cc:138
bool test(F fcn) const
Generic any/all test functionality with arbitrary predicate.
Definition: Array.h:807
~ArrayRep(void)
Definition: Array.h:172
Array(const Array< U > &a)
Type conversion case.
Definition: Array.h:289
octave::refcount< int > count
Definition: Array.h:137
bool isvector(void) const
Definition: dim-vector.h:422
the element is set to zero In other the statement xample y
Definition: data.cc:5264
void assign(const idx_vector &i, const idx_vector &j, const Array< T > &rhs)
Indexed assignment (always with resize & fill).
Definition: Array.h:656
for i
Definition: data.cc:5264
T & elem(const Array< octave_idx_type > &ra_idx)
Definition: Array.h:499
void resize2(octave_idx_type nr, octave_idx_type nc)
Resizing (with fill).
Definition: Array.h:606
bool test_all(bool(&fcn)(const T &)) const
Overloads for function references.
Definition: Array.h:834
crefT elem(octave_idx_type i, octave_idx_type j, octave_idx_type k) const
Definition: Array.h:523
void maybe_economize(void)
Definition: Array.h:690
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
crefT xelem(octave_idx_type i, octave_idx_type j) const
Definition: Array.h:463
Array< T > index(const Array< idx_vector > &ia, bool resize_ok) const
Indexing with possible resizing and fill.
Definition: Array.h:640
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
crefT xelem(octave_idx_type n) const
Definition: Array.h:459
void * jit_array_rep(void) const
WARNING: Only call these functions from jit.
Definition: Array.h:854
ArrayRep(octave_idx_type n)
Definition: Array.h:157
bool is_nd_vector(void) const
Definition: dim-vector.h:431
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
size_t byte_size(void) const
Definition: Array.h:438
void chop_trailing_singletons(void)
Definition: dim-vector.h:226
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
nd group nd example For each display the value
Definition: sysdep.cc:866
dim_vector dv
Definition: sub2ind.cc:263
octave::stream os
Definition: file-io.cc:627
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 * x
NoAlias(X x)
Definition: Array.h:900
Array< T >::ArrayRep * rep
Definition: Array.h:218
int ndims(void) const
Definition: Array.h:590
void F(const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:756