src/Index/NDIndex.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef NDINDEX_H
00012 #define NDINDEX_H
00013 
00014 // include files
00015 #include "Index/Index.h"
00016 
00017 #ifdef IPPL_USE_STANDARD_HEADERS
00018 #include <iostream>
00019 using namespace std;
00020 #else
00021 #include <iostream.h>
00022 #endif
00023 
00024 // forward declarations
00025 template <unsigned Dim> class NDIndex;
00026 
00027 template <unsigned Dim>
00028 NDIndex<Dim> operator+(const NDIndex<Dim>&, const int *);
00029 template <unsigned Dim>
00030 NDIndex<Dim> operator+(const int *,const NDIndex<Dim>&);
00031 
00032 template <unsigned Dim>
00033 NDIndex<Dim> operator-(const NDIndex<Dim>&, const int *);
00034 template <unsigned Dim>
00035 NDIndex<Dim> operator-(const int *,const NDIndex<Dim>&);
00036 
00037 template <unsigned Dim>
00038 NDIndex<Dim> operator-(const NDIndex<Dim>&);
00039 
00040 template <unsigned Dim>
00041 NDIndex<Dim> operator*(const NDIndex<Dim>&, const int *);
00042 template <unsigned Dim>
00043 NDIndex<Dim> operator*(const int *,const NDIndex<Dim>&);
00044 
00045 template <unsigned Dim>
00046 NDIndex<Dim> operator/(const NDIndex<Dim>&, const int *);
00047 
00048 template <unsigned Dim>
00049 bool operator<(const NDIndex<Dim>&, const NDIndex<Dim>&);
00050 
00051 template <unsigned Dim, unsigned Dim2>
00052 bool operator==(const NDIndex<Dim>&, const NDIndex<Dim2>&);
00053 
00054 template <unsigned Dim>
00055 ostream& operator<<(ostream&, const NDIndex<Dim>&);
00056 
00058 
00059 //
00060 // Implementation of plugbase that the member template and enumerated
00061 // plugbase member functions use.
00062 //
00063 
00064 template<unsigned D1, unsigned D2>
00065 NDIndex<D1> plugBase(const NDIndex<D1>&, const NDIndex<D2>&);
00066 
00067 
00068 
00069 /***********************************************************************
00070 
00071 This is a simple wrapper around Index that just keeps track of
00072 N of them and passes along requests for intersect, plugBase and
00073 so on.
00074 
00075 ***********************************************************************/
00076 
00077 template<unsigned Dim>
00078 class NDIndex
00079 {
00080 public: 
00081 
00082   // Null ctor does nothing.
00083   NDIndex() {}
00084 
00085   // Construct from a simple array of Indexes
00086   NDIndex(const Index *idx);
00087 
00088   // Construct from individual indexes.
00089   // Only instantiate the ones that make sense.
00090   NDIndex(const Index&);
00091   NDIndex(const Index&,const Index&);
00092   NDIndex(const Index&,const Index&,const Index&);
00093   NDIndex(const Index&,const Index&,const Index&,
00094           const Index&);
00095   NDIndex(const Index&,const Index&,const Index&,
00096           const Index&,const Index&);
00097   NDIndex(const Index&,const Index&,const Index&,
00098           const Index&,const Index&,const Index&);
00099   NDIndex(const NDIndex<Dim-1>&, const Index&);
00100 
00101   // Return a reference to any of the Indexes.
00102   const Index& operator[](unsigned d) const
00103     {
00104       return p[d];
00105     }
00106   Index& operator[](unsigned d)
00107     {
00108       return p[d];
00109     }
00110 
00111   // Get the total size.
00112   unsigned size() const;
00113 
00114   // Stuff for doing index mapping calculations.
00115   bool empty() const;
00116   NDIndex<Dim> intersect(const NDIndex<Dim>&) const;
00117 #ifdef IPPL_USE_MEMBER_TEMPLATES
00118   template<unsigned D>
00119   NDIndex<Dim> plugBase(const NDIndex<D>& i)const { 
00120       return ::plugBase(*this,i);
00121   }
00122 #else
00123   NDIndex<Dim> plugBase(const NDIndex<1>& i)const{ return ::plugBase(*this,i);}
00124   NDIndex<Dim> plugBase(const NDIndex<2>& i)const{ return ::plugBase(*this,i);}
00125   NDIndex<Dim> plugBase(const NDIndex<3>& i)const{ return ::plugBase(*this,i);}
00126   NDIndex<Dim> plugBase(const NDIndex<4>& i)const{ return ::plugBase(*this,i);}
00127   NDIndex<Dim> plugBase(const NDIndex<5>& i)const{ return ::plugBase(*this,i);}
00128   NDIndex<Dim> plugBase(const NDIndex<6>& i)const{ return ::plugBase(*this,i);}
00129   NDIndex<Dim> plugBase(const NDIndex<7>& i)const{ return ::plugBase(*this,i);}
00130 #endif
00131 
00132   // useful functions with DomainMap.
00133   bool touches(const NDIndex<Dim>&) const;
00134   bool contains(const NDIndex<Dim>& a) const;
00135   bool containsAllPoints(const NDIndex<Dim> &b) const;
00136   
00137   // Split on dimension d with the given ratio 0<a<1.
00138   bool split(NDIndex<Dim>& l, NDIndex<Dim>& r, unsigned d, double a) const;
00139   // Split on dimension d, or the longest dimension.
00140   bool split(NDIndex<Dim>& l, NDIndex<Dim>& r, unsigned d) const;
00141   bool split(NDIndex<Dim>& l, NDIndex<Dim>& r) const;
00142 
00143   // put data into a message to send to another node
00144   Message& putMessage(Message& m) const {
00145     unsigned d;
00146     for ( d = 0 ; d < Dim ; ++d )
00147       p[d].putMessage(m);
00148     return m;
00149   }
00150 
00151   // get data out from a message
00152   Message& getMessage(Message& m) {
00153     unsigned d;
00154     for ( d = 0 ; d < Dim ; ++d )
00155       p[d].getMessage(m);
00156     return m;
00157   }
00158 private:
00159   Index p[Dim==0?1:Dim];                        // Pointer to the indexes.
00160 
00161 };
00162 
00163 
00164 // Additive operations.
00165 template <unsigned Dim>
00166 inline
00167 NDIndex<Dim> operator+(const NDIndex<Dim>& ndi, const int * off)
00168 {
00169   NDIndex<Dim> newNdi;
00170   for (unsigned d=0; d<Dim; d++) newNdi[d] = ndi[d] + off[d];
00171   return newNdi;
00172 }
00173 template <unsigned Dim>
00174 inline
00175 NDIndex<Dim> operator+(const int * off, const NDIndex<Dim>& ndi)
00176 {
00177   NDIndex<Dim> newNdi;
00178   for (unsigned d=0; d<Dim; d++) newNdi[d] = off[d] + ndi[d];
00179   return newNdi;
00180 }
00181 template <unsigned Dim>
00182 inline
00183 NDIndex<Dim> operator-(const NDIndex<Dim>& ndi, const int * off)
00184 {
00185   NDIndex<Dim> newNdi;
00186   for (unsigned d=0; d<Dim; d++) newNdi[d] = ndi[d] - off[d];
00187   return newNdi;
00188 } 
00189 template <unsigned Dim>
00190 inline
00191 NDIndex<Dim> operator-(const int * off, const NDIndex<Dim>& ndi)
00192 {
00193   NDIndex<Dim> newNdi;
00194   for (unsigned d=0; d<Dim; d++) newNdi[d] = off[d] - ndi[d];
00195   return newNdi;
00196 }
00197 
00198 // Multipplicative operations.
00199 template <unsigned Dim>
00200 inline
00201 NDIndex<Dim> operator-(const NDIndex<Dim>& ndi)
00202 {
00203   NDIndex<Dim> newNdi;
00204   for (unsigned d=0; d<Dim; d++) newNdi[d] = -ndi[d];
00205   return newNdi;
00206 }
00207 template <unsigned Dim>
00208 inline
00209 NDIndex<Dim> operator*(const NDIndex<Dim>& ndi, const int * mult)
00210 {
00211   NDIndex<Dim> newNdi;
00212   for (unsigned d=0; d<Dim; d++) newNdi[d] = ndi[d] * mult[d];
00213   return newNdi;
00214 }
00215 template <unsigned Dim>
00216 inline
00217 NDIndex<Dim> operator*(const int * mult, const NDIndex<Dim>& ndi)
00218 {
00219   NDIndex<Dim> newNdi;
00220   for (unsigned d=0; d<Dim; d++) newNdi[d] = mult[d] * ndi[d];
00221   return newNdi;
00222 }
00223 template <unsigned Dim>
00224 inline
00225 NDIndex<Dim> operator/(const NDIndex<Dim>& ndi, const int *denom)
00226 {
00227   NDIndex<Dim> newNdi;
00228   for (unsigned d=0; d<Dim; d++) newNdi[d] = ndi[d]/denom[d];
00229   return newNdi;
00230 }
00231 
00232 // Comparison operators so we can use a map container
00233 // Just compare the Indexes in turn.
00234 template <unsigned Dim>
00235 inline
00236 bool operator<(const NDIndex<Dim>& lhs, const NDIndex<Dim>& rhs) {
00237   for (unsigned d=0; d<Dim; ++d) {
00238     if (lhs[d] < rhs[d]) return true;
00239     if ( !(lhs[d]==rhs[d]) ) return false;
00240   }
00241   return false;
00242 }
00243 
00244 template <unsigned Dim, unsigned Dim2>
00245 inline
00246 bool operator==(const NDIndex<Dim>& lhs, const NDIndex<Dim2>& rhs) {
00247   if (Dim != Dim2) {
00248     return false;
00249   } else {
00250     for (unsigned d=0; d<Dim; ++d)
00251       if ( !(lhs[d]==rhs[d]) ) return false;
00252     return true;
00253   }
00254 }
00255 
00256 // write NDIndex out to the given stream
00257 template <unsigned Dim>
00258 inline ostream&
00259 operator<<(ostream& out, const NDIndex<Dim>& idx) {
00260   unsigned d;
00261   out << '{';
00262   for (d = 0; d < Dim; ++d) 
00263     out << idx[d] << ((d==Dim-1) ? '}' : ',');
00264   return out;
00265 }
00266 
00267 
00268 
00269 
00271 
00272 // Build some helper objects for use in maps.
00273 
00274 template<unsigned Dim>
00275 class Touches 
00276 {
00277 public:
00278   Touches() {}
00279   static bool test(const NDIndex<Dim>& a, const NDIndex<Dim>& b) 
00280   {
00281     return a.touches(b);
00282   }
00283 };
00284 
00285 template<unsigned Dim>
00286 class Contains 
00287 {
00288 public:
00289   Contains() {}
00290   static bool test(const NDIndex<Dim>& a, const NDIndex<Dim>& b) 
00291   {
00292     return a.contains(b);
00293   }
00294 };
00295 
00296 template<unsigned Dim>
00297 class Split 
00298 {
00299 public:
00300   Split() {}
00301   static bool test(NDIndex<Dim>& l,
00302                    NDIndex<Dim>& r,
00303                    const NDIndex<Dim>& a) 
00304   {
00305     return a.split(l,r);
00306   }
00307 };
00308 
00310 
00311 #ifndef NDINDEX_INLINES_H
00312 #include "Index/NDIndexInlines.h"
00313 #endif
00314 
00316 
00317 #endif // NDINDEX_H
00318 
00319 /***************************************************************************
00320  * $RCSfile: NDIndex.h,v $   $Author: adelmann $
00321  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
00322  * IPPL_VERSION_ID: $Id: NDIndex.h,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
00323  ***************************************************************************/

Generated on Mon Jan 16 13:23:48 2006 for IPPL by  doxygen 1.4.6