vtf-logo

IndexRange.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00008 #if !defined(__ads_array_IndexRange_h__)
00009 #define __ads_array_IndexRange_h__
00010 
00011 #include "FixedArray.h"
00012 
00013 #include "../iterator/TrivialOutputIterator.h"
00014 #include "../utility/string.h"
00015 
00016 #include <iostream>
00017 #include <string>
00018 #include <sstream>
00019 
00020 BEGIN_NAMESPACE_ADS
00021 
00023 
00036 template<int N, typename T = int>
00037 class IndexRange {
00038   //
00039   // Public types.
00040   //
00041 
00042 public:
00043 
00045   typedef T index_type;
00047   typedef FixedArray<N,index_type> multi_index_type;
00048 
00049   //
00050   // Member data
00051   //
00052 
00053 private:
00054 
00055   multi_index_type _lbounds, _ubounds;
00056 
00057 public:
00058 
00059   //--------------------------------------------------------------------------
00061   // @{
00062 
00064   IndexRange() :
00065     _lbounds(index_type(0)),
00066     _ubounds(index_type(0))
00067   {}
00068 
00070   IndexRange(const index_type ubound) :
00071     _lbounds(index_type(0)),
00072     _ubounds(ubound) {
00073     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00074   }
00075 
00077   IndexRange(const multi_index_type& ubounds) :
00078     _lbounds(index_type(0)),
00079     _ubounds(ubounds)
00080   {}
00081 
00083   IndexRange(const multi_index_type& lbounds, 
00084              const multi_index_type& ubounds) :
00085     _lbounds(lbounds),
00086     _ubounds(ubounds)
00087   {}
00088 
00090   IndexRange(const index_type lb0, const index_type ub0) :
00091     _lbounds(lb0),
00092     _ubounds(ub0) {
00093     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00094   }
00095 
00097   IndexRange(const index_type lb0, const index_type lb1, 
00098               const index_type ub0, const index_type ub1) :
00099     _lbounds(lb0, lb1),
00100     _ubounds(ub0, ub1) {
00101     LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00102   }
00103 
00105   IndexRange(const index_type lb0, 
00106               const index_type lb1, 
00107               const index_type lb2, 
00108               const index_type ub0,
00109               const index_type ub1,
00110               const index_type ub2) :
00111     _lbounds(lb0, lb1, lb2),
00112     _ubounds(ub0, ub1, ub2) {
00113     LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00114   }
00115 
00117   IndexRange(const IndexRange& x) :
00118     _lbounds(x._lbounds),
00119     _ubounds(x._ubounds)
00120   {}
00121 
00123   ~IndexRange()
00124   {}
00125 
00126   // @}
00127   //--------------------------------------------------------------------------
00129   // @{
00130 
00132   IndexRange& 
00133   operator=(const IndexRange& other) {
00134     if (&other != this) {
00135       _lbounds = other._lbounds;
00136       _ubounds = other._ubounds;
00137     }
00138     return *this;
00139   }
00140 
00141   // @}
00142   //--------------------------------------------------------------------------
00144   // @{
00145 
00146   void
00147   swap(IndexRange& other) {
00148     _lbounds.swap(other._lbounds);
00149     _ubounds.swap(other._ubounds);
00150   }
00151 
00152   // @}
00153   //--------------------------------------------------------------------------
00155   // @{
00156 
00158   static
00159   int
00160   dimension() {
00161     return N;
00162   }
00163 
00164   // @}
00165   //--------------------------------------------------------------------------
00167   // @{
00168 
00170   const multi_index_type&
00171   lbounds() const {     
00172     return _lbounds;
00173   }
00174 
00176   const multi_index_type&
00177   ubounds() const {     
00178     return _ubounds;
00179   }
00180 
00182   index_type
00183   lbound(const index_type i) const {    
00184     return _lbounds[i];
00185   }
00186 
00188   index_type
00189   ubound(const index_type i) const {    
00190     return _ubounds[i];
00191   }
00192 
00194 
00197   multi_index_type 
00198   extents() const {     
00199     return _ubounds - _lbounds;
00200   }
00201 
00203   index_type 
00204   content() const {     
00205     return computeProduct(extents());
00206   }
00207 
00209   bool
00210   empty() const {
00211     for (int i = 0; i != N; ++i) {
00212       if (_ubounds[i] <= _lbounds[i]) {
00213         return true;
00214       }
00215     }
00216     return false;
00217   }
00218 
00220   bool
00221   is_in(const multi_index_type& x) const {
00222     for (int i = 0; i != N; ++i) {
00223       if (x[i] < _lbounds[i] || _ubounds[i] <= x[i]) {
00224         return false;
00225       }
00226     }
00227     return true;
00228   }
00229 
00231 
00234   bool
00235   is_in(const index_type x) const {
00236     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00237     return (_lbounds[0] <= x && x < _ubounds[0]);
00238   }
00239 
00241 
00244   bool
00245   is_in(const index_type x, const index_type y) const {
00246     LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00247     return (_lbounds[0] <= x && x < _ubounds[0] &&
00248             _lbounds[1] <= y && y < _ubounds[1]);
00249   }
00250 
00252 
00255   bool
00256   is_in(const index_type x, const index_type y, const index_type z) const {
00257     LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00258     return (_lbounds[0] <= x && x < _ubounds[0] &&
00259              _lbounds[1] <= y && y < _ubounds[1] &&
00260              _lbounds[2] <= z && z < _ubounds[2]);
00261   }
00262 
00263   // @}
00264   //--------------------------------------------------------------------------
00266   // @{
00267 
00268 
00270   index_type 
00271   lbound() const {
00272     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00273     return lbounds()[0];
00274   }
00275 
00277   index_type 
00278   ubound() const {      
00279     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00280     return ubounds()[0];
00281   }
00282 
00284 
00287   index_type 
00288   extent() const {      
00289     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00290     return ubound() - lbound();
00291   }
00292 
00293   // @}
00294   //--------------------------------------------------------------------------
00296   // @{
00297 
00299   void
00300   set_lbounds(const multi_index_type& lbounds) {        
00301     _lbounds = lbounds;
00302   }
00303 
00305   void
00306   set_ubounds(const multi_index_type& ubounds) {        
00307     _ubounds = ubounds;
00308   }
00309 
00311 
00314   void
00315   set_lbounds(const index_type lb0) {   
00316     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00317     _lbounds[0] = lb0;
00318   }
00319 
00321 
00324   void
00325   set_ubounds(const index_type ub0) {   
00326     LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00327     _ubounds[0] = ub0;
00328   }
00329 
00331 
00334   void
00335   set_lbounds(const index_type lb0, const index_type lb1) {     
00336     LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00337     _lbounds[0] = lb0;
00338     _lbounds[1] = lb1;
00339   }
00340 
00342 
00345   void
00346   set_ubounds(const index_type ub0, const index_type ub1) {     
00347     LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00348     _ubounds[0] = ub0;
00349     _ubounds[1] = ub1;
00350   }
00351 
00353 
00356   void
00357   set_lbounds(const index_type lb0, const index_type lb1, 
00358               const index_type lb2) {   
00359     LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00360     _lbounds[0] = lb0;
00361     _lbounds[1] = lb1;
00362     _lbounds[2] = lb2;
00363   }
00364 
00366 
00369   void
00370   set_ubounds(const index_type ub0, const index_type ub1, 
00371               const index_type ub2) {   
00372     LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00373     _ubounds[0] = ub0;
00374     _ubounds[1] = ub1;
00375     _ubounds[2] = ub2;
00376   }
00377 
00378   // @}
00379   //--------------------------------------------------------------------------
00381   // @{
00382 
00384   void
00385   set_lbound(const index_type lbound) {
00386     set_lbounds(lbound);
00387   }
00388 
00390   void
00391   set_ubound(const index_type ubound) {
00392     set_ubounds(ubound);
00393   }
00394 
00395   // @}
00396   //--------------------------------------------------------------------------
00398 
00399 
00400   bool
00401   operator==(const IndexRange& x) const {
00402     return _lbounds == x.lbounds() && _ubounds == x.ubounds();
00403   }
00404 
00405   // @}
00406   //--------------------------------------------------------------------------
00408 
00409 
00411   void
00412   put(std::ostream& out) const {
00413     out << _lbounds << " " << _ubounds;
00414   }
00415 
00417 
00421   void
00422   get(std::istream& in) {
00423     // Get a line from the input stream.  We assume that the index range 
00424     // must be written on one line.
00425     std::string line;
00426     // I loop here to skip blank lines.
00427     do {
00428       // CONTINUE: I should handle lines with only white space.
00429       std::getline(in, line);
00430     } while (line.empty() && in.good());
00431     // Count the numbers in the line.
00432     const int Size = ads::split(line, " ", 
00433                                 ads::constructTrivialOutputIterator());
00434     // If they specified extents.
00435     if (Size == N) {
00436       // Set the lower bounds to zero.
00437       _lbounds = 0;
00438       // Read the extents as upper bounds.
00439       std::istringstream stream(line);
00440       stream >> _ubounds;
00441     }
00442     // If they specified lower and upper bounds.
00443     else if (Size == 2 * N) {
00444       // Read the lower and upper bounds.
00445       std::istringstream stream(line);
00446       stream >> _lbounds >> _ubounds;
00447     }
00448     // Otherwise, it is an error.
00449     else {
00450       std::cerr 
00451         << "Error in reading an IndexRange:\n"
00452         << "Wrong number of numbers.  We expected either " << N
00453         << " or " << 2 * N << "\n"
00454         << "but got " << Size << "\n";
00455       assert(false);
00456     }
00457   }
00458 
00460   void
00461   write(std::ostream& out) const {
00462     _lbounds.write(out);
00463     _ubounds.write(out);
00464   }
00465 
00467   void
00468   read(std::istream& in) {
00469     _lbounds.read(in);
00470     _ubounds.read(in);
00471   }
00472 
00474 };
00475 
00476 //
00477 // Equality Operators
00478 //
00479 
00480 // CONTINUE: I don't think that I need this.
00481 #if 0
00483 
00484 template<int N, typename T>
00485 inline
00486 bool
00487 operator==(const IndexRange<N,T>& a, const IndexRange<N,T>& b) {
00488   return a.is_equal(b);
00489 }
00490 #endif
00491 
00493 
00494 template<int N, typename T>
00495 inline
00496 bool
00497 operator!=(const IndexRange<N,T>& a, const IndexRange<N,T>& b) {
00498   return !(a == b);
00499 }
00500 
00501 
00502 //
00503 // File I/O
00504 //
00505 
00507 
00510 template<int N, typename T>
00511 inline
00512 std::ostream&
00513 operator<<(std::ostream& out, const IndexRange<N,T>& x) {
00514   x.put(out);
00515   return out;
00516 }
00517 
00519 
00522 template<int N, typename T>
00523 inline
00524 std::istream&
00525 operator>>(std::istream& in, IndexRange<N,T>& x) {
00526   x.get(in);
00527   return in;
00528 }
00529 
00530 //
00531 // Mathematical operations.
00532 //
00533 
00535 
00536 template<int N, typename T>
00537 inline
00538 void
00539 compute_intersection(const IndexRange<N,T>& x, const IndexRange<N,T>& y, 
00540                      IndexRange<N,T>& result) {
00541   typename IndexRange<N,T>::multi_index_type lower, upper;
00542   for (int n = 0; n != N; ++n) {
00543     lower[n] = std::max(x.lbound(n), y.lbound(n));
00544     upper[n] = std::min(x.ubound(n), y.ubound(n));
00545     // An empty range has the same lower and upper bounds.
00546     upper[n] = std::max(lower[n], upper[n]);
00547   }
00548   result.set_lbounds(lower);
00549   result.set_ubounds(upper);
00550 }
00551 
00552 
00553 END_NAMESPACE_ADS
00554 
00555 #endif

Generated on Fri Aug 24 12:55:25 2007 for Algorithms and Data Structures Package by  doxygen 1.4.7