Array.h

Go to the documentation of this file.
00001 // Template array classes
00002 /*
00003 
00004 Copyright (C) 1993-2012 John W. Eaton
00005 Copyright (C) 2008-2009 Jaroslav Hajek
00006 Copyright (C) 2010 VZLU Prague
00007 
00008 This file is part of Octave.
00009 
00010 Octave is free software; you can redistribute it and/or modify it
00011 under the terms of the GNU General Public License as published by the
00012 Free Software Foundation; either version 3 of the License, or (at your
00013 option) any later version.
00014 
00015 Octave is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018 for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with Octave; see the file COPYING.  If not, see
00022 <http://www.gnu.org/licenses/>.
00023 
00024 */
00025 
00026 #if !defined (octave_Array_h)
00027 #define octave_Array_h 1
00028 
00029 #include <cassert>
00030 #include <cstddef>
00031 
00032 #include <algorithm>
00033 #include <iosfwd>
00034 
00035 #include "dim-vector.h"
00036 #include "idx-vector.h"
00037 #include "lo-traits.h"
00038 #include "lo-utils.h"
00039 #include "oct-sort.h"
00040 #include "quit.h"
00041 #include "oct-mem.h"
00042 #include "oct-refcount.h"
00043 
00044 // One dimensional array class.  Handles the reference counting for
00045 // all the derived classes.
00046 
00047 template <class T>
00048 class
00049 Array
00050 {
00051 protected:
00052 
00053   //--------------------------------------------------------------------
00054   // The real representation of all arrays.
00055   //--------------------------------------------------------------------
00056 
00057   class ArrayRep
00058   {
00059   public:
00060 
00061     T *data;
00062     octave_idx_type len;
00063     octave_refcount<int> count;
00064 
00065     ArrayRep (T *d, octave_idx_type l)
00066       : data (no_ctor_new<T> (l)), len (l), count (1)
00067         {
00068           copy_or_memcpy (l, d, data);
00069         }
00070 
00071     template <class U>
00072     ArrayRep (U *d, octave_idx_type l)
00073       : data (no_ctor_new<T> (l)), len (l), count (1)
00074         {
00075           std::copy (d, d+l, data);
00076         }
00077 
00078     ArrayRep (void) : data (0), len (0), count (1) { }
00079 
00080     explicit ArrayRep (octave_idx_type n) : data (no_ctor_new<T> (n)), len (n), count (1) { }
00081 
00082     explicit ArrayRep (octave_idx_type n, const T& val)
00083       : data (no_ctor_new<T> (n)), len (n), count (1)
00084       {
00085         fill_or_memset (n, val, data);
00086       }
00087 
00088     ArrayRep (const ArrayRep& a)
00089       : data (no_ctor_new<T> (a.len)), len (a.len), count (1)
00090       {
00091         copy_or_memcpy (a.len, a.data, data);
00092       }
00093 
00094     ~ArrayRep (void) { no_ctor_delete<T> (data); }
00095 
00096     octave_idx_type length (void) const { return len; }
00097 
00098   private:
00099 
00100     // No assignment!
00101 
00102     ArrayRep& operator = (const ArrayRep& a);
00103   };
00104 
00105   //--------------------------------------------------------------------
00106 
00107 public:
00108 
00109   void make_unique (void)
00110     {
00111       if (rep->count > 1)
00112         {
00113           ArrayRep *r = new ArrayRep (slice_data, slice_len);
00114 
00115           if (--rep->count == 0)
00116             delete rep;
00117           
00118           rep = r;
00119           slice_data = rep->data;
00120         }
00121     }
00122 
00123   typedef T element_type;
00124 
00125   typedef typename ref_param<T>::type crefT;
00126 
00127   typedef bool (*compare_fcn_type) (typename ref_param<T>::type,
00128                                     typename ref_param<T>::type);
00129 
00130 protected:
00131 
00132   dim_vector dimensions;
00133 
00134   typename Array<T>::ArrayRep *rep;
00135 
00136   // Rationale:
00137   // slice_data is a pointer to rep->data, denoting together with slice_len the
00138   // actual portion of the data referenced by this Array<T> object. This allows
00139   // to make shallow copies not only of a whole array, but also of contiguous
00140   // subranges. Every time rep is directly manipulated, slice_data and slice_len
00141   // need to be properly updated.
00142 
00143   T* slice_data;
00144   octave_idx_type slice_len;
00145 
00146   // slice constructor
00147   Array (const Array<T>& a, const dim_vector& dv,
00148          octave_idx_type l, octave_idx_type u)
00149     : dimensions (dv), rep(a.rep), slice_data (a.slice_data+l), slice_len (u-l)
00150     {
00151       rep->count++;
00152       dimensions.chop_trailing_singletons ();
00153     }
00154 
00155 private:
00156 
00157   typename Array<T>::ArrayRep *nil_rep (void) const
00158     {
00159       // NR was originally allocated with new, but that does not seem
00160       // to be necessary since it will never be deleted.  So just use
00161       // a static object instead.
00162 
00163       static typename Array<T>::ArrayRep nr;
00164       return &nr;
00165     }
00166 
00167 public:
00168 
00169   // Empty ctor (0x0).
00170 
00171   Array (void)
00172     : dimensions (), rep (nil_rep ()), slice_data (rep->data),
00173       slice_len (rep->len)
00174     {
00175       rep->count++;
00176     }
00177 
00178   // Obsolete 1D ctor (there are no 1D arrays).
00179   explicit Array (octave_idx_type n) GCC_ATTR_DEPRECATED
00180     : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
00181       slice_data (rep->data), slice_len (rep->len)
00182     { }
00183 
00184   // Obsolete initialized 1D ctor (there are no 1D arrays).
00185   explicit Array (octave_idx_type n, const T& val) GCC_ATTR_DEPRECATED
00186     : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
00187       slice_data (rep->data), slice_len (rep->len)
00188     {
00189       fill (val);
00190     }
00191 
00192   // nD uninitialized ctor.
00193   explicit Array (const dim_vector& dv)
00194     : dimensions (dv),
00195       rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
00196       slice_data (rep->data), slice_len (rep->len)
00197     {
00198       dimensions.chop_trailing_singletons ();
00199     }
00200 
00201   // nD initialized ctor.
00202   explicit Array (const dim_vector& dv, const T& val)
00203     : dimensions (dv),
00204       rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
00205       slice_data (rep->data), slice_len (rep->len)
00206     {
00207       fill (val);
00208       dimensions.chop_trailing_singletons ();
00209     }
00210 
00211   // Reshape constructor.
00212   Array (const Array<T>& a, const dim_vector& dv);
00213 
00214   // Type conversion case.
00215   template <class U>
00216   Array (const Array<U>& a)
00217     : dimensions (a.dims ()),
00218       rep (new typename Array<T>::ArrayRep (a.data (), a.length ())),
00219       slice_data (rep->data), slice_len (rep->len)
00220     { }
00221 
00222   // No type conversion case.
00223   Array (const Array<T>& a)
00224     : dimensions (a.dimensions), rep (a.rep), slice_data (a.slice_data),
00225       slice_len (a.slice_len)
00226     {
00227       rep->count++;
00228     }
00229 
00230 public:
00231 
00232   ~Array (void)
00233     {
00234       if (--rep->count == 0)
00235         delete rep;
00236     }
00237 
00238   Array<T>& operator = (const Array<T>& a)
00239     {
00240       if (this != &a)
00241         {
00242           if (--rep->count == 0)
00243             delete rep;
00244 
00245           rep = a.rep;
00246           rep->count++;
00247 
00248           dimensions = a.dimensions;
00249           slice_data = a.slice_data;
00250           slice_len = a.slice_len;
00251         }
00252 
00253       return *this;
00254     }
00255 
00256   void fill (const T& val);
00257 
00258   void clear (void);
00259   void clear (const dim_vector& dv);
00260 
00261   void clear (octave_idx_type r, octave_idx_type c)
00262     { clear (dim_vector (r, c)); }
00263 
00264   octave_idx_type capacity (void) const { return slice_len; }
00265   octave_idx_type length (void) const { return capacity (); }
00266   octave_idx_type nelem (void) const { return capacity (); }
00267   octave_idx_type numel (void) const { return nelem (); }
00268 
00269   octave_idx_type dim1 (void) const { return dimensions(0); }
00270   octave_idx_type dim2 (void) const { return dimensions(1); }
00271   octave_idx_type dim3 (void) const { return dimensions(2); }
00272 
00273   // Return the array as a column vector.
00274   Array<T> as_column (void) const
00275     {
00276       Array<T> retval (*this);
00277       if (dimensions.length () != 2 || dimensions(1) != 1)
00278         retval.dimensions = dim_vector (numel (), 1);
00279 
00280       return retval;
00281     }
00282 
00283   // Return the array as a row vector.
00284   Array<T> as_row (void) const
00285     {
00286       Array<T> retval (*this);
00287       if (dimensions.length () != 2 || dimensions(0) != 1)
00288         retval.dimensions = dim_vector (1, numel ());
00289 
00290       return retval;
00291     }
00292 
00293   // Return the array as a matrix.
00294   Array<T> as_matrix (void) const
00295     {
00296       Array<T> retval (*this);
00297       if (dimensions.length () != 2)
00298         retval.dimensions = dimensions.redim (2);
00299 
00300       return retval;
00301     }
00302 
00303   octave_idx_type rows (void) const { return dim1 (); }
00304   octave_idx_type cols (void) const { return dim2 (); }
00305   octave_idx_type columns (void) const { return dim2 (); }
00306   octave_idx_type pages (void) const { return dim3 (); }
00307 
00308   size_t byte_size (void) const { return static_cast<size_t> (numel ()) * sizeof (T); }
00309 
00310   // Return a const-reference so that dims ()(i) works efficiently.
00311   const dim_vector& dims (void) const { return dimensions; }
00312 
00313   Array<T> squeeze (void) const;
00314 
00315   void chop_trailing_singletons (void) GCC_ATTR_DEPRECATED
00316   { dimensions.chop_trailing_singletons (); }
00317 
00318   octave_idx_type compute_index (octave_idx_type i, octave_idx_type j) const;
00319   octave_idx_type compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;
00320   octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const;
00321 
00322   octave_idx_type compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const
00323     { return dimensions.compute_index (ra_idx.data (), ra_idx.length ()); }
00324 
00325   // No checking, even for multiple references, ever.
00326 
00327   T& xelem (octave_idx_type n) { return slice_data [n]; }
00328   crefT xelem (octave_idx_type n) const { return slice_data [n]; }
00329 
00330   T& xelem (octave_idx_type i, octave_idx_type j) { return xelem (dim1()*j+i); }
00331   crefT xelem (octave_idx_type i, octave_idx_type j) const { return xelem (dim1()*j+i); }
00332 
00333   T& xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)
00334     { return xelem (i, dim2()*k+j); }
00335   crefT xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const
00336     { return xelem (i, dim2()*k+j); }
00337 
00338   T& xelem (const Array<octave_idx_type>& ra_idx)
00339     { return xelem (compute_index_unchecked (ra_idx)); }
00340 
00341   crefT xelem (const Array<octave_idx_type>& ra_idx) const
00342     { return xelem (compute_index_unchecked (ra_idx)); }
00343 
00344   // FIXME -- would be nice to fix this so that we don't
00345   // unnecessarily force a copy, but that is not so easy, and I see no
00346   // clean way to do it.
00347 
00348   T& checkelem (octave_idx_type n);
00349   T& checkelem (octave_idx_type i, octave_idx_type j);
00350   T& checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k);
00351   T& checkelem (const Array<octave_idx_type>& ra_idx);
00352 
00353   T& elem (octave_idx_type n)
00354     {
00355       make_unique ();
00356       return xelem (n);
00357     }
00358 
00359   T& elem (octave_idx_type i, octave_idx_type j) { return elem (dim1()*j+i); }
00360 
00361   T& elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, dim2()*k+j); }
00362 
00363   T& elem (const Array<octave_idx_type>& ra_idx)
00364     { return Array<T>::elem (compute_index_unchecked (ra_idx)); }
00365 
00366 #if defined (BOUNDS_CHECKING)
00367   T& operator () (octave_idx_type n) { return checkelem (n); }
00368   T& operator () (octave_idx_type i, octave_idx_type j) { return checkelem (i, j); }
00369   T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return checkelem (i, j, k); }
00370   T& operator () (const Array<octave_idx_type>& ra_idx) { return checkelem (ra_idx); }
00371 #else
00372   T& operator () (octave_idx_type n) { return elem (n); }
00373   T& operator () (octave_idx_type i, octave_idx_type j) { return elem (i, j); }
00374   T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, j, k); }
00375   T& operator () (const Array<octave_idx_type>& ra_idx) { return elem (ra_idx); }
00376 #endif
00377 
00378   crefT checkelem (octave_idx_type n) const;
00379   crefT checkelem (octave_idx_type i, octave_idx_type j) const;
00380   crefT checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;
00381   crefT checkelem (const Array<octave_idx_type>& ra_idx) const;
00382 
00383   crefT elem (octave_idx_type n) const { return xelem (n); }
00384 
00385   crefT elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); }
00386 
00387   crefT elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return xelem (i, j, k); }
00388 
00389   crefT elem (const Array<octave_idx_type>& ra_idx) const
00390     { return Array<T>::xelem (compute_index_unchecked (ra_idx)); }
00391 
00392 #if defined (BOUNDS_CHECKING)
00393   crefT operator () (octave_idx_type n) const { return checkelem (n); }
00394   crefT operator () (octave_idx_type i, octave_idx_type j) const { return checkelem (i, j); }
00395   crefT operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return checkelem (i, j, k); }
00396   crefT operator () (const Array<octave_idx_type>& ra_idx) const { return checkelem (ra_idx); }
00397 #else
00398   crefT operator () (octave_idx_type n) const { return elem (n); }
00399   crefT operator () (octave_idx_type i, octave_idx_type j) const { return elem (i, j); }
00400   crefT operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return elem (i, j, k); }
00401   crefT operator () (const Array<octave_idx_type>& ra_idx) const { return elem (ra_idx); }
00402 #endif
00403 
00404   // Fast extractors. All of these produce shallow copies.
00405   // Warning: none of these do check bounds, unless BOUNDS_CHECKING is on!
00406 
00407   // Extract column: A(:,k+1).
00408   Array<T> column (octave_idx_type k) const;
00409   // Extract page: A(:,:,k+1).
00410   Array<T> page (octave_idx_type k) const;
00411 
00412   // Extract a slice from this array as a column vector: A(:)(lo+1:up).
00413   // Must be 0 <= lo && up <= numel. May be up < lo.
00414   Array<T> linear_slice (octave_idx_type lo, octave_idx_type up) const;
00415 
00416   Array<T> reshape (octave_idx_type nr, octave_idx_type nc) const
00417     { return Array<T> (*this, dim_vector (nr, nc)); }
00418 
00419   Array<T> reshape (const dim_vector& new_dims) const
00420     { return Array<T> (*this, new_dims); }
00421 
00422   Array<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
00423   Array<T> ipermute (const Array<octave_idx_type>& vec) const
00424     { return permute (vec, true); }
00425 
00426   bool is_square (void) const { return (dim1 () == dim2 ()); }
00427 
00428   bool is_empty (void) const { return numel () == 0; }
00429 
00430   bool is_vector (void) const { return dimensions.is_vector (); }
00431 
00432   Array<T> transpose (void) const;
00433   Array<T> hermitian (T (*fcn) (const T&) = 0) const;
00434 
00435   const T *data (void) const { return slice_data; }
00436 
00437   const T *fortran_vec (void) const { return data (); }
00438 
00439   T *fortran_vec (void);
00440 
00441   bool is_shared (void) { return rep->count > 1; }
00442 
00443   int ndims (void) const { return dimensions.length (); }
00444 
00445   // Indexing without resizing.
00446 
00447   Array<T> index (const idx_vector& i) const;
00448 
00449   Array<T> index (const idx_vector& i, const idx_vector& j) const;
00450 
00451   Array<T> index (const Array<idx_vector>& ia) const;
00452 
00453   static const T& resize_fill_value ();
00454 
00455   // Resizing (with fill).
00456 
00457   void resize1 (octave_idx_type n, const T& rfv = resize_fill_value ());
00458 
00459   void resize (octave_idx_type n) GCC_ATTR_DEPRECATED
00460     { resize1 (n); }
00461 
00462   void resize (octave_idx_type nr, octave_idx_type nc,
00463                const T& rfv = resize_fill_value ()) GCC_ATTR_DEPRECATED
00464   {
00465     resize2 (nr, nc, rfv);
00466   }
00467 
00468   void resize (const dim_vector& dv, const T& rfv = resize_fill_value ());
00469 
00470   // Indexing with possible resizing and fill
00471   // FIXME -- this is really a corner case, that should better be
00472   // handled directly in liboctinterp.
00473 
00474   Array<T> index (const idx_vector& i, bool resize_ok,
00475                   const T& rfv = resize_fill_value ()) const;
00476 
00477   Array<T> index (const idx_vector& i, const idx_vector& j,
00478                   bool resize_ok, const T& rfv = resize_fill_value ()) const;
00479 
00480   Array<T> index (const Array<idx_vector>& ia,
00481                   bool resize_ok, const T& rfv = resize_fill_value ()) const;
00482 
00483   // Indexed assignment (always with resize & fill).
00484 
00485   void assign (const idx_vector& i, const Array<T>& rhs,
00486                const T& rfv = resize_fill_value ());
00487 
00488   void assign (const idx_vector& i, const idx_vector& j, const Array<T>& rhs,
00489                const T& rfv = resize_fill_value ());
00490 
00491   void assign (const Array<idx_vector>& ia, const Array<T>& rhs,
00492                const T& rfv = resize_fill_value ());
00493 
00494   // Deleting elements.
00495 
00496   // A(I) = [] (with a single subscript)
00497   void delete_elements (const idx_vector& i);
00498 
00499   // A(:,...,I,...,:) = [] (>= 2 subscripts, one of them is non-colon)
00500   void delete_elements (int dim, const idx_vector& i);
00501 
00502   // Dispatcher to the above two.
00503   void delete_elements (const Array<idx_vector>& ia);
00504 
00505   // Insert an array into another at a specified position.
00506   // If size (a) is [d1 d2 ... dN] and idx is [i1 i2 ... iN],
00507   // this method is equivalent to
00508   // x(i1:i1+d1-1, i2:i2+d2-1, ... , iN:iN+dN-1) = a.
00509   Array<T>& insert (const Array<T>& a, const Array<octave_idx_type>& idx);
00510 
00511   // This is just a special case for idx = [r c 0 ...]
00512   Array<T>& insert (const Array<T>& a, octave_idx_type r, octave_idx_type c);
00513 
00514   void maybe_economize (void)
00515     {
00516       if (rep->count == 1 && slice_len != rep->len)
00517         {
00518           ArrayRep *new_rep = new ArrayRep (slice_data, slice_len);
00519           delete rep;
00520           rep = new_rep;
00521           slice_data = rep->data;
00522         }
00523     }
00524 
00525   void print_info (std::ostream& os, const std::string& prefix) const;
00526 
00527   // Unsafe.  This function exists to support the MEX interface.
00528   // You should not use it anywhere else.
00529   void *mex_get_data (void) const { return const_cast<T *> (data ()); }
00530 
00531   Array<T> sort (int dim = 0, sortmode mode = ASCENDING) const;
00532   Array<T> sort (Array<octave_idx_type> &sidx, int dim = 0,
00533                  sortmode mode = ASCENDING) const;
00534 
00535   // Ordering is auto-detected or can be specified.
00536   sortmode is_sorted (sortmode mode = UNSORTED) const;
00537 
00538   // Sort by rows returns only indices.
00539   Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;
00540 
00541   // Ordering is auto-detected or can be specified.
00542   sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
00543 
00544   // Do a binary lookup in a sorted array. Must not contain NaNs.
00545   // Mode can be specified or is auto-detected by comparing 1st and last element.
00546   octave_idx_type lookup (const T& value, sortmode mode = UNSORTED) const;
00547 
00548   // Ditto, but for an array of values, specializing on the case when values
00549   // are sorted. NaNs get the value N.
00550   Array<octave_idx_type> lookup (const Array<T>& values, sortmode mode = UNSORTED) const;
00551 
00552   // Count nonzero elements.
00553   octave_idx_type nnz (void) const;
00554 
00555   // Find indices of (at most n) nonzero elements. If n is specified, backward
00556   // specifies search from backward.
00557   Array<octave_idx_type> find (octave_idx_type n = -1, bool backward = false) const;
00558 
00559   // Returns the n-th element in increasing order, using the same ordering as
00560   // used for sort. n can either be a scalar index or a contiguous range.
00561   Array<T> nth_element (const idx_vector& n, int dim = 0) const;
00562 
00563   Array<T> diag (octave_idx_type k = 0) const;
00564 
00565   // Concatenation along a specified (0-based) dimension, equivalent to cat().
00566   // dim = -1 corresponds to dim = 0 and dim = -2 corresponds to dim = 1,
00567   // but apply the looser matching rules of vertcat/horzcat.
00568   static Array<T>
00569   cat (int dim, octave_idx_type n, const Array<T> *array_list);
00570 
00571   template <class U, class F>
00572   Array<U>
00573   map (F fcn) const
00574   {
00575     octave_idx_type len = length ();
00576 
00577     const T *m = data ();
00578 
00579     Array<U> result (dims ());
00580     U *p = result.fortran_vec ();
00581 
00582     octave_idx_type i;
00583     for (i = 0; i < len - 3; i += 4)
00584       {
00585         octave_quit ();
00586 
00587         p[i] = fcn (m[i]);
00588         p[i+1] = fcn (m[i+1]);
00589         p[i+2] = fcn (m[i+2]);
00590         p[i+3] = fcn (m[i+3]);
00591       }
00592 
00593     octave_quit ();
00594 
00595     for (; i < len; i++)
00596       p[i] = fcn (m[i]);
00597 
00598     return result;
00599   }
00600 
00601   // Overloads for function references.
00602   template <class U>
00603   Array<U>
00604   map (U (&fcn) (T)) const
00605   { return map<U, U (&) (T)> (fcn); }
00606 
00607   template <class U>
00608   Array<U>
00609   map (U (&fcn) (const T&)) const
00610   { return map<U, U (&) (const T&)> (fcn); }
00611 
00612   // Generic any/all test functionality with arbitrary predicate.
00613   template <class F, bool zero>
00614   bool test (F fcn) const
00615   {
00616     octave_idx_type len = length ();
00617 
00618     const T *m = data ();
00619 
00620     octave_idx_type i;
00621     for (i = 0; i < len - 3; i += 4)
00622       {
00623         octave_quit ();
00624 
00625         if (fcn (m[i]) != zero
00626             || fcn (m[i+1]) != zero
00627             || fcn (m[i+2]) != zero
00628             || fcn (m[i+3]) != zero)
00629            return ! zero;
00630 
00631       }
00632 
00633     octave_quit ();
00634 
00635     for (; i < len; i++)
00636        if (fcn (m[i]) != zero)
00637           return ! zero;
00638 
00639     return zero;
00640   }
00641 
00642   // Simpler calls.
00643   template <class F>
00644   bool test_any (F fcn) const
00645   { return test<F, false> (fcn); }
00646 
00647   template <class F>
00648   bool test_all (F fcn) const
00649   { return test<F, true> (fcn); }
00650 
00651   // Overloads for function references.
00652   bool test_any (bool (&fcn) (T)) const
00653   { return test<bool (&) (T), false> (fcn); }
00654 
00655   bool test_any (bool (&fcn) (const T&)) const
00656   { return test<bool (&) (const T&), false> (fcn); }
00657 
00658   bool test_all (bool (&fcn) (T)) const
00659   { return test<bool (&) (T), true> (fcn); }
00660 
00661   bool test_all (bool (&fcn) (const T&)) const
00662   { return test<bool (&) (const T&), true> (fcn); }
00663 
00664   template <class U> friend class Array;
00665 
00666   // Returns true if this->dims () == dv, and if so, replaces this->dimensions
00667   // by a shallow copy of dv. This is useful for maintaining several arrays with
00668   // supposedly equal dimensions (e.g. structs in the interpreter).
00669   bool optimize_dimensions (const dim_vector& dv);
00670 
00671 private:
00672 
00673   void resize2 (octave_idx_type nr, octave_idx_type nc,
00674                 const T& rfv = resize_fill_value ());
00675 
00676   static void instantiation_guard ();
00677 };
00678 
00679 // This is a simple wrapper template that will subclass an Array<T> type or any
00680 // later type derived from it and override the default non-const operator() to
00681 // not check for the array's uniqueness. It is, however, the user's
00682 // responsibility to ensure the array is actually unaliased whenever elements
00683 // are accessed.
00684 
00685 template<class ArrayClass>
00686 class NoAlias : public ArrayClass
00687 {
00688   typedef typename ArrayClass::element_type T;
00689 public:
00690   NoAlias () : ArrayClass () { }
00691 
00692   // FIXME: this would be simpler once C++0x is available
00693   template <class X>
00694     explicit NoAlias (X x) : ArrayClass (x) { }
00695 
00696   template <class X, class Y>
00697     explicit NoAlias (X x, Y y) : ArrayClass (x, y) { }
00698 
00699   template <class X, class Y, class Z>
00700     explicit NoAlias (X x, Y y, Z z) : ArrayClass (x, y, z) { }
00701 
00702   T& operator () (octave_idx_type n)
00703     { return ArrayClass::xelem (n); }
00704   T& operator () (octave_idx_type i, octave_idx_type j)
00705     { return ArrayClass::xelem (i, j); }
00706   T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k)
00707     { return ArrayClass::xelem (i, j, k); }
00708   T& operator () (const Array<octave_idx_type>& ra_idx)
00709     { return ArrayClass::xelem (ra_idx); }
00710 };
00711 
00712 template <class T>
00713 std::ostream&
00714 operator << (std::ostream& os, const Array<T>& a);
00715 
00716 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines