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_FULLSTORAGEVIEW_TCC
 34 #define FLENS_STORAGE_FULLSTORAGE_FULLSTORAGEVIEW_TCC 1
 35 
 36 #include <flens/storage/fullstorage/trapezoidalfill.h>
 37 #include <flens/typedefs.h>
 38 
 39 namespace flens {
 40 
 41 template <typename T, StorageOrder Order, typename I, typename A>
 42 FullStorageView<T, Order, I, A>::FullStorageView(IndexType numRows,
 43                                                  IndexType numCols,
 44                                                  ElementType *data,
 45                                                  IndexType leadingDimension,
 46                                                  IndexType firstRow,
 47                                                  IndexType firstCol,
 48                                                  const Allocator &allocator)
 49     : _data(data),
 50       _allocator(allocator),
 51       _numRows(numRows), _numCols(numCols),
 52       _leadingDimension(leadingDimension),
 53       _firstRow(0), _firstCol(0)
 54 {
 55     ASSERT(_numRows>=0);
 56     ASSERT(_numCols>=0);
 57 
 58     changeIndexBase(firstRow, firstCol);
 59 }
 60 
 61 template <typename T, StorageOrder Order, typename I, typename A>
 62 template <typename ARRAY>
 63 FullStorageView<T, Order, I, A>::FullStorageView(IndexType numRows,
 64                                                  IndexType numCols,
 65                                                  ARRAY &array,
 66                                                  IndexType leadingDimension,
 67                                                  IndexType firstRow,
 68                                                  IndexType firstCol,
 69                                                  const Allocator &allocator)
 70     : _data(array.data()),
 71       _allocator(allocator),
 72       _numRows(numRows), _numCols(numCols),
 73       _leadingDimension(leadingDimension),
 74       _firstRow(0), _firstCol(0)
 75 {
 76     ASSERT(numRows*numCols<=array.length());
 77     ASSERT(_numRows>=0);
 78     ASSERT(_numCols>=0);
 79 
 80     changeIndexBase(firstRow, firstCol);
 81 }
 82 
 83 template <typename T, StorageOrder Order, typename I, typename A>
 84 FullStorageView<T, Order, I, A>::FullStorageView(const FullStorageView &rhs)
 85     : _data(rhs._data),
 86       _allocator(rhs._allocator),
 87       _numRows(rhs._numRows), _numCols(rhs._numCols),
 88       _leadingDimension(rhs._leadingDimension),
 89       _firstRow(rhs._firstRow), _firstCol(rhs._firstCol)
 90 {
 91 }
 92 
 93 template <typename T, StorageOrder Order, typename I, typename A>
 94 template <typename RHS>
 95 FullStorageView<T, Order, I, A>::FullStorageView(RHS &rhs)
 96     : _data(rhs.data()),
 97       _allocator(rhs.allocator()),
 98       _numRows(rhs.numRows()), _numCols(rhs.numCols()),
 99       _leadingDimension(rhs.leadingDimension()),
100       _firstRow(0), _firstCol(0)
101 {
102     changeIndexBase(rhs.firstRow(), rhs.firstCol());
103 }
104 
105 template <typename T, StorageOrder Order, typename I, typename A>
106 FullStorageView<T, Order, I, A>::~FullStorageView()
107 {
108 }
109 
110 //-- operators -----------------------------------------------------------------
111 
112 template <typename T, StorageOrder Order, typename I, typename A>
113 const typename FullStorageView<T, Order, I, A>::ElementType &
114 FullStorageView<T, Order, I, A>::operator()(IndexType row, IndexType col) const
115 {
116     ASSERT(row>=_firstRow);
117     ASSERT(row<_firstRow+_numRows);
118     ASSERT(col>=_firstCol);
119     ASSERT(col<_firstCol+_numCols);
120 
121     if (Order==ColMajor) {
122         return _data[col*_leadingDimension+row];
123     }
124     return _data[row*_leadingDimension+col];
125 }
126 
127 template <typename T, StorageOrder Order, typename I, typename A>
128 typename FullStorageView<T, Order, I, A>::ElementType &
129 FullStorageView<T, Order, I, A>::operator()(IndexType row, IndexType col)
130 {
131     ASSERT(row>=_firstRow);
132     ASSERT(row<_firstRow+_numRows);
133     ASSERT(col>=_firstCol);
134     ASSERT(col<_firstCol+_numCols);
135 
136     if (Order==ColMajor) {
137         return _data[col*_leadingDimension+row];
138     }
139     return _data[row*_leadingDimension+col];
140 }
141 
142 //-- methods -------------------------------------------------------------------
143 
144 template <typename T, StorageOrder Order, typename I, typename A>
145 typename FullStorageView<T, Order, I, A>::IndexType
146 FullStorageView<T, Order, I, A>::firstRow() const
147 {
148     return _firstRow;
149 }
150 
151 template <typename T, StorageOrder Order, typename I, typename A>
152 typename FullStorageView<T, Order, I, A>::IndexType
153 FullStorageView<T, Order, I, A>::lastRow() const
154 {
155     return _firstRow+_numRows-1;
156 }
157 
158 template <typename T, StorageOrder Order, typename I, typename A>
159 typename FullStorageView<T, Order, I, A>::IndexType
160 FullStorageView<T, Order, I, A>::firstCol() const
161 {
162     return _firstCol;
163 }
164 
165 template <typename T, StorageOrder Order, typename I, typename A>
166 typename FullStorageView<T, Order, I, A>::IndexType
167 FullStorageView<T, Order, I, A>::lastCol() const
168 {
169     return _firstCol+_numCols-1;
170 }
171 
172 template <typename T, StorageOrder Order, typename I, typename A>
173 typename FullStorageView<T, Order, I, A>::IndexType
174 FullStorageView<T, Order, I, A>::numRows() const
175 {
176     return _numRows;
177 }
178 
179 template <typename T, StorageOrder Order, typename I, typename A>
180 typename FullStorageView<T, Order, I, A>::IndexType
181 FullStorageView<T, Order, I, A>::numCols() const
182 {
183     return _numCols;
184 }
185 
186 template <typename T, StorageOrder Order, typename I, typename A>
187 typename FullStorageView<T, Order, I, A>::IndexType
188 FullStorageView<T, Order, I, A>::leadingDimension() const
189 {
190     return _leadingDimension;
191 }
192 
193 template <typename T, StorageOrder Order, typename I, typename A>
194 typename FullStorageView<T, Order, I, A>::IndexType
195 FullStorageView<T, Order, I, A>::strideRow() const
196 {
197     return (Order==ColMajor) ? 1
198                              : leadingDimension();
199 }
200 
201 template <typename T, StorageOrder Order, typename I, typename A>
202 typename FullStorageView<T, Order, I, A>::IndexType
203 FullStorageView<T, Order, I, A>::strideCol() const
204 {
205     return (Order==ColMajor) ? leadingDimension()
206                              : 1;
207 }
208 
209 template <typename T, StorageOrder Order, typename I, typename A>
210 const typename FullStorageView<T, Order, I, A>::ElementType *
211 FullStorageView<T, Order, I, A>::data() const
212 {
213 #   ifndef NDEBUG
214     if ((numRows()==0) || numCols()==0) {
215         return 0;
216     }
217 #   endif
218     return &(this->operator()(_firstRow, _firstCol));
219 }
220 
221 template <typename T, StorageOrder Order, typename I, typename A>
222 typename FullStorageView<T, Order, I, A>::ElementType *
223 FullStorageView<T, Order, I, A>::data()
224 {
225 #   ifndef NDEBUG
226     if ((numRows()==0) || numCols()==0) {
227         return 0;
228     }
229 #   endif
230 
231     return &(this->operator()(_firstRow, _firstCol));
232 }
233 
234 template <typename T, StorageOrder Order, typename I, typename A>
235 const typename FullStorageView<T, Order, I, A>::Allocator &
236 FullStorageView<T, Order, I, A>::allocator() const
237 {
238     return _allocator;
239 }
240 
241 template <typename T, StorageOrder Order, typename I, typename A>
242 bool
243 FullStorageView<T, Order, I, A>::resize(IndexType DEBUG_VAR(_numRows),
244                                         IndexType DEBUG_VAR(_numCols),
245                                         IndexType firstRow,
246                                         IndexType firstCol,
247                                         const ElementType &)
248 {
249     ASSERT(_numRows==numRows());
250     ASSERT(_numCols==numCols());
251     changeIndexBase(firstRow, firstCol);
252     return false;
253 }
254 
255 template <typename T, StorageOrder Order, typename I, typename A>
256 template <typename FS>
257 bool
258 FullStorageView<T, Order, I, A>::resize(const FS &rhs, const ElementType &value)
259 {
260     return resize(rhs.numRows(), rhs.numCols(),
261                   rhs.firstRow(), rhs.firstCol(),
262                   value);
263 }
264 
265 template <typename T, StorageOrder Order, typename I, typename A>
266 bool
267 FullStorageView<T, Order, I, A>::fill(const ElementType &value)
268 {
269     if (Order==RowMajor) {
270         ElementType *p = data();
271         for (IndexType i=0; i<numRows(); ++i, p+=leadingDimension()) {
272             std::fill_n(p, numCols(), value);
273         }
274         return true;
275     }
276     if (Order==ColMajor) {
277         ElementType *p = data();
278         for (IndexType j=0; j<numCols(); ++j, p+=leadingDimension()) {
279             std::fill_n(p, numRows(), value);
280         }
281         return true;
282     }
283     ASSERT(0);
284     return false;
285 }
286 
287 template <typename T, StorageOrder Order, typename I, typename A>
288 bool
289 FullStorageView<T, Order, I, A>::fill(StorageUpLo  upLo,
290                                       const ElementType &value)
291 {
292     trapezoidalFill(order, upLo, value,
293                     numRows(), numCols(),
294                     data(), leadingDimension());
295     return true;
296 }
297 
298 template <typename T, StorageOrder Order, typename I, typename A>
299 void
300 FullStorageView<T, Order, I, A>::changeIndexBase(IndexType firstRow,
301                                                  IndexType firstCol)
302 {
303 #   ifndef NDEBUG
304     // prevent an out-of-bound assertion in case a view is empty anyway
305     if ((numRows()==0) || (numCols()==0)) {
306         _firstRow = firstRow;
307         _firstCol = firstCol;
308         return;
309     }
310 #   endif
311 
312     if (Order==RowMajor) {
313         _data = data() - (firstRow*leadingDimension() + firstCol);
314     }
315     if (Order==ColMajor) {
316         _data = data() - (firstCol*leadingDimension() + firstRow);
317     }
318     _firstRow = firstRow;
319     _firstCol = firstCol;
320 }
321 
322 // view of fullstorage scheme as an array
323 template <typename T, StorageOrder Order, typename I, typename A>
324 const typename FullStorageView<T, Order, I, A>::ConstArrayView
325 FullStorageView<T, Order, I, A>::arrayView(IndexType firstViewIndex) const
326 {
327 #   ifndef NDEBUG
328     if (order==ColMajor) {
329         ASSERT(numRows()==leadingDimension());
330     } else {
331         ASSERT(numCols()==leadingDimension());
332     }
333 #   endif
334 
335     return ConstArrayView(numCols()*numRows(),
336                           data(),
337                           IndexType(1),
338                           firstViewIndex,
339                           allocator());
340 }
341 
342 template <typename T, StorageOrder Order, typename I, typename A>
343 typename FullStorageView<T, Order, I, A>::ArrayView
344 FullStorageView<T, Order, I, A>::arrayView(IndexType firstViewIndex)
345 {
346 #   ifndef NDEBUG
347     if (order==ColMajor) {
348         ASSERT(numRows()==leadingDimension());
349     } else {
350         ASSERT(numCols()==leadingDimension());
351     }
352 #   endif
353 
354     return ArrayView(numCols()*numRows(),
355                      data(),
356                      IndexType(1),
357                      firstViewIndex,
358                      allocator());
359 }
360 
361 // view of rectangular part
362 template <typename T, StorageOrder Order, typename I, typename A>
363 const typename FullStorageView<T, Order, I, A>::ConstView
364 FullStorageView<T, Order, I, A>::view(IndexType fromRow, IndexType fromCol,
365                                       IndexType toRow, IndexType toCol,
366                                       IndexType firstViewRow,
367                                       IndexType firstViewCol) const
368 {
369     const IndexType numRows = toRow-fromRow+1;
370     const IndexType numCols = toCol-fromCol+1;
371 
372 #   ifndef NDEBUG
373     // prevent an out-of-bound assertion in case a view is empty anyway
374     if ((numRows==0) || (numCols==0)) {
375         return ConstView(numRows, numCols, 0, leadingDimension(),
376                          firstViewRow, firstViewCol, allocator());
377     }
378 #   endif
379 
380     ASSERT(fromRow>=firstRow());
381     ASSERT(fromRow<=toRow);
382     ASSERT(toRow<=lastRow());
383 
384     ASSERT(fromCol>=firstCol());
385     ASSERT(fromCol<=toCol);
386     ASSERT(toCol<=lastCol());
387 
388     return ConstView(numRows,                              // # rows
389                      numCols,                              // # cols
390                      &(operator()(fromRow, fromCol)),      // data
391                      leadingDimension(),                   // leading dimension
392                      firstViewRow,                         // firstRow
393                      firstViewCol,                         // firstCol
394                      allocator());                         // allocator
395 }
396 
397 template <typename T, StorageOrder Order, typename I, typename A>
398 FullStorageView<T, Order, I, A>
399 FullStorageView<T, Order, I, A>::view(IndexType fromRow, IndexType fromCol,
400                                       IndexType toRow, IndexType toCol,
401                                       IndexType firstViewRow,
402                                       IndexType firstViewCol)
403 {
404     const IndexType numRows = toRow-fromRow+1;
405     const IndexType numCols = toCol-fromCol+1;
406 
407 #   ifndef NDEBUG
408     // prevent an out-of-bound assertion in case a view is empty anyway
409     if ((numRows==0) || (numCols==0)) {
410         return View(numRows, numCols, 0, leadingDimension(),
411                     firstViewRow, firstViewCol, allocator());
412     }
413 #   endif
414 
415     ASSERT(fromRow>=firstRow());
416     ASSERT(fromRow<=toRow);
417     ASSERT(toRow<=lastRow());
418 
419     ASSERT(fromCol>=firstCol());
420     ASSERT(fromCol<=toCol);
421     ASSERT(toCol<=lastCol());
422 
423     return View(numRows,                              // # rows
424                 numCols,                              // # cols
425                 &(operator()(fromRow, fromCol)),      // data
426                 leadingDimension(),                   // leading dimension
427                 firstViewRow,                         // firstRow
428                 firstViewCol,                         // firstCol
429                 allocator());                         // allocator
430 }
431 
432 // view of single row
433 template <typename T, StorageOrder Order, typename I, typename A>
434 const typename FullStorageView<T, Order, I, A>::ConstArrayView
435 FullStorageView<T, Order, I, A>::viewRow(IndexType row,
436                                          IndexType firstViewIndex) const
437 {
438 #   ifndef NDEBUG
439     // prevent an out-of-bound assertion in case a view is empty anyway
440     if (numCols()==0) {
441         return ConstArrayView(numCols(), 0, strideCol(),
442                               firstViewIndex, allocator());
443     }
444 #   endif
445 
446     ASSERT(row>=firstRow());
447     ASSERT(row<=lastRow());
448 
449     return ConstArrayView(numCols(),
450                           &(operator()(row, _firstCol)),
451                           strideCol(),
452                           firstViewIndex,
453                           allocator());
454 }
455 
456 template <typename T, StorageOrder Order, typename I, typename A>
457 typename FullStorageView<T, Order, I, A>::ArrayView
458 FullStorageView<T, Order, I, A>::viewRow(IndexType row,
459                                          IndexType firstViewIndex)
460 {
461 #   ifndef NDEBUG
462     // prevent an out-of-bound assertion in case a view is empty anyway
463     if (numCols()==0) {
464         return ArrayView(numCols(), 0, strideCol(),
465                          firstViewIndex, allocator());
466     }
467 #   endif
468 
469     ASSERT(row>=firstRow());
470     ASSERT(row<=lastRow());
471 
472     return ArrayView(numCols(),
473                      &(operator()(row, _firstCol)),
474                      strideCol(),
475                      firstViewIndex,
476                      allocator());
477 }
478 
479 template <typename T, StorageOrder Order, typename I, typename A>
480 const typename FullStorageView<T, Order, I, A>::ConstArrayView
481 FullStorageView<T, Order, I, A>::viewRow(IndexType row,
482                                          IndexType firstCol, IndexType lastCol,
483                                          IndexType firstViewIndex) const
484 {
485     const IndexType length = lastCol-firstCol+1;
486 
487 #   ifndef NDEBUG
488     // prevent an out-of-bound assertion in case a view is empty anyway
489     if (length==0) {
490         return ConstArrayView(length, 0, strideCol(),
491                               firstViewIndex, allocator());
492     }
493 #   endif
494 
495     ASSERT(row>=firstRow());
496     ASSERT(row<=lastRow());
497 
498     return ConstArrayView(length,
499                           &(operator()(row, firstCol)),
500                           strideCol(),
501                           firstViewIndex,
502                           allocator());
503 }
504 
505 template <typename T, StorageOrder Order, typename I, typename A>
506 typename FullStorageView<T, Order, I, A>::ArrayView
507 FullStorageView<T, Order, I, A>::viewRow(IndexType row,
508                                          IndexType firstCol, IndexType lastCol,
509                                          IndexType firstViewIndex)
510 {
511     const IndexType length = lastCol-firstCol+1;
512 
513 #   ifndef NDEBUG
514     // prevent an out-of-bound assertion in case a view is empty anyway
515     if (length==0) {
516         return ArrayView(length, 0, strideCol(),
517                          firstViewIndex, allocator());
518     }
519 #   endif
520 
521     ASSERT(row>=firstRow());
522     ASSERT(row<=lastRow());
523 
524     return ArrayView(length,
525                      &(operator()(row, firstCol)),
526                      strideCol(),
527                      firstViewIndex,
528                      allocator());
529 }
530 
531 // view of single column
532 template <typename T, StorageOrder Order, typename I, typename A>
533 const typename FullStorageView<T, Order, I, A>::ConstArrayView
534 FullStorageView<T, Order, I, A>::viewCol(IndexType col,
535                                          IndexType firstViewIndex) const
536 {
537 #   ifndef NDEBUG
538     // prevent an out-of-bound assertion in case a view is empty anyway
539     if (numRows()==0) {
540         return ConstArrayView(numRows(), 0, strideRow(),
541                               firstViewIndex, allocator());
542     }
543 #   endif
544 
545     ASSERT(col>=firstCol());
546     ASSERT(col<=lastCol());
547 
548     return ConstArrayView(numRows(),
549                           &(operator()(_firstRow, col)),
550                           strideRow(),
551                           firstViewIndex,
552                           allocator());
553 }
554 
555 template <typename T, StorageOrder Order, typename I, typename A>
556 typename FullStorageView<T, Order, I, A>::ArrayView
557 FullStorageView<T, Order, I, A>::viewCol(IndexType col,
558                                          IndexType firstViewIndex)
559 {
560 #   ifndef NDEBUG
561     // prevent an out-of-bound assertion in case a view is empty anyway
562     if (numRows()==0) {
563         return ArrayView(numRows(), 0, strideRow(),
564                          firstViewIndex, allocator());
565     }
566 #   endif
567 
568     ASSERT(col>=firstCol());
569     ASSERT(col<=lastCol());
570 
571     return ArrayView(numRows(),
572                      &(operator()(_firstRow, col)),
573                      strideRow(),
574                      firstViewIndex,
575                      allocator());
576 }
577 
578 template <typename T, StorageOrder Order, typename I, typename A>
579 const typename FullStorageView<T, Order, I, A>::ConstArrayView
580 FullStorageView<T, Order, I, A>::viewCol(IndexType firstRow, IndexType lastRow,
581                                          IndexType col,
582                                          IndexType firstViewIndex) const
583 {
584     const IndexType length = lastRow-firstRow+1;
585 
586 #   ifndef NDEBUG
587     // prevent an out-of-bound assertion in case a view is empty anyway
588     if (length==0) {
589         return ConstArrayView(length, 0, strideRow(),
590                               firstViewIndex, allocator());
591     }
592 #   endif
593 
594     ASSERT(col>=firstCol());
595     ASSERT(col<=lastCol());
596 
597     return ConstArrayView(length,
598                           &(operator()(firstRow, col)),
599                           strideRow(),
600                           firstViewIndex,
601                           allocator());
602 }
603 
604 template <typename T, StorageOrder Order, typename I, typename A>
605 typename FullStorageView<T, Order, I, A>::ArrayView
606 FullStorageView<T, Order, I, A>::viewCol(IndexType firstRow, IndexType lastRow,
607                                          IndexType col,
608                                          IndexType firstViewIndex)
609 {
610     const IndexType length = lastRow-firstRow+1;
611 
612 #   ifndef NDEBUG
613     // prevent an out-of-bound assertion in case a view is empty anyway
614     if (length==0) {
615         return ArrayView(length, 0, strideRow(),
616                          firstViewIndex, allocator());
617     }
618 #   endif
619 
620     ASSERT(col>=firstCol());
621     ASSERT(col<=lastCol());
622 
623     return ArrayView(length,
624                      &(operator()(firstRow, col)),
625                      strideRow(),
626                      firstViewIndex,
627                      allocator());
628 }
629 
630 // view of d-th diagonal
631 template <typename T, StorageOrder Order, typename I, typename A>
632 const typename FullStorageView<T, Order, I, A>::ConstArrayView
633 FullStorageView<T, Order, I, A>::viewDiag(IndexType d,
634                                           IndexType firstViewIndex) const
635 {
636     IndexType _row = (d>0) ? 0 : -d;
637     IndexType _col = (d>0) ? d :  0;
638 
639     IndexType row = firstRow() + _row;
640     IndexType col = firstCol() + _col;
641 
642     return ConstArrayView(std::min(numRows()-_row, numCols()-_col),
643                           &(operator()(row,col)),
644                           leadingDimension()+1,
645                           firstViewIndex,
646                           allocator());
647 }
648 
649 template <typename T, StorageOrder Order, typename I, typename A>
650 typename FullStorageView<T, Order, I, A>::ArrayView
651 FullStorageView<T, Order, I, A>::viewDiag(IndexType d,
652                                           IndexType firstViewIndex)
653 {
654     IndexType _row = (d>0) ? 0 : -d;
655     IndexType _col = (d>0) ? d :  0;
656 
657     IndexType row = firstRow() + _row;
658     IndexType col = firstCol() + _col;
659 
660     return ArrayView(std::min(numRows()-_row,numCols()-_col),
661                      &(operator()(row,col)),
662                      leadingDimension()+1,
663                      firstViewIndex,
664                      allocator());
665 }
666 
667 // namespace flens
668 
669 #endif // FLENS_STORAGE_FULLSTORAGE_FULLSTORAGEVIEW_TCC