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
00014
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
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
00152
00153
00154
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