src/Region/PRegion.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 PREGION_H
00012 #define PREGION_H
00013 
00014 /***********************************************************************
00015  * PRegion represents a (possibly continuous) numeric interval.  It is 
00016  * similar to Index, with the following differences:
00017  *      1. It is templated on the data type; Index always uses integers
00018  *      2. A PRegion is defined between two endpoints A and B; the PRegion
00019  *         includes values X where A <= X < B (i.e., X in [A,B) )
00020  *      3. PRegion does not keep track of a base Index, and does not
00021  *         supply the plugBase operation.  It is not designed for use in
00022  *         Field operations like Index is, it is meant instead for use in
00023  *         Particle construction and usage.
00024  *
00025  ***********************************************************************
00026  *
00027  * PRegion<T>()      --> make a PRegion on [0,1)
00028  * PRegion<T>(B)     --> make a PRegion on [0,B)
00029  * PRegion<T>(A,B)   --> make a PRegion on [A,B)
00030  *
00031  ***********************************************************************/
00032 
00033 // include files
00034 #include "Message/Message.h"
00035 
00036 #ifdef IPPL_USE_STANDARD_HEADERS
00037 #include <iostream>
00038 using namespace std;
00039 #else
00040 #include <iostream.h>
00041 #endif
00042 
00043 // forward declarations
00044 template<class T> class PRegion;
00045 template <class T>
00046 PRegion<T> operator+(const PRegion<T>&, T);
00047 template <class T>
00048 PRegion<T> operator+(T, const PRegion<T>&);
00049 template <class T>
00050 PRegion<T> operator-(const PRegion<T>&, T);
00051 template <class T>
00052 PRegion<T> operator-(T, const PRegion<T>&);
00053 template <class T>
00054 PRegion<T> operator-(const PRegion<T>&);
00055 template <class T>
00056 PRegion<T> operator*(const PRegion<T>&, T);
00057 template <class T>
00058 PRegion<T> operator*(T, const PRegion<T>&);
00059 template <class T>
00060 PRegion<T> operator/(const PRegion<T>&, T);
00061 template<class T>
00062 ostream& operator<<(ostream&, const PRegion<T>&);
00063 
00064 template<class T>
00065 class PRegion {
00066 
00067 public:
00068   // 
00069   // Member functions.  Make these inline for efficiency.
00070   //
00071 
00072   // Constructors
00073   PRegion() : First(0), Last(1) {}                       // [0,1)
00074   PRegion(T B) : First(0), Last(B) {}                    // [0,B)
00075   PRegion(T A, T B) : First(A), Last(B) {}               // [A,B)
00076 
00077   // Destructor ... nothing to do
00078   ~PRegion() {}
00079 
00080   // General query functions
00081   T min() const { return (First < Last ? First : Last); }  // smallest elem
00082   T max() const { return (First > Last ? First : Last); }  // largest elem
00083   T length() const { return (max() - min()); }             // length of region
00084   T first() const { return First; }                        // first element.
00085   T last() const { return Last; }                          // last element.
00086   bool empty() const { return (First == Last);}            // is it empty?
00087 
00088   // compute-assign operators
00089   PRegion<T>& operator+=(T t) {
00090     First += t;
00091     Last += t;
00092     return *this;
00093   }
00094   PRegion<T>& operator-=(T t) {
00095     First -= t;
00096     Last -= t;
00097     return *this;
00098   }
00099   PRegion<T>& operator*=(T t) {
00100     First *= t;
00101     Last *= t;
00102     return *this;
00103   }
00104   PRegion<T>& operator/=(T t) {
00105     if (t != 0) {
00106       First /= t;
00107       Last /= t;
00108     }
00109     return *this;
00110   }
00111 
00112   // Intersect with another PRegion.  Since we have possibly continuous
00113   // variables, we do not consider the stride here, just where the two
00114   // intervals overlap (if at all)
00115   PRegion<T> intersect(const PRegion<T>& r) const {
00116     T A = 0;
00117     T B = 0;
00118 
00119     // find min and max of both ranges
00120     T Amin = min();
00121     T Amax = max();
00122     T Bmin = r.min();
00123     T Bmax = r.max();
00124 
00125     // make sure these regions overlap
00126     // must check special case of single points
00127     if (Amin == Amax) {
00128       if ((Bmin == Bmax && Amin == Bmin) ||
00129           (Bmin != Bmax && Amin >= Bmin && Amin < Bmax))
00130         A = B = Amin;
00131     }
00132     else if (Bmin == Bmax) {
00133       if (Bmin >= Amin && Bmin < Amax)
00134         A = B = Bmin;
00135     }
00136     else {
00137       if (Amax > Bmin && Bmax > Amin) {
00138         A = (Amin > Bmin ? Amin : Bmin);
00139         B = (Amax < Bmax ? Amax : Bmax);
00140       }
00141     }
00142 
00143     // now return the intersecting region
00144     return PRegion<T>(A, B);
00145   }
00146 
00147   // Test to see if there is any overlap between two PRegions
00148   bool touches(const PRegion<T>& r) const {
00149     bool retval = false;
00150     // find min and max of both ranges
00151     T Amin = min();
00152     T Amax = max();
00153     T Bmin = r.min();
00154     T Bmax = r.max();
00155 
00156     // check for overlap ... must check special case of single points
00157     if (Amin == Amax) {
00158       if ((Bmin == Bmax && Amin == Bmin) ||
00159           (Bmin != Bmax && Amin >= Bmin && Amin < Bmax))
00160         retval = true;
00161     }
00162     else if (Bmin == Bmax) {
00163       if (Bmin >= Amin && Bmin < Amax)
00164         retval = true;
00165     }
00166     else {
00167       if (Amax > Bmin && Bmax > Amin)
00168         retval = true;
00169     }
00170     return retval;
00171   }
00172 
00173   // Test to see if the given PRegion is contained within this one
00174   bool contains(const PRegion<T>& r) const {
00175     return ( min() <= r.min() && max() >= r.max() );
00176   }
00177 
00178   // Split one into two.
00179   bool split(PRegion<T>& l, PRegion<T>& r) const {
00180     T mid = First + (Last - First) / T(2);
00181     l = PRegion<T>(First, mid);
00182     r = PRegion<T>(mid, Last);
00183     return true;
00184   }
00185 
00186   // An operator< so we can impose some sort of ordering.
00187   bool operator<(const PRegion<T>& r) const {
00188     T L1 = length();
00189     T L2 = r.length();
00190     T Amin = min();
00191     T Bmin = r.min();
00192     return ( (L1 < L2) || ( (L1 == L2) && ( (Amin < Bmin) ||
00193                    ( (Amin == Bmin) && (L1 > 0) ) ) ) );
00194   }
00195 
00196   // Test for equality.
00197   bool operator==(const PRegion<T>& r) const {
00198     return ( (Last==r.Last) && (First==r.First) );
00199   }
00200 
00201   // put data into a message to send to another node
00202   Message& putMessage(Message& m) {
00203     T d[2];
00204     d[0] = First;
00205     d[1] = Last;
00206 #ifdef IPPL_USE_MEMBER_TEMPLATES
00207     m.put(d, d + 2);
00208 #else
00209     putMessage(m,d,d+2);
00210 #endif
00211     return m;
00212   }
00213 
00214   // get data out from a message
00215   Message& getMessage(Message& m) {
00216     T d[2];
00217 #ifdef IPPL_USE_MEMBER_TEMPLATES
00218     m.get_iter(d);
00219 #else
00220     getMessage_iter(m,d);
00221 #endif
00222     *this = PRegion<T>(d[0], d[1]);
00223     return m;
00224   }
00225 
00226 private: 
00227   // The interval endpoints
00228   T First, Last;
00229 };
00230 
00231 
00232 // Additive operations.
00233 template <class T>
00234 inline 
00235 PRegion<T> operator+(const PRegion<T>& r, T t) {
00236   return PRegion<T>(r.first() + t, r.last() + t);
00237 }
00238 template <class T>
00239 inline 
00240 PRegion<T> operator+(T t, const PRegion<T>& r) {
00241   return PRegion<T>(r.first() + t, r.last() + t);
00242 }
00243 template <class T>
00244 inline 
00245 PRegion<T> operator-(const PRegion<T>& r, T t) {
00246   return PRegion<T>(r.first() - t, r.last() - t);
00247 }
00248 template <class T>
00249 inline 
00250 PRegion<T> operator-(T t, const PRegion<T>& r) {
00251   return PRegion<T>(t - r.first(), t - r.last());
00252 }
00253 
00254 // Multipplicative operations.
00255 template <class T>
00256 inline 
00257 PRegion<T> operator-(const PRegion<T>& r) {
00258   return PRegion<T>(-r.first(), -r.last());
00259 }
00260 template <class T>
00261 inline 
00262 PRegion<T> operator*(const PRegion<T>& r, T t) {
00263   return PRegion<T>(r.first() * t, r.last() * t);
00264 }
00265 template <class T>
00266 inline 
00267 PRegion<T> operator*(T t, const PRegion<T>& r) {
00268   return PRegion<T>(r.first() * t, r.last() * t);
00269 }
00270 template <class T>
00271 inline 
00272 PRegion<T> operator/(const PRegion<T>& r, T t) {
00273   if (t != 0)
00274     return PRegion<T>(r.first() / t, r.last() / t);
00275   else        // This is an error!!
00276     return r;
00277 }
00278 
00279 // Print out PRegion.
00280 template <class T>
00281 inline 
00282 ostream& operator<<(ostream& out, const PRegion<T>& r) {
00283   out << '[' << r.min();
00284   out << ',' << r.max();
00285   out << ')';
00286   return out;
00287 }
00288 
00289 
00290 #endif // PREGION_H
00291 
00292 /***************************************************************************
00293  * $RCSfile: PRegion.h,v $   $Author: adelmann $
00294  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:32 $
00295  * IPPL_VERSION_ID: $Id: PRegion.h,v 1.1.1.1 2003/01/23 07:40:32 adelmann Exp $ 
00296  ***************************************************************************/

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