1 /*
  2  *   Copyright (c) 2007, Michael Lehn
  3  *
  4  *   All rights reserved.
  5  *
  6  *   Redistribution and use in source and binary forms, with or without
  7  *   modification, are permitted provided that the following conditions
  8  *   are met:
  9  *
 10  *   1) Redistributions of source code must retain the above copyright
 11  *      notice, this list of conditions and the following disclaimer.
 12  *   2) Redistributions in binary form must reproduce the above copyright
 13  *      notice, this list of conditions and the following disclaimer in
 14  *      the documentation and/or other materials provided with the
 15  *      distribution.
 16  *   3) Neither the name of the FLENS development group nor the names of
 17  *      its contributors may be used to endorse or promote products derived
 18  *      from this software without specific prior written permission.
 19  *
 20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 31  */
 32 
 33 #ifndef FLENS_STORAGE_FULLSTORAGE_CONSTFULLSTORAGEVIEW_TCC
 34 #define FLENS_STORAGE_FULLSTORAGE_CONSTFULLSTORAGEVIEW_TCC 1
 35 
 36 #include <flens/typedefs.h>
 37 
 38 namespace flens {
 39 
 40 template <typename T, StorageOrder Order, typename I, typename A>
 41 ConstFullStorageView<T, Order, I, A>::ConstFullStorageView(
 42                                         IndexType numRows, IndexType numCols,
 43                                         const ElementType *data,
 44                                         IndexType leadingDimension,
 45                                         IndexType firstRow,
 46                                         IndexType firstCol,
 47                                         const Allocator &allocator)
 48     : _data(data), _allocator(allocator), _numRows(numRows), _numCols(numCols),
 49       _leadingDimension(leadingDimension), _firstRow(0), _firstCol(0)
 50 {
 51     ASSERT(_numRows>=0);
 52     ASSERT(_numCols>=0);
 53     changeIndexBase(firstRow, firstCol);
 54 }
 55 
 56 template <typename T, StorageOrder Order, typename I, typename A>
 57 template <typename ARRAY>
 58 ConstFullStorageView<T, Order, I, A>::ConstFullStorageView(
 59                                        IndexType numRows, IndexType numCols,
 60                                        ARRAY &array, IndexType leadingDimension,
 61                                        IndexType firstRow, IndexType firstCol,
 62                                        const Allocator &allocator)
 63     : _data(array.data()),
 64       _allocator(allocator),
 65       _numRows(numRows), _numCols(numCols),
 66       _leadingDimension(leadingDimension),
 67       _firstRow(0), _firstCol(0)
 68 {
 69     ASSERT(_numRows>=0);
 70     ASSERT(_numCols>=0);
 71     ASSERT(numRows*numCols<=array.length());
 72 
 73     changeIndexBase(firstRow, firstCol);
 74 }
 75 
 76 template <typename T, StorageOrder Order, typename I, typename A>
 77 ConstFullStorageView<T, Order, I, A>::ConstFullStorageView(
 78                                                 const ConstFullStorageView &rhs)
 79     : _data(rhs._data),
 80       _allocator(rhs._allocator),
 81       _numRows(rhs._numRows), _numCols(rhs._numCols),
 82       _leadingDimension(rhs._leadingDimension),
 83       _firstRow(rhs._firstRow), _firstCol(rhs._firstCol)
 84 {
 85 }
 86 
 87 template <typename T, StorageOrder Order, typename I, typename A>
 88 template <typename RHS>
 89 ConstFullStorageView<T, Order, I, A>::ConstFullStorageView(const RHS &rhs)
 90     : _data(rhs.data()),
 91       _allocator(rhs.allocator()),
 92       _numRows(rhs.numRows()), _numCols(rhs.numCols()),
 93       _leadingDimension(rhs.leadingDimension()),
 94       _firstRow(0), _firstCol(0)
 95 {
 96     changeIndexBase(rhs.firstRow(), rhs.firstCol());
 97 }
 98 
 99 template <typename T, StorageOrder Order, typename I, typename A>
100 ConstFullStorageView<T, Order, I, A>::~ConstFullStorageView()
101 {
102 }
103 
104 //-- operators -----------------------------------------------------------------
105 
106 template <typename T, StorageOrder Order, typename I, typename A>
107 const typename ConstFullStorageView<T, Order, I, A>::ElementType &
108 ConstFullStorageView<T, Order, I, A>::operator()(IndexType row,
109                                                  IndexType col) const
110 {
111     ASSERT(row>=_firstRow);
112     ASSERT(row<_firstRow+_numRows);
113     ASSERT(col>=_firstCol);
114     ASSERT(col<_firstCol+_numCols);
115 
116     if (Order==ColMajor) {
117         return _data[col*_leadingDimension+row];
118     }
119     return _data[row*_leadingDimension+col];
120 }
121 
122 //-- methods -------------------------------------------------------------------
123 
124 template <typename T, StorageOrder Order, typename I, typename A>
125 typename ConstFullStorageView<T, Order, I, A>::IndexType
126 ConstFullStorageView<T, Order, I, A>::firstRow() const
127 {
128     return _firstRow;
129 }
130 
131 template <typename T, StorageOrder Order, typename I, typename A>
132 typename ConstFullStorageView<T, Order, I, A>::IndexType
133 ConstFullStorageView<T, Order, I, A>::firstCol() const
134 {
135     return _firstCol;
136 }
137 
138 template <typename T, StorageOrder Order, typename I, typename A>
139 typename ConstFullStorageView<T, Order, I, A>::IndexType
140 ConstFullStorageView<T, Order, I, A>::lastRow() const
141 {
142     return _firstRow+_numRows-1;
143 }
144 
145 template <typename T, StorageOrder Order, typename I, typename A>
146 typename ConstFullStorageView<T, Order, I, A>::IndexType
147 ConstFullStorageView<T, Order, I, A>::lastCol() const
148 {
149     return _firstCol+_numCols-1;
150 }
151 
152 template <typename T, StorageOrder Order, typename I, typename A>
153 typename ConstFullStorageView<T, Order, I, A>::IndexType
154 ConstFullStorageView<T, Order, I, A>::numRows() const
155 {
156     return _numRows;
157 }
158 
159 template <typename T, StorageOrder Order, typename I, typename A>
160 typename ConstFullStorageView<T, Order, I, A>::IndexType
161 ConstFullStorageView<T, Order, I, A>::numCols() const
162 {
163     return _numCols;
164 }
165 
166 template <typename T, StorageOrder Order, typename I, typename A>
167 typename ConstFullStorageView<T, Order, I, A>::IndexType
168 ConstFullStorageView<T, Order, I, A>::leadingDimension() const
169 {
170     return _leadingDimension;
171 }
172 
173 template <typename T, StorageOrder Order, typename I, typename A>
174 typename ConstFullStorageView<T, Order, I, A>::IndexType
175 ConstFullStorageView<T, Order, I, A>::strideRow() const
176 {
177     return (Order==ColMajor) ? 1
178                              : leadingDimension();
179 }
180 
181 template <typename T, StorageOrder Order, typename I, typename A>
182 typename ConstFullStorageView<T, Order, I, A>::IndexType
183 ConstFullStorageView<T, Order, I, A>::strideCol() const
184 {
185     return (Order==ColMajor) ? leadingDimension()
186                              : 1;
187 }
188 
189 template <typename T, StorageOrder Order, typename I, typename A>
190 const typename ConstFullStorageView<T, Order, I, A>::ElementType *
191 ConstFullStorageView<T, Order, I, A>::data() const
192 {
193 #   ifndef NDEBUG
194     if ((numRows()==0) || numCols()==0) {
195         return 0;
196     }
197 #   endif
198 
199     return &(this->operator()(_firstRow, _firstCol));
200 }
201 
202 template <typename T, StorageOrder Order, typename I, typename A>
203 const typename ConstFullStorageView<T, Order, I, A>::Allocator &
204 ConstFullStorageView<T, Order, I, A>::allocator() const
205 {
206     return _allocator;
207 }
208 
209 template <typename T, StorageOrder Order, typename I, typename A>
210 void
211 ConstFullStorageView<T, Order, I, A>::changeIndexBase(IndexType firstRow,
212                                                       IndexType firstCol)
213 {
214     if (Order==RowMajor) {
215         _data = data() - (firstRow*leadingDimension() + firstCol);
216     }
217     if (Order==ColMajor) {
218         _data = data() - (firstCol*leadingDimension() + firstRow);
219     }
220     _firstRow = firstRow;
221     _firstCol = firstCol;
222 }
223 
224 /// view of fullstorage scheme as an array
225 template <typename T, StorageOrder Order, typename I, typename A>
226 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
227 ConstFullStorageView<T, Order, I, A>::arrayView(IndexType firstViewIndex) const
228 {
229 #   ifndef NDEBUG
230     if (order==ColMajor) {
231         ASSERT(numRows()==leadingDimension());
232     } else {
233         ASSERT(numCols()==leadingDimension());
234     }
235 #   endif
236 
237     return ConstArrayView(numCols()*numRows(),
238                           data(),
239                           IndexType(1),
240                           firstViewIndex,
241                           allocator());
242 }
243 
244 // view of rectangular part
245 template <typename T, StorageOrder Order, typename I, typename A>
246 const ConstFullStorageView<T, Order, I, A>
247 ConstFullStorageView<T, Order, I, A>::view(IndexType fromRow, IndexType fromCol,
248                                            IndexType toRow, IndexType toCol,
249                                            IndexType firstViewRow,
250                                            IndexType firstViewCol) const
251 {
252     const IndexType numRows = toRow-fromRow+1;
253     const IndexType numCols = toCol-fromCol+1;
254 
255 #   ifndef NDEBUG
256     // prevent an out-of-bound assertion in case a view is empty anyway
257     if ((numRows==0) || (numCols==0)) {
258         return ConstView(numRows, numCols, 0, leadingDimension(),
259                          firstViewRow, firstViewCol, allocator());
260 
261     }
262 #   endif
263 
264     ASSERT(fromRow>=firstRow());
265     ASSERT(fromRow<=toRow);
266     ASSERT(toRow<=lastRow());
267 
268     ASSERT(fromCol>=firstCol());
269     ASSERT(fromCol<=toCol);
270     ASSERT(toCol<=lastCol());
271 
272     return ConstView(numRows,                              // # rows
273                      numCols,                              // # cols
274                      &(this->operator()(fromRow, fromCol)),// data
275                      leadingDimension(),                   // leading dimension
276                      firstViewRow,                         // firstRow
277                      firstViewCol,                         // firstCol
278                      allocator());                         // allocator
279 }
280 
281 // view of single row
282 template <typename T, StorageOrder Order, typename I, typename A>
283 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
284 ConstFullStorageView<T, Order, I, A>::viewRow(IndexType row,
285                                               IndexType firstViewIndex) const
286 {
287 #   ifndef NDEBUG
288     // prevent an out-of-bound assertion in case a view is empty anyway
289     if (numCols()==0) {
290         row = this->firstRow();
291     }
292 #   endif
293 
294     ASSERT(row>=firstRow());
295     ASSERT(row<=lastRow());
296 
297     return ConstArrayView(numCols(),
298                           &(this->operator()(row, _firstCol)),
299                           strideCol(),
300                           firstViewIndex,
301                           allocator());
302 }
303 
304 template <typename T, StorageOrder Order, typename I, typename A>
305 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
306 ConstFullStorageView<T, Order, I, A>::viewRow(IndexType row,
307                                               IndexType firstCol,
308                                               IndexType lastCol,
309                                               IndexType firstViewIndex) const
310 {
311     const IndexType length = lastCol-firstCol+1;
312 
313 #   ifndef NDEBUG
314     // prevent an out-of-bound assertion in case a view is empty anyway
315     if (length==0) {
316         row =       firstRow();
317         firstCol =  this->firstCol();
318     }
319 #   endif
320 
321     ASSERT(row>=firstRow());
322     ASSERT(row<=lastRow());
323 
324     return ConstArrayView(length,
325                           &(this->operator()(row, firstCol)),
326                           strideCol(),
327                           firstViewIndex,
328                           allocator());
329 }
330 
331 // view of single columns
332 template <typename T, StorageOrder Order, typename I, typename A>
333 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
334 ConstFullStorageView<T, Order, I, A>::viewCol(IndexType col,
335                                               IndexType firstViewIndex) const
336 {
337 #   ifndef NDEBUG
338     // prevent an out-of-bound assertion in case a view is empty anyway
339     if (numRows()==0) {
340         col = this->firstCol();
341     }
342 #   endif
343 
344     ASSERT(col>=firstCol());
345     ASSERT(col<=lastCol());
346 
347     return ConstArrayView(numRows(),
348                           &(this->operator()(_firstRow, col)),
349                           strideRow(),
350                           firstViewIndex,
351                           allocator());
352 }
353 
354 template <typename T, StorageOrder Order, typename I, typename A>
355 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
356 ConstFullStorageView<T, Order, I, A>::viewCol(IndexType firstRow,
357                                               IndexType lastRow,
358                                               IndexType col,
359                                               IndexType firstViewIndex) const
360 {
361     const IndexType length = lastRow-firstRow+1;
362 
363 #   ifndef NDEBUG
364     // prevent an out-of-bound assertion in case a view is empty anyway
365     if (length==0) {
366         firstRow =  this->firstRow();
367         col =       firstCol();
368     }
369 #   endif
370 
371     ASSERT(col>=firstCol());
372     ASSERT(col<=lastCol());
373 
374     return ConstArrayView(length,
375                           &(this->operator()(firstRow, col)),
376                           strideRow(),
377                           firstViewIndex,
378                           allocator());
379 }
380 
381 // view of d-th diagonal
382 template <typename T, StorageOrder Order, typename I, typename A>
383 const typename ConstFullStorageView<T, Order, I, A>::ConstArrayView
384 ConstFullStorageView<T, Order, I, A>::viewDiag(IndexType d,
385                                                IndexType firstViewIndex) const
386 {
387     IndexType _row = (d>0) ? 0 : -d;
388     IndexType _col = (d>0) ? d :  0;
389 
390     IndexType row = firstRow() + _row;
391     IndexType col = firstCol() + _col;
392 
393     return ConstArrayView(std::min(numRows()-_row, numCols()-_col),
394                           &(this->operator()(row,col)),
395                           leadingDimension()+1,
396                           firstViewIndex,
397                           allocator());
398 }
399 
400 // namespace flens
401 
402 #endif // FLENS_STORAGE_FULLSTORAGE_CONSTFULLSTORAGEVIEW_TCC