メインページ   クラス階層   構成   ファイル一覧   構成メンバ   ファイルメンバ  

Array.h

解説を見る。
00001 // Template array classes
00002 /*
00003 
00004 Copyright (C) 1996, 1997 John W. Eaton
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 2, or (at your option) any
00011 later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, write to the Free
00020 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021 
00022 */
00023 
00024 #if !defined (octave_Array_h)
00025 #define octave_Array_h 1
00026 
00027 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
00028 #pragma interface
00029 #endif
00030 
00031 #include <cassert>
00032 #include <cstddef>
00033 
00034 #include <iostream>
00035 
00036 #include "dim-vector.h"
00037 #include "lo-utils.h"
00038 
00039 class idx_vector;
00040 
00041 // One dimensional array class.  Handles the reference counting for
00042 // all the derived classes.
00043 
00044 template <class T>
00045 T
00046 resize_fill_value (const T& x)
00047 {
00048   return x;
00049 }
00050 
00051 template <class T>
00052 class
00053 Array
00054 {
00055 protected:
00056 
00057   //--------------------------------------------------------------------
00058   // The real representation of all arrays.
00059   //--------------------------------------------------------------------
00060 
00061   class ArrayRep
00062   {
00063   public:
00064 
00065     T *data;
00066     int len;
00067     int count;
00068 
00069     ArrayRep (T *d, int l) : data (d), len (l), count (1) { }
00070 
00071     ArrayRep (void) : data (0), len (0), count (1) { }
00072 
00073     explicit ArrayRep (int n) : data (new T [n]), len (n), count (1) { }
00074 
00075     explicit ArrayRep (int n, const T& val)
00076       : data (new T [n]), len (n), count (1)
00077       {
00078         fill (val);
00079       }
00080 
00081     ArrayRep (const ArrayRep& a)
00082       : data (new T [a.len]), len (a.len), count (1)
00083       {
00084         for (int i = 0; i < len; i++)
00085           data[i] = a.data[i];
00086       }
00087  
00088     ~ArrayRep (void) { delete [] data; }
00089 
00090     int length (void) const { return len; }
00091 
00092     void fill (const T& val)
00093       {
00094         for (int i = 0; i < len; i++)
00095           data[i] = val;
00096       }
00097 
00098     T& elem (int n) { return data[n]; }
00099 
00100     T elem (int n) const { return data[n]; }
00101 
00102     void qsort (int (*compare) (const void *, const void *))
00103       {
00104         octave_qsort (data, static_cast<size_t> (len), sizeof (T), compare);
00105       }
00106 
00107   private:
00108 
00109     // No assignment!
00110 
00111     ArrayRep& operator = (const ArrayRep& a);
00112   };
00113 
00114   //--------------------------------------------------------------------
00115 
00116   void make_unique (void)
00117     {
00118       if (rep->count > 1)
00119         {
00120           --rep->count;
00121           rep = new ArrayRep (*rep);
00122         }
00123     }
00124 
00125   void make_unique (const T& val)
00126     {
00127       if (rep->count > 1)
00128         {
00129           --rep->count;
00130           rep = new ArrayRep (rep->length (), val);
00131         }
00132       else
00133         rep->fill (val);
00134     }
00135 
00136 public:
00137 
00138   // !!! WARNING !!! -- these should be protected, not public.  You
00139   // should not access these data members directly!
00140 
00141   typename Array<T>::ArrayRep *rep;
00142 
00143   dim_vector dimensions;
00144 
00145 protected:
00146 
00147   idx_vector *idx;
00148   int idx_count;
00149 
00150   Array (T *d, int n)
00151     : rep (new typename Array<T>::ArrayRep (d, n)), dimensions (n),
00152       idx (0), idx_count (0) { }
00153 
00154   Array (T *d, const dim_vector& dv)
00155     : rep (new typename Array<T>::ArrayRep (d, get_size (dv))),
00156       dimensions (dv), idx (0), idx_count (0) { }
00157 
00158 private:
00159 
00160   typename Array<T>::ArrayRep *nil_rep (void) const
00161     {
00162       static typename Array<T>::ArrayRep *nr
00163         = new typename Array<T>::ArrayRep ();
00164 
00165       return nr;
00166     }
00167 
00168   template <class U>
00169   T *
00170   coerce (const U *a, int len)
00171   {
00172     T *retval = new T [len];
00173 
00174     for (int i = 0; i < len; i++)
00175       retval[i] = T (a[i]);
00176 
00177     return retval;
00178   }
00179 
00180 public:
00181 
00182   Array (void)
00183     : rep (nil_rep ()), dimensions (),
00184       idx (0), idx_count (0) { rep->count++; }
00185 
00186   explicit Array (int n)
00187     : rep (new typename Array<T>::ArrayRep (n)), dimensions (n),
00188       idx (0), idx_count (0) { }
00189 
00190   explicit Array (int n, const T& val)
00191     : rep (new typename Array<T>::ArrayRep (n)), dimensions (n),
00192       idx (0), idx_count (0)
00193     {
00194       fill (val);
00195     }
00196 
00197   // Type conversion case.
00198   template <class U>
00199   Array (const Array<U>& a)
00200     : rep (new typename Array<T>::ArrayRep (coerce (a.data (), a.length ()), a.length ())),
00201       dimensions (a.dimensions), idx (0), idx_count (0)
00202     {
00203     }
00204 
00205   // No type conversion case.
00206   Array (const Array<T>& a)
00207     : rep (a.rep), dimensions (a.dimensions), idx (0), idx_count (0)
00208     {
00209       rep->count++;
00210     }
00211 
00212 public:
00213 
00214   Array (const dim_vector& dv)
00215     : rep (new typename Array<T>::ArrayRep (get_size (dv))),
00216       dimensions (dv), idx (0), idx_count (0) { }
00217 
00218   Array (const dim_vector& dv, const T& val)
00219     : rep (new typename Array<T>::ArrayRep (get_size (dv))),
00220       dimensions (dv), idx (0), idx_count (0)
00221     {
00222       fill (val);
00223     }
00224 
00225   Array (const Array<T>& a, const dim_vector& dv);
00226 
00227   virtual ~Array (void);
00228 
00229   Array<T>& operator = (const Array<T>& a)
00230     {
00231       if (this != &a)
00232         {
00233           if (--rep->count <= 0)
00234             delete rep;
00235 
00236           rep = a.rep;
00237           rep->count++;
00238 
00239           dimensions = a.dimensions;
00240         }
00241 
00242       idx_count = 0;
00243       idx = 0;
00244 
00245       return *this;
00246     }
00247 
00248   void fill (const T& val) { make_unique (val); }
00249 
00250   int capacity (void) const { return rep->length (); }
00251   int length (void) const { return capacity (); }
00252   int nelem (void) const { return capacity (); }
00253   int numel (void) const { return nelem (); }
00254 
00255   int dim1 (void) const { return dimensions(0); }
00256   int dim2 (void) const { return dimensions(1); }
00257   int dim3 (void) const { return dimensions(2); }
00258 
00259   int rows (void) const { return dim1 (); }
00260   int cols (void) const { return dim2 (); }
00261   int columns (void) const { return dim2 (); }
00262   int pages (void) const { return dim3 (); }
00263 
00264   size_t byte_size (void) const { return numel () * sizeof (T); }
00265 
00266   dim_vector dims (void) const { return dimensions; }
00267 
00268   Array<T> squeeze (void) const;
00269   
00270   void chop_trailing_singletons (void) 
00271   { dimensions.chop_trailing_singletons (); }
00272   
00273   static int get_size (int r, int c);
00274   static int get_size (int r, int c, int p);
00275   static int get_size (const dim_vector& dv);
00276 
00277   int compute_index (const Array<int>& ra_idx) const;
00278 
00279   T range_error (const char *fcn, int n) const;
00280   T& range_error (const char *fcn, int n);
00281 
00282   T range_error (const char *fcn, int i, int j) const;
00283   T& range_error (const char *fcn, int i, int j);
00284 
00285   T range_error (const char *fcn, int i, int j, int k) const;
00286   T& range_error (const char *fcn, int i, int j, int k);
00287 
00288   T range_error (const char *fcn, const Array<int>& ra_idx) const;
00289   T& range_error (const char *fcn, const Array<int>& ra_idx);
00290 
00291   // No checking, even for multiple references, ever.
00292 
00293   T& xelem (int n) { return rep->elem (n); }
00294   T xelem (int n) const { return rep->elem (n); }
00295 
00296   T& xelem (int i, int j) { return xelem (dim1()*j+i); }
00297   T xelem (int i, int j) const { return xelem (dim1()*j+i); }
00298 
00299   T& xelem (int i, int j, int k) { return xelem (i, dim2()*k+j); }
00300   T xelem (int i, int j, int k) const { return xelem (i, dim2()*k+j); }
00301 
00302   T& xelem (const Array<int>& ra_idx)
00303     { return xelem (compute_index (ra_idx)); }
00304 
00305   T xelem (const Array<int>& ra_idx) const
00306     { return xelem (compute_index (ra_idx)); }
00307 
00308   // XXX FIXME XXX -- would be nice to fix this so that we don't
00309   // unnecessarily force a copy, but that is not so easy, and I see no
00310   // clean way to do it.
00311 
00312   T& checkelem (int n)
00313     {
00314       if (n < 0 || n >= rep->length ())
00315         return range_error ("T& Array<T>::checkelem", n);
00316       else
00317         {
00318           make_unique ();
00319           return xelem (n);
00320         }
00321     }
00322 
00323   T& checkelem (int i, int j)
00324     {
00325       if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
00326         return range_error ("T& Array<T>::checkelem", i, j);
00327       else
00328         return elem (dim1()*j+i);
00329     }
00330 
00331   T& checkelem (int i, int j, int k)
00332     {
00333       if (i < 0 || j < 0 || k < 0 || i >= dim1 () || j >= dim2 () || k >= dim3 ())
00334         return range_error ("T& Array<T>::checkelem", i, j, k);
00335       else
00336         return elem (i, dim2()*k+j);
00337     }
00338 
00339   T& checkelem (const Array<int>& ra_idx)
00340     {
00341       int i = compute_index (ra_idx);
00342 
00343       if (i < 0)
00344         return range_error ("T& Array<T>::checkelem", ra_idx);
00345       else
00346         return elem (i);
00347     }
00348 
00349   T& elem (int n)
00350     {
00351       make_unique ();
00352       return xelem (n);
00353     }
00354 
00355   T& elem (int i, int j) { return elem (dim1()*j+i); }
00356 
00357   T& elem (int i, int j, int k) { return elem (i, dim2()*k+j); }
00358 
00359   T& elem (const Array<int>& ra_idx)
00360     { return Array<T>::elem (compute_index (ra_idx)); }
00361 
00362 #if defined (BOUNDS_CHECKING)
00363   T& operator () (int n) { return checkelem (n); }
00364   T& operator () (int i, int j) { return checkelem (i, j); }
00365   T& operator () (int i, int j, int k) { return checkelem (i, j, k); }
00366   T& operator () (const Array<int>& ra_idx) { return checkelem (ra_idx); }
00367 #else
00368   T& operator () (int n) { return elem (n); }
00369   T& operator () (int i, int j) { return elem (i, j); }
00370   T& operator () (int i, int j, int k) { return elem (i, j, k); }
00371   T& operator () (const Array<int>& ra_idx) { return elem (ra_idx); }
00372 #endif
00373 
00374   T checkelem (int n) const
00375     {
00376       if (n < 0 || n >= rep->length ())
00377         return range_error ("T Array<T>::checkelem", n);
00378       else
00379         return xelem (n);
00380     }
00381 
00382   T checkelem (int i, int j) const
00383     {
00384       if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
00385         return range_error ("T Array<T>::checkelem", i, j);
00386       else
00387         return elem (dim1()*j+i);
00388     }
00389 
00390   T checkelem (int i, int j, int k) const
00391     {
00392       if (i < 0 || j < 0 || k < 0 || i >= dim1 () || j >= dim2 () || k >= dim3 ())
00393         return range_error ("T Array<T>::checkelem", i, j, k);
00394       else
00395         return Array<T>::elem (i, Array<T>::dim1()*k+j);
00396     }
00397 
00398   T checkelem (const Array<int>& ra_idx) const
00399     {
00400       int i = compute_index (ra_idx);
00401 
00402       if (i < 0)
00403         return range_error ("T Array<T>::checkelem", ra_idx);
00404       else
00405         return Array<T>::elem (i);
00406     }
00407 
00408   T elem (int n) const { return xelem (n); }
00409 
00410   T elem (int i, int j) const { return elem (dim1()*j+i); }
00411 
00412   T elem (int i, int j, int k) const { return elem (i, dim2()*k+j); }
00413 
00414   T elem (const Array<int>& ra_idx) const
00415     { return Array<T>::elem (compute_index (ra_idx)); }
00416 
00417 #if defined (BOUNDS_CHECKING)
00418   T operator () (int n) const { return checkelem (n); }
00419   T operator () (int i, int j) const { return checkelem (i, j); }
00420   T operator () (int i, int j, int k) const { return checkelem (i, j, k); }
00421   T operator () (const Array<int>& ra_idx) const { return checkelem (ra_idx); }
00422 #else
00423   T operator () (int n) const { return elem (n); }
00424   T operator () (int i, int j) const { return elem (i, j); }
00425   T operator () (int i, int j, int k) const { return elem (i, j, k); }
00426   T operator () (const Array<int>& ra_idx) const { return elem (ra_idx); }
00427 #endif
00428 
00429   Array<T> reshape (const dim_vector& new_dims) const;
00430 
00431   Array<T> permute (const Array<int>& vec, bool inv = false) const;
00432   Array<T> ipermute (const Array<int>& vec) const
00433     { return permute (vec, true); }
00434 
00435   void resize_no_fill (int n);
00436   void resize_and_fill (int n, const T& val);
00437 
00438   // !!! WARNING !!! -- the following resize_no_fill and
00439   // resize_and_fill functions are public because template friends
00440   // don't work properly with versions of gcc earlier than 3.3.  You
00441   // should use these functions only in classes that are derived
00442   // from Array<T>.
00443 
00444   // protected:
00445 
00446   void resize_no_fill (int r, int c);
00447   void resize_and_fill (int r, int c, const T& val);
00448 
00449   void resize_no_fill (int r, int c, int p);
00450   void resize_and_fill (int r, int c, int p, const T& val);
00451 
00452   void resize_no_fill (const dim_vector& dv);
00453   void resize_and_fill (const dim_vector& dv, const T& val);
00454 
00455 public:
00456 
00457   void resize (int n) { resize_no_fill (n); }
00458 
00459   void resize (int n, const T& val) { resize_and_fill (n, val); }
00460 
00461   void resize (const dim_vector& dv) { resize_no_fill (dv); }
00462 
00463   void resize (const dim_vector& dv, const T& val)
00464     { resize_and_fill (dv, val); }
00465 
00466   Array<T>& insert (const Array<T>& a, int r, int c);
00467   Array<T>& insert2 (const Array<T>& a, int r, int c);
00468   Array<T>& insertN (const Array<T>& a, int r, int c);
00469 
00470   Array<T>& insert (const Array<T>& a, const Array<int>& idx);
00471 
00472   bool is_square (void) const { return (dim1 () == dim2 ()); }
00473 
00474   bool is_empty (void) const { return numel () == 0; }
00475 
00476   Array<T> transpose (void) const;
00477 
00478   const T *data (void) const { return rep->data; }
00479 
00480   const T *fortran_vec (void) const { return data (); }
00481 
00482   T *fortran_vec (void);
00483 
00484   Array<T>& qsort (int (*compare) (const void *, const void *))
00485     {
00486       make_unique ();
00487 
00488       rep->qsort (compare);
00489 
00490       return *this;
00491     }
00492 
00493   int ndims (void) const { return dimensions.length (); }
00494 
00495   void maybe_delete_dims (void);
00496 
00497   void clear_index (void);
00498 
00499   void set_index (const idx_vector& i);
00500 
00501   int index_count (void) const { return idx_count; }
00502 
00503   idx_vector *get_idx (void) const { return idx; }
00504 
00505   void maybe_delete_elements (idx_vector& i);
00506 
00507   void maybe_delete_elements_1 (idx_vector& i);
00508 
00509   void maybe_delete_elements_2 (idx_vector& i);
00510 
00511   void maybe_delete_elements (idx_vector& i, idx_vector& j);
00512 
00513   void maybe_delete_elements (idx_vector& i, idx_vector& j, idx_vector& k);
00514 
00515   void maybe_delete_elements (Array<idx_vector>& ra_idx, const T& rfv);
00516 
00517   Array<T> value (void);
00518 
00519   Array<T> index (idx_vector& i, int resize_ok = 0,
00520                   const T& rfv = resize_fill_value (T ())) const;
00521 
00522   Array<T> index1 (idx_vector& i, int resize_ok = 0,
00523                    const T& rfv = resize_fill_value (T ())) const;
00524 
00525   Array<T> index2 (idx_vector& i, int resize_ok = 0,
00526                    const T& rfv = resize_fill_value (T ())) const;
00527 
00528   Array<T> indexN (idx_vector& i, int resize_ok = 0,
00529                    const T& rfv = resize_fill_value (T ())) const;
00530 
00531   Array<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0,
00532                   const T& rfv = resize_fill_value (T ())) const;
00533 
00534   Array<T> index (Array<idx_vector>& ra_idx, int resize_ok = 0,
00535                   const T& rfv = resize_fill_value (T ())) const;
00536 
00537   //  static T resize_fill_value (void) { return T (); }
00538 
00539   void print_info (std::ostream& os, const std::string& prefix) const;
00540 };
00541 
00542 // NOTE: these functions should be friends of the Array<T> class and
00543 // Array<T>::dimensions should be protected, not public, but we can't
00544 // do that because of bugs in gcc prior to 3.3.
00545 
00546 template <class LT, class RT>
00547 /* friend */ int
00548 assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv);
00549 
00550 template <class LT, class RT>
00551 /* friend */ int
00552 assign1 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv);
00553 
00554 template <class LT, class RT>
00555 /* friend */ int
00556 assign2 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv);
00557 
00558 template <class LT, class RT>
00559 /* friend */ int
00560 assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv);
00561 
00562 template <class LT, class RT>
00563 int
00564 assign (Array<LT>& lhs, const Array<RT>& rhs)
00565 {
00566   return assign (lhs, rhs, resize_fill_value (LT ()));
00567 }
00568 
00569 #define INSTANTIATE_ARRAY_ASSIGN(LT, RT) \
00570   template int assign (Array<LT>&, const Array<RT>&, const LT&); \
00571   template int assign1 (Array<LT>&, const Array<RT>&, const LT&); \
00572   template int assign2 (Array<LT>&, const Array<RT>&, const LT&); \
00573   template int assignN (Array<LT>&, const Array<RT>&, const LT&); \
00574   template int assign (Array<LT>&, const Array<RT>&)
00575 
00576 
00577 #define INSTANTIATE_ARRAY(T) \
00578   template class Array<T>; \
00579   template T resize_fill_value (const T&); \
00580 
00581 #define INSTANTIATE_ARRAY_AND_ASSIGN(T) \
00582   INSTANTIATE_ARRAY (T); \
00583   INSTANTIATE_ARRAY_ASSIGN (T, T)
00584 
00585 #endif
00586 
00587 /*
00588 ;;; Local Variables: ***
00589 ;;; mode: C++ ***
00590 ;;; End: ***
00591 */

Wed Dec 29 11:50:54 2004に生成されました。 doxygen1.2.18
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送