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

dim-vector.h

解説を見る。
00001 /*
00002 
00003 Copyright (C) 2003 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 2, or (at your option) any
00010 later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 
00021 */
00022 
00023 #if !defined (octave_dim_vector_h)
00024 #define octave_dim_vector_h 1
00025 
00026 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
00027 #pragma interface
00028 #endif
00029 
00030 #include <cassert>
00031 #include <string>
00032 
00033 #include "lo-sstream.h"
00034 
00035 class
00036 dim_vector
00037 {
00038 protected:
00039 
00040   class dim_vector_rep
00041   {
00042   public:
00043 
00044     int *dims;
00045     int ndims;
00046     int count;
00047 
00048     dim_vector_rep (void) : dims (0), ndims (0), count (1) { }
00049 
00050     dim_vector_rep (int n) : dims (new int [1]), ndims (1), count (1)
00051     {
00052       dims[0] = n;
00053     }
00054 
00055     dim_vector_rep (int r, int c) : dims (new int [2]), ndims (2), count (1)
00056     {
00057       dims[0] = r;
00058       dims[1] = c;
00059     }
00060 
00061     dim_vector_rep (int r, int c, int p)
00062       : dims (new int [3]), ndims (3), count (1)
00063     {
00064       dims[0] = r;
00065       dims[1] = c;
00066       dims[2] = p;
00067     }
00068 
00069     dim_vector_rep (const dim_vector_rep& dv)
00070       : dims (dv.ndims > 0 ? new int [dv.ndims] : 0),
00071         ndims (dv.ndims > 0 ? dv.ndims : 0), count (1)
00072     {
00073       if (dims)
00074         {
00075           for (int i = 0; i < ndims; i++)
00076             dims[i] = dv.dims[i];
00077         }
00078     }
00079 
00080     dim_vector_rep (int n, const dim_vector_rep *dv, int fill_value = 0)
00081       : dims ((dv && n > 0) ? new int [n] : 0),
00082         ndims (n > 0 ? n : 0), count (1)
00083     {
00084       if (dims)
00085         {
00086           int dv_ndims = dv ? dv->ndims : 0;
00087 
00088           int min_len = n < dv_ndims ? n : dv_ndims;
00089 
00090           for (int i = 0; i < min_len; i++)
00091             dims[i] = dv->dims[i];
00092 
00093           for (int i = dv_ndims; i < n; i++)
00094             dims[i] = fill_value;
00095         }
00096     }
00097 
00098     ~dim_vector_rep (void) { delete [] dims; }
00099 
00100     int length (void) const { return ndims; }
00101 
00102     int& elem (int i)
00103     {
00104       assert (i >= 0 && i < ndims);
00105       return dims[i];
00106     }
00107 
00108     int elem (int i) const
00109     {
00110       assert (i >= 0 && i < ndims);
00111       return dims[i];
00112     }
00113 
00114     void chop_trailing_singletons (void)
00115     {
00116       for (int i = ndims - 1; i > 1; i--)
00117         {
00118           if (dims[i] == 1)
00119             ndims--;
00120           else
00121             break;
00122         }
00123     }
00124 
00125   private:
00126 
00127     // No assignment!
00128 
00129     dim_vector_rep& operator = (const dim_vector_rep& dv);
00130   };
00131 
00132   dim_vector_rep *rep;
00133 
00134   void make_unique (void)
00135   {
00136     if (rep->count > 1)
00137       {
00138         --rep->count;
00139         rep = new dim_vector_rep (*rep);
00140       }
00141   }
00142 
00143 private:
00144 
00145   dim_vector_rep *nil_rep (void) const
00146   {
00147     static dim_vector_rep *nr = new dim_vector_rep ();
00148 
00149     return nr;
00150   }
00151 
00152 public:
00153 
00154   explicit dim_vector (void)
00155     : rep (nil_rep ()) { rep->count++; }
00156 
00157   explicit dim_vector (int n)
00158     : rep (new dim_vector_rep (n)) { }
00159 
00160   explicit dim_vector (int r, int c)
00161     : rep (new dim_vector_rep (r, c)) { }
00162 
00163   explicit dim_vector (int r, int c, int p)
00164     : rep (new dim_vector_rep (r, c, p)) { }
00165 
00166   dim_vector (const dim_vector& dv)
00167     : rep (dv.rep) { rep->count++; }
00168 
00169   dim_vector& operator = (const dim_vector& dv)
00170   {
00171     if (&dv != this)
00172       {
00173         if (--rep->count <= 0)
00174           delete rep;
00175 
00176         rep = dv.rep;
00177         rep->count++;
00178       }
00179 
00180     return *this;
00181   }
00182 
00183   ~dim_vector (void)
00184   {
00185     if (--rep->count <= 0)
00186       delete rep;
00187   }
00188 
00189   int length (void) const { return rep->length (); }
00190 
00191   int& elem (int i) { make_unique (); return rep->elem (i); }
00192 
00193   int elem (int i) const { return rep->elem (i); }
00194 
00195   int& operator () (int i) { return elem (i); }
00196 
00197   int operator () (int i) const { return elem (i); }
00198 
00199   void resize (int n, int fill_value = 0)
00200   {
00201     int len = length ();
00202 
00203     if (n != len)
00204       {
00205         dim_vector_rep *old_rep = rep;
00206 
00207         rep = new dim_vector_rep (n, old_rep, fill_value);
00208 
00209         if (--old_rep->count <= 0)
00210           delete old_rep;
00211       }
00212   }
00213 
00214   std::string str (char sep = 'x') const
00215   {
00216     OSSTREAM buf;
00217 
00218     for (int i = 0; i < length (); i++)
00219       {
00220         buf << elem (i);
00221 
00222         if (i < length () - 1)
00223           buf << sep;
00224       }
00225 
00226     buf << OSSTREAM_ENDS;
00227 
00228     std::string retval = OSSTREAM_STR (buf);
00229 
00230     OSSTREAM_FREEZE (buf);
00231 
00232     return retval;
00233   }
00234 
00235   bool all_zero (void) const
00236   {
00237     bool retval = true;
00238 
00239     for (int i = 0; i < length (); i++)
00240       {
00241         if (elem (i) != 0)
00242           {
00243             retval = false;
00244             break;
00245           }
00246       }
00247 
00248     return retval;
00249   }
00250 
00251   bool any_zero (void) const
00252   {
00253     bool retval = false;
00254 
00255     for (int i = 0; i < length (); i++)
00256       {
00257         if (elem (i) == 0)
00258           {
00259             retval = true;
00260             break;
00261           }
00262       }
00263 
00264     return retval;
00265   }
00266 
00267   int
00268   num_ones (void) const
00269   {
00270     int retval = 0;
00271 
00272     for (int i = 0; i < length (); i++)
00273       if (elem (i) == 1)
00274         retval++;
00275 
00276     return retval;
00277   }
00278 
00279   bool
00280   all_ones (void) const
00281   {
00282     return (num_ones () == length ());
00283   }
00284 
00285   // This is the number of elements that a matrix with this dimension
00286   // vector would have, NOT the number of dimensions (elements in the
00287   // dimension vector).
00288 
00289   int numel (void) const
00290   {
00291     int n_dims = length ();
00292 
00293     int retval = n_dims > 0 ? elem (0) : 0;
00294 
00295     for (int i = 1; i < n_dims; i++)
00296       retval *= elem (i);
00297 
00298     return retval;
00299   }
00300 
00301   void chop_trailing_singletons (void)
00302   {
00303     make_unique ();
00304     rep->chop_trailing_singletons ();
00305   }
00306 
00307   dim_vector squeeze (void) const
00308   {
00309     dim_vector new_dims = *this;
00310 
00311     bool dims_changed = 1;
00312 
00313     int k = 0;
00314 
00315     for (int i = 0; i < length (); i++)
00316       {
00317         if (elem (i) == 1)
00318           dims_changed = true;
00319         else
00320           new_dims(k++) = elem (i);
00321       }
00322 
00323     if (dims_changed)
00324       {
00325         if (k == 0)
00326           new_dims = dim_vector (1, 1);
00327         else if (k == 1)
00328           {
00329             // There is one non-singleton dimension, so we need
00330             // to decide the correct orientation.
00331 
00332             if (elem (0) == 1)
00333               {
00334                 // The original dimension vector had a leading
00335                 // singleton dimension.
00336 
00337                 int tmp = new_dims(0);
00338         
00339                 new_dims.resize (2);
00340 
00341                 new_dims(0) = 1;
00342                 new_dims(1) = tmp;
00343               }
00344             else
00345               {
00346                 // The first element of the original dimension vector
00347                 // was not a singleton dimension.
00348 
00349                 new_dims.resize (2);
00350 
00351                 new_dims(1) = 1;
00352               }
00353           }
00354         else
00355           new_dims.resize(k);
00356       }
00357  
00358     return new_dims;
00359   }
00360 
00361   bool concat (const dim_vector& dvb, int dim = 0)
00362   {
00363     if (all_zero ())
00364       {
00365         *this = dvb;
00366         return true;
00367       }
00368 
00369     if (dvb.all_zero ())
00370       return true;
00371 
00372     int na = length ();
00373     int nb = dvb.length ();
00374   
00375     // Find the max and min value of na and nb
00376     int n_max = na > nb ? na : nb;
00377     int n_min = na < nb ? na : nb;
00378   
00379     // The elements of the dimension vectors can only differ
00380     // if the dim variable differs from the actual dimension
00381     // they differ.
00382 
00383     for (int i = 0; i < n_min; i++)
00384       {
00385         if (elem(i) != dvb(i) && dim != i)
00386             return false;
00387       }
00388   
00389     // Ditto.
00390     for (int i = n_min; i < n_max; i++)
00391       {
00392         if (na > n_min)
00393           {
00394             if (elem(i) != 1 && dim != i)
00395               return false;
00396           }
00397         else 
00398           {
00399             if (dvb(i) != 1 && dim != i)
00400               return false;
00401           }
00402       }
00403     
00404     // If we want to add the dimension vectors at a dimension
00405     // larger than both, then we need to set n_max to this number
00406     // so that we resize *this to the right dimension.
00407     
00408     n_max = n_max > (dim + 1) ? n_max : (dim + 1);
00409     
00410     // Resize *this to the appropriate dimensions.
00411     
00412     if (n_max > na)
00413       {
00414         dim_vector_rep *old_rep = rep;
00415 
00416         rep = new dim_vector_rep (n_max, old_rep, 1);
00417 
00418         if (--old_rep->count <= 0)
00419           delete old_rep;
00420       }
00421   
00422     // Larger or equal since dim has been decremented by one.
00423 
00424     if (dim >= nb)
00425       elem (dim)++;
00426     else
00427       elem (dim) += dvb(dim);
00428 
00429     return true;
00430   }
00431 };
00432 
00433 static inline bool
00434 operator == (const dim_vector& a, const dim_vector& b)
00435 {
00436   bool retval = true;
00437 
00438   int a_len = a.length ();
00439   int b_len = b.length ();
00440 
00441   if (a_len != b_len)
00442     retval = false;
00443   else
00444     {
00445       for (int i = 0; i < a_len; i++)
00446         {
00447           if (a(i) != b(i))
00448             {
00449               retval = false;
00450               break;
00451             }
00452         }
00453     }
00454 
00455   return retval;
00456 }
00457 
00458 static inline bool
00459 operator != (const dim_vector& a, const dim_vector& b)
00460 {
00461   return ! operator == (a, b);
00462 }
00463 
00464 #endif
00465 
00466 /*
00467 ;;; Local Variables: ***
00468 ;;; mode: C++ ***
00469 ;;; End: ***
00470 */

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