• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

storage/grid.h

Go to the documentation of this file.
00001 #ifndef LIBGEODECOMP_STORAGE_GRID_H
00002 #define LIBGEODECOMP_STORAGE_GRID_H
00003 
00004 #include <libflatarray/aligned_allocator.hpp>
00005 #include <libgeodecomp/geometry/coord.h>
00006 #include <libgeodecomp/geometry/coordbox.h>
00007 #include <libgeodecomp/geometry/region.h>
00008 #include <libgeodecomp/geometry/topologies.h>
00009 #include <libgeodecomp/storage/coordmap.h>
00010 #include <libgeodecomp/storage/gridbase.h>
00011 #include <libgeodecomp/storage/selector.h>
00012 
00013 // CodeGear's C++ compiler isn't compatible with boost::multi_array
00014 // (at least the version that ships with C++ Builder 2009)
00015 #ifndef __CODEGEARC__
00016 #include <boost/multi_array.hpp>
00017 #else
00018 #include <libgeodecomp/misc/supervector.h>
00019 #endif
00020 
00021 #include <boost/foreach.hpp>
00022 #include <iostream>
00023 
00024 namespace LibGeoDecomp {
00025 
00026 template<typename CELL_TYPE, typename GRID_TYPE>
00027 class CoordMap;
00028 
00029 namespace GridHelpers {
00030 
00031 template<int DIM>
00032 class FillCoordBox;
00033 
00034 template<>
00035 class FillCoordBox<1>
00036 {
00037 public:
00038     template<typename GRID, typename CELL>
00039     void operator()(const Coord<1>& origin, const Coord<1>& dim, GRID *grid, const CELL& cell)
00040     {
00041         CELL *cursor = &(*grid)[origin];
00042         std::fill(cursor, cursor + dim.x(), cell);
00043     }
00044 };
00045 
00046 template<>
00047 class FillCoordBox<2>
00048 {
00049 public:
00050     template<typename GRID, typename CELL>
00051     void operator()(const Coord<2>& origin, const Coord<2>& dim, GRID *grid, const CELL& cell)
00052     {
00053         int maxY = origin.y() + dim.y();
00054         Coord<2> c = origin;
00055         for (; c.y() < maxY; ++c.y()) {
00056             CELL *cursor = &(*grid)[c];
00057             std::fill(cursor, cursor + dim.x(), cell);
00058         }
00059     }
00060 };
00061 
00062 template<>
00063 class FillCoordBox<3>
00064 {
00065 public:
00066     template<typename GRID, typename CELL>
00067     void operator()(const Coord<3>& origin, const Coord<3>& dim, GRID *grid, const CELL& cell)
00068     {
00069         int maxY = origin.y() + dim.y();
00070         int maxZ = origin.z() + dim.z();
00071         Coord<3> c = origin;
00072 
00073         for (; c.z() < maxZ; ++c.z()) {
00074             for (c.y() = origin.y(); c.y() < maxY; ++c.y()) {
00075                 CELL *cursor = &(*grid)[c];
00076                 std::fill(cursor, cursor + dim.x(), cell);
00077             }
00078         }
00079     }
00080 };
00081 
00082 }
00083 
00087 template<typename CELL_TYPE, typename TOPOLOGY=Topologies::Cube<2>::Topology>
00088 class Grid : public GridBase<CELL_TYPE, TOPOLOGY::DIM>
00089 {
00090 public:
00091     friend class GridTest;
00092     friend class ParallelStripingSimulatorTest;
00093     const static int DIM = TOPOLOGY::DIM;
00094 
00095 #ifndef __CODEGEARC__
00096     typedef typename boost::detail::multi_array::sub_array<CELL_TYPE, DIM - 1> SliceRef;
00097     typedef typename boost::detail::multi_array::const_sub_array<CELL_TYPE, 1> ConstSliceRef;
00098     typedef typename boost::multi_array<
00099         // always align on cache line boundaries
00100         CELL_TYPE, DIM, LibFlatArray::aligned_allocator<CELL_TYPE, 64> > CellMatrix;
00101     typedef typename CellMatrix::index Index;
00102 #else
00103     typedef std::vector<CELL_TYPE>& SliceRef;
00104     typedef const std::vector<CELL_TYPE>& ConstSliceRef;
00105     typedef int Index;
00106 #endif
00107 
00108     typedef TOPOLOGY Topology;
00109     typedef CELL_TYPE Cell;
00110     typedef CoordMap<CELL_TYPE, Grid<CELL_TYPE, TOPOLOGY> > CoordMapType;
00111 
00112     explicit Grid(
00113         const Coord<DIM>& dim = Coord<DIM>(),
00114         const CELL_TYPE& defaultCell = CELL_TYPE(),
00115         const CELL_TYPE& edgeCell = CELL_TYPE()) :
00116         dimensions(dim),
00117         cellMatrix(dim.toExtents()),
00118         edgeCell(edgeCell)
00119     {
00120         CoordBox<DIM> box(Coord<DIM>(), dim);
00121         for (typename CoordBox<DIM>::StreakIterator i = box.beginStreak(); i != box.endStreak(); ++i) {
00122             Streak<DIM> s = *i;
00123             CELL_TYPE *start = &(*this)[s.origin];
00124             CELL_TYPE *end   = start + s.length();
00125             std::fill(start, end, defaultCell);
00126         }
00127     }
00128 
00129     explicit Grid(const GridBase<CELL_TYPE, DIM>& base) :
00130         dimensions(base.dimensions()),
00131         cellMatrix(base.dimensions().toExtents()),
00132         edgeCell(base.getEdge())
00133     {
00134         CoordBox<DIM> box = base.boundingBox();
00135         for (typename CoordBox<DIM>::Iterator i = box.begin(); i != box.end(); ++i) {
00136             set(*i - box.origin, base.get(*i));
00137         }
00138     }
00139 
00140     Grid& operator=(const Grid& other)
00141     {
00142         resize(other.getDimensions());
00143         std::copy(other.cellMatrix.begin(), other.cellMatrix.end(), cellMatrix.begin());
00144         edgeCell = other.edgeCell;
00145 
00146         return *this;
00147     }
00148 
00149     inline void resize(const Coord<DIM>& newDim)
00150     {
00151         // temporarly resize to 0-sized array to avoid having two
00152         // large arrays simultaneously allocated. somehow I feel
00153         // boost::multi_array::resize should be responsible for
00154         // this...
00155         Coord<DIM> tempDim;
00156         cellMatrix.resize(tempDim.toExtents());
00157         dimensions = newDim;
00158         cellMatrix.resize(newDim.toExtents());
00159     }
00160 
00165     inline CoordMapType getNeighborhood(const Coord<DIM>& center) const
00166     {
00167         return CoordMapType(center, this);
00168     }
00169 
00170     inline CELL_TYPE& getEdgeCell()
00171     {
00172         return edgeCell;
00173     }
00174 
00175     inline const CELL_TYPE& getEdgeCell() const
00176     {
00177         return edgeCell;
00178     }
00179 
00180     inline CELL_TYPE *baseAddress()
00181     {
00182         return &(*this)[Coord<DIM>()];
00183     }
00184 
00185     inline const CELL_TYPE *baseAddress() const
00186     {
00187         return &(*this)[Coord<DIM>()];
00188     }
00189 
00190     inline CELL_TYPE& operator[](const Coord<DIM>& coord)
00191     {
00192         return Topology::locate(*this, coord);
00193     }
00194 
00195     inline const CELL_TYPE& operator[](const Coord<DIM>& coord) const
00196     {
00197         return (const_cast<Grid&>(*this))[coord];
00198     }
00199 
00203     inline const ConstSliceRef operator[](const Index y) const
00204     {
00205         return cellMatrix[y];
00206     }
00207 
00211     inline SliceRef operator[](const Index y)
00212     {
00213         return cellMatrix[y];
00214     }
00215 
00216     inline bool operator==(const Grid& other) const
00217     {
00218         if (boundingBox() == CoordBox<DIM>() &&
00219             other.boundingBox() == CoordBox<DIM>()) {
00220             return true;
00221         }
00222 
00223         return
00224             (edgeCell   == other.edgeCell) &&
00225             (cellMatrix == other.cellMatrix);
00226     }
00227 
00228     inline bool operator==(const GridBase<CELL_TYPE, TOPOLOGY::DIM>& other) const
00229     {
00230         if (boundingBox() != other.boundingBox()) {
00231             return false;
00232         }
00233 
00234         if (edgeCell != other.getEdge()) {
00235             return false;
00236         }
00237 
00238         CoordBox<DIM> box = boundingBox();
00239         for (typename CoordBox<DIM>::Iterator i = box.begin(); i != box.end(); ++i) {
00240             if ((*this)[*i] != other.get(*i)) {
00241                 return false;
00242             }
00243         }
00244 
00245         return true;
00246     }
00247 
00248     inline bool operator!=(const Grid& other) const
00249     {
00250         return !(*this == other);
00251     }
00252 
00253     inline bool operator!=(const GridBase<CELL_TYPE, TOPOLOGY::DIM>& other) const
00254     {
00255         return !(*this == other);
00256     }
00257 
00258     virtual void set(const Coord<DIM>& coord, const CELL_TYPE& cell)
00259     {
00260         (*this)[coord] = cell;
00261     }
00262 
00263     virtual void set(const Streak<DIM>& streak, const CELL_TYPE *cells)
00264     {
00265         Coord<DIM> cursor = streak.origin;
00266         for (; cursor.x() < streak.endX; ++cursor.x()) {
00267             (*this)[cursor] = *cells;
00268             ++cells;
00269         }
00270     }
00271 
00272     virtual CELL_TYPE get(const Coord<DIM>& coord) const
00273     {
00274         return (*this)[coord];
00275     }
00276 
00277     virtual void get(const Streak<DIM>& streak, CELL_TYPE *cells) const
00278     {
00279         Coord<DIM> cursor = streak.origin;
00280         for (; cursor.x() < streak.endX; ++cursor.x()) {
00281             *cells = (*this)[cursor];
00282             ++cells;
00283         }
00284     }
00285 
00286     virtual void setEdge(const CELL_TYPE& cell)
00287     {
00288         getEdgeCell() = cell;
00289     }
00290 
00291     virtual const CELL_TYPE& getEdge() const
00292     {
00293         return getEdgeCell();
00294     }
00295 
00296     void fill(const CoordBox<DIM>& box, const CELL_TYPE& cell)
00297     {
00298         GridHelpers::FillCoordBox<DIM>()(box.origin, box.dimensions, this, cell);
00299     }
00300 
00301     inline const Coord<DIM>& getDimensions() const
00302     {
00303         return dimensions;
00304     }
00305 
00306     inline std::string toString() const
00307     {
00308         std::ostringstream message;
00309         message << "Grid<" << DIM << ">(\n"
00310                 << "boundingBox: " << boundingBox()  << "\n"
00311                 << "edgeCell:\n"
00312                 << edgeCell << "\n";
00313 
00314         CoordBox<DIM> box = boundingBox();
00315         for (typename CoordBox<DIM>::Iterator i = box.begin(); i != box.end(); ++i) {
00316             message << "Coord" << *i << ":\n" << (*this)[*i] << "\n";
00317         }
00318 
00319         message << ")";
00320         return message.str();
00321     }
00322 
00323     virtual CoordBox<DIM> boundingBox() const
00324     {
00325         return CoordBox<DIM>(Coord<DIM>(), dimensions);
00326     }
00327 
00328 protected:
00329     void saveMemberImplementation(
00330         char *target, const Selector<CELL_TYPE>& selector, const Region<DIM>& region) const
00331     {
00332         for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
00333             selector.copyMemberOut(&(*this)[i->origin], target, i->length());
00334             target += selector.sizeOfExternal() * i->length();
00335         }
00336     }
00337 
00338     void loadMemberImplementation(
00339         const char *source, const Selector<CELL_TYPE>& selector, const Region<DIM>& region)
00340     {
00341         for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
00342             selector.copyMemberIn(source, &(*this)[i->origin], i->length());
00343             source += selector.sizeOfExternal() * i->length();
00344         }
00345     }
00346 
00347 private:
00348     Coord<DIM> dimensions;
00349     CellMatrix cellMatrix;
00350     CELL_TYPE edgeCell;
00351 };
00352 
00353 template<typename _CharT, typename _Traits, typename _CellT, typename _TopologyT>
00354 std::basic_ostream<_CharT, _Traits>&
00355 operator<<(std::basic_ostream<_CharT, _Traits>& __os,
00356            const Grid<_CellT, _TopologyT>& grid)
00357 {
00358     __os << grid.toString();
00359     return __os;
00360 }
00361 
00362 }
00363 
00364 #endif

Generated on Thu Jan 8 2015 01:34:44 for LibGeoDecomp by  doxygen 1.7.1