1 #ifndef LIBGEODECOMP_STORAGE_DISPLACEDGRID_H
2 #define LIBGEODECOMP_STORAGE_DISPLACEDGRID_H
3 
4 #include <libgeodecomp/geometry/coordbox.h>
5 #include <libgeodecomp/geometry/region.h>
6 #include <libgeodecomp/storage/grid.h>
7 
8 namespace LibGeoDecomp {
9 
10 /**
11  * A grid whose origin has been shiftet by a certain offset. If
12  * TOPOLOGICALLY_CORRECT is set to true, the coordinates will be
13  * normalized according to the given topology and some superordinate
14  * dimension (see topologicalDimensions()) before using them for
15  * access. Useful for writing topology agnostic code that should work
16  * an a torus, too.
17  */
18 template<typename CELL_TYPE,
19          typename TOPOLOGY=Topologies::Cube<2>::Topology,
20          bool TOPOLOGICALLY_CORRECT=false>
21 class DisplacedGrid : public GridBase<CELL_TYPE, TOPOLOGY::DIM>
22 {
23 public:
24     const static int DIM = TOPOLOGY::DIM;
25 
26     typedef CELL_TYPE Cell;
27     typedef TOPOLOGY Topology;
28     typedef typename boost::multi_array<CELL_TYPE, DIM>::index Index;
29     typedef Grid<CELL_TYPE, TOPOLOGY> Delegate;
30     typedef CoordMap<CELL_TYPE, Delegate> CoordMapType;
31 
32     explicit DisplacedGrid(
33         const CoordBox<DIM>& box = CoordBox<DIM>(),
34         const CELL_TYPE& defaultCell = CELL_TYPE(),
35         const CELL_TYPE& edgeCell = CELL_TYPE(),
36         const Coord<DIM>& topologicalDimensions = Coord<DIM>()) :
37         delegate(box.dimensions, defaultCell, edgeCell),
38         origin(box.origin),
39         topoDimensions(topologicalDimensions)
40     {}
41 
42     explicit DisplacedGrid(
43         const Delegate& grid,
44         const Coord<DIM>& origin=Coord<DIM>()) :
delegate(grid)45         delegate(grid),
46         origin(origin)
47     {}
48 
topologicalDimensions()49     inline const Coord<DIM>& topologicalDimensions() const
50     {
51         return topoDimensions;
52     }
53 
topologicalDimensions()54     inline Coord<DIM>& topologicalDimensions()
55     {
56         return topoDimensions;
57     }
58 
baseAddress()59     inline CELL_TYPE *baseAddress()
60     {
61         return delegate.baseAddress();
62     }
63 
baseAddress()64     inline const CELL_TYPE *baseAddress() const
65     {
66         return delegate.baseAddress();
67     }
68 
getOrigin()69     inline const Coord<DIM>& getOrigin() const
70     {
71         return origin;
72     }
73 
getEdgeCell()74     inline const CELL_TYPE& getEdgeCell() const
75     {
76         return delegate.getEdgeCell();
77     }
78 
getEdgeCell()79     inline CELL_TYPE& getEdgeCell()
80     {
81         return delegate.getEdgeCell();
82     }
83 
setOrigin(const Coord<DIM> & newOrigin)84     inline void setOrigin(const Coord<DIM>& newOrigin)
85     {
86         origin = newOrigin;
87     }
88 
resize(const CoordBox<DIM> & box)89     inline void resize(const CoordBox<DIM>& box)
90     {
91         delegate.resize(box.dimensions);
92         origin = box.origin;
93     }
94 
95     inline CELL_TYPE& operator[](const Coord<DIM>& absoluteCoord)
96     {
97         Coord<DIM> relativeCoord = absoluteCoord - origin;
98         if (TOPOLOGICALLY_CORRECT) {
99             relativeCoord = Topology::normalize(relativeCoord, topoDimensions);
100         }
101         return delegate[relativeCoord];
102     }
103 
104     inline const CELL_TYPE& operator[](const Coord<DIM>& absoluteCoord) const
105     {
106         return (const_cast<DisplacedGrid&>(*this))[absoluteCoord];
107     }
108 
set(const Coord<DIM> & coord,const CELL_TYPE & cell)109     virtual void set(const Coord<DIM>& coord, const CELL_TYPE& cell)
110     {
111         (*this)[coord] = cell;
112     }
113 
set(const Streak<DIM> & streak,const CELL_TYPE * cells)114     virtual void set(const Streak<DIM>& streak, const CELL_TYPE *cells)
115     {
116 	delegate.set(Streak<DIM>(streak.origin - origin,
117 				 streak.endX - origin.x()),
118 		     cells);
119     }
120 
get(const Coord<DIM> & coord)121     virtual CELL_TYPE get(const Coord<DIM>& coord) const
122     {
123         return (*this)[coord];
124     }
125 
get(const Streak<DIM> & streak,CELL_TYPE * cells)126     virtual void get(const Streak<DIM>& streak, CELL_TYPE *cells) const
127     {
128 	delegate.get(Streak<DIM>(streak.origin - origin,
129 				 streak.endX - origin.x()),
130 		     cells);
131     }
132 
setEdge(const CELL_TYPE & cell)133     virtual void setEdge(const CELL_TYPE& cell)
134     {
135         getEdgeCell() = cell;
136     }
137 
getEdge()138     virtual const CELL_TYPE& getEdge() const
139     {
140         return getEdgeCell();
141     }
142 
fill(const CoordBox<DIM> & box,const CELL_TYPE & cell)143     void fill(const CoordBox<DIM>& box, const CELL_TYPE& cell)
144     {
145         delegate.fill(CoordBox<DIM>(box.origin - origin, box.dimensions), cell);
146     }
147 
paste(const GridBase<CELL_TYPE,DIM> & grid,const Region<DIM> & region)148     inline void paste(const GridBase<CELL_TYPE, DIM>& grid, const Region<DIM>& region)
149     {
150         for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
151             for (Coord<DIM> c = i->origin; c.x() < i->endX; ++c.x()) {
152                 (*this)[c] = grid.get(c);
153             }
154         }
155     }
156 
getDimensions()157     inline const Coord<DIM>& getDimensions() const
158     {
159         return delegate.getDimensions();
160     }
161 
boundingBox()162     virtual CoordBox<DIM> boundingBox() const
163     {
164         return CoordBox<DIM>(origin, delegate.getDimensions());
165     }
166 
getNeighborhood(const Coord<DIM> & center)167     inline CoordMapType getNeighborhood(const Coord<DIM>& center) const
168     {
169         Coord<DIM> relativeCoord = center - origin;
170         if (TOPOLOGICALLY_CORRECT) {
171             relativeCoord = Topology::normalize(relativeCoord, topoDimensions);
172         }
173         return CoordMapType(relativeCoord, &delegate);
174     }
175 
vanillaGrid()176     inline const Delegate *vanillaGrid() const
177     {
178         return &delegate;
179     }
180 
vanillaGrid()181     inline Delegate *vanillaGrid()
182     {
183         return &delegate;
184     }
185 
toString()186     inline std::string toString() const
187     {
188         std::ostringstream message;
189         message << "DisplacedGrid<" << DIM << ">(\n"
190                 << "  origin: " << origin << "\n"
191                 << "  delegate:\n"
192                 << delegate
193                 << ")";
194         return message.str();
195     }
196 
197 protected:
saveMemberImplementation(char * target,const Selector<CELL_TYPE> & selector,const Region<DIM> & region)198     void saveMemberImplementation(
199         char *target, const Selector<CELL_TYPE>& selector, const Region<DIM>& region) const
200     {
201         for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
202             selector.copyMemberOut(&(*this)[i->origin], target, i->length());
203             target += selector.sizeOfExternal() * i->length();
204         }
205     }
206 
loadMemberImplementation(const char * source,const Selector<CELL_TYPE> & selector,const Region<DIM> & region)207     void loadMemberImplementation(
208         const char *source, const Selector<CELL_TYPE>& selector, const Region<DIM>& region)
209     {
210         for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
211             selector.copyMemberIn(source, &(*this)[i->origin], i->length());
212             source += selector.sizeOfExternal() * i->length();
213         }
214     }
215 
216 
217 private:
218     Delegate delegate;
219     Coord<DIM> origin;
220     Coord<DIM> topoDimensions;
221 };
222 
223 }
224 
225 template<typename _CharT, typename _Traits, typename _CellT, typename _Topology, bool _Correctness>
226 std::basic_ostream<_CharT, _Traits>&
227 operator<<(std::basic_ostream<_CharT, _Traits>& __os,
228            const LibGeoDecomp::DisplacedGrid<_CellT, _Topology, _Correctness>& grid)
229 {
230     __os << grid.toString();
231     return __os;
232 }
233 
234 #endif
235