Domi
Multi-dimensional, distributed data structures
 All Classes Files Functions Variables Typedefs Friends
Domi_MDArrayView.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Domi: Multi-dimensional Distributed Linear Algebra Services
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia
8 // Corporation, the U.S. Government retains certain rights in this
9 // software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact William F. Spotz (wfspotz@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef DOMI_MDARRAYVIEW_HPP
44 #define DOMI_MDARRAYVIEW_HPP
45 
46 // Standar includes
47 #include <cstdarg>
48 
49 // Teuchos includes
50 #include "Teuchos_Array.hpp"
51 #include "Teuchos_ArrayView.hpp"
52 #include "Teuchos_ConstTypeTraits.hpp"
53 #include "Teuchos_RCPNode.hpp"
54 
55 // Domi includes
56 #include "Domi_ConfigDefs.hpp"
57 #include "Domi_Exceptions.hpp"
58 #include "Domi_Utils.hpp"
59 #include "Domi_Slice.hpp"
60 #include "Domi_MDIterator.hpp"
61 #include "Domi_MDRevIterator.hpp"
62 
63 namespace Domi
64 {
65 
66 // I put these non-member template functions here for the same reason
67 // that Ross did the same thing for the Teuchos::Array class. See
68 // Teuchos_Array.hpp for details.
69 template< typename T > class MDArray;
70 template< typename T > class MDArrayView;
71 template< typename T > class MDArrayRCP;
72 
77 template< typename T >
78 bool operator==(const MDArrayView< T > & a1,
79  const MDArrayView< T > & a2);
80 
85 template< typename T >
86 bool operator!=(const MDArrayView< T > & a1,
87  const MDArrayView< T > & a2);
88 
93 template< typename T >
94 void swap(MDArrayView< T > & a1,
95  MDArrayView< T > & a2);
96 
113 template< typename T >
114 class MDArrayView
115 {
116 public:
117 
120 
122  typedef T value_type;
123 
125  typedef T* pointer;
126 
128  typedef const T* const_pointer;
129 
131  typedef T& reference;
132 
134  typedef const T& const_reference;
135 
137 
140 
149  MDArrayView(Teuchos::ENull null_arg = Teuchos::null);
150 
164  MDArrayView(const Teuchos::ArrayView< T > & array,
165  const Teuchos::ArrayView< dim_type > & dims,
166  const Layout layout = DEFAULT_ORDER);
167 
188  MDArrayView(const Teuchos::ArrayView< T > & array,
189  const Teuchos::Array< dim_type > & dims,
190  const Teuchos::Array< size_type > & strides,
191  const Layout layout = DEFAULT_ORDER);
192 
197  MDArrayView(const MDArrayView< T > & array);
198 
199  /* \brief Parent/single index sub-array view constructor
200  *
201  * \param parent [in] an MDArrayView, from which this MDArrayView
202  * will be derived
203  *
204  * \param axis [in] the axis to which this index ordinal applies
205  *
206  * \param index [in] the ordinal that defines this sub-array
207  */
208  MDArrayView(const MDArrayView< T > & parent,
209  int axis,
210  dim_type index);
211 
212  /* \brief Parent/single slice sub-array view constructor
213  *
214  * \param parent [in] an MDArrayView, from which this MDArrayView
215  * will be derived
216  *
217  * \param axis [in] the axis to which this index ordinal applies
218  *
219  * \param slice [in] the slice that defines this sub-array
220  */
221  MDArrayView(const MDArrayView< T > & parent,
222  int axis,
223  Slice slice);
224 
230 
233  ~MDArrayView();
234 
236 
239 
242  inline int numDims() const;
243 
246  inline const Teuchos::Array< dim_type > & dimensions() const;
247 
253  inline dim_type dimension(int axis) const;
254 
257  inline size_type size() const;
258 
261  inline const Teuchos::Array< size_type > & strides() const;
262 
265  inline const Teuchos::ArrayView< T > & arrayView() const;
266 
270  inline const Teuchos::ArrayView< const T > & arrayViewConst() const;
271 
274  inline Layout layout() const;
275 
278  inline bool contiguous() const;
279 
281 
284 
285  friend class MDIterator< MDArrayView< T > >;
286  friend class MDIterator< MDArrayView< const T > >;
287  friend class MDRevIterator< MDArrayView< T > >;
288  friend class MDRevIterator< MDArrayView< const T > >;
289 
294 
297  iterator begin();
298 
301  iterator end();
302 
305  const_iterator begin() const;
306 
309  const_iterator end() const;
310 
313  const_iterator cbegin() const;
314 
317  const_iterator cend() const;
318 
322 
326 
330 
334 
336 
339 
346 
356  MDArrayView< T > operator[](dim_type i);
357 
367  const MDArrayView< T > operator[](dim_type i) const;
368 
380 
391  const MDArrayView< T > operator[](Slice s) const;
392 
394 
397 
406  inline T & operator()(dim_type i);
407 
418  inline T & operator()(dim_type i, dim_type j);
419 
432  inline T & operator()(dim_type i, dim_type j, dim_type k);
433 
448  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m);
449 
466  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m,
467  dim_type n);
468 
490  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m,
491  dim_type n, dim_type p, ...);
492 
501  inline const T & operator()(dim_type i) const;
502 
513  inline const T & operator()(dim_type i, dim_type j) const;
514 
527  inline const T & operator()(dim_type i, dim_type j, dim_type k) const;
528 
543  inline const T & operator()(dim_type i, dim_type j, dim_type k,
544  dim_type m) const;
545 
562  inline const T & operator()(dim_type i, dim_type j, dim_type k,
563  dim_type m, dim_type n) const;
564 
586  inline const T & operator()(dim_type i, dim_type j, dim_type k,
587  dim_type m, dim_type n, dim_type p, ...) const;
588 
589 
591 
594 
600  void assign(const T & value);
601 
611  T & at(dim_type i, ...);
612 
621  const T & at(dim_type i, ...) const;
622 
626  inline static bool hasBoundsChecking();
627 
631  std::string toString() const;
632 
636  inline const T * getRawPtr() const;
637 
641  inline T * getRawPtr();
642 
643  // These operators are declared as friends so that the compiler will
644  // do automatic type conversion.
645 
648 
651  template< typename T2 >
652  friend bool operator==(const MDArrayView< T2 > & a1, const MDArrayView< T2 > & a2);
653 
656  template< typename T2 >
657  friend bool operator!=(const MDArrayView< T2 > & a1, const MDArrayView< T2 > & a2);
658 
661  template< typename T2 >
662  friend void swap(MDArrayView< T2 > & a1, MDArrayView< T2 > & a2);
663 
668  template< typename T2 >
669  friend std::ostream & operator<<(std::ostream & os,
670  const MDArrayView< T2 > & a);
671 
673 
674 private:
675 
676  Teuchos::Array< dim_type > _dimensions;
677  Teuchos::Array< size_type > _strides;
678  Teuchos::ArrayView< T > _array;
679  Layout _layout;
680  pointer _ptr;
681  int _next_axis;
682 
683  // Method provided for aiding in array bounds checking. It raises
684  // an exception when the given axis is out of range of valid
685  // dimensions.
686  void assertAxis(int axis) const;
687 
688  // Method provided for aiding in array bounds checking. It raises
689  // an exception when the given index i is out of range along the
690  // given axis.
691  void assertIndex(dim_type i, int axis) const;
692 
693  // Private implementation of the toString() method that includes an
694  // indent argument. The publicly available version takes no
695  // arguments and calls this one with initial indent value of zero.
696  // This method can call itself recursively.
697  std::string toString(int indent) const;
698 
699 }; // class MDArrayView
700 
702 // Implementations //
704 
705 template< typename T >
707 MDArrayView(Teuchos::ENull null_arg) :
708  _dimensions(Teuchos::tuple< dim_type >(0)),
709  _strides(Teuchos::tuple< size_type >(1)),
710  _array(),
711  _layout(DEFAULT_ORDER),
712  _ptr(),
713  _next_axis(0)
714 {
715 }
716 
718 
719 template< typename T >
720 MDArrayView< T >::MDArrayView(const Teuchos::ArrayView< T > & array,
721  const Teuchos::ArrayView< dim_type > & dims,
722  const Layout layout) :
723  _dimensions(dims),
724  _strides(computeStrides< size_type, dim_type >(dims, layout)),
725  _array(array),
726  _layout(layout),
727  _ptr(_array.getRawPtr()),
728  _next_axis(0)
729 {
730  TEUCHOS_TEST_FOR_EXCEPTION(array.size() < computeSize(dims),
731  RangeError,
732  "Teuchos::ArrayView size too small for "
733  "dimensions");
734 }
735 
737 
738 template< typename T >
739 MDArrayView< T >::MDArrayView(const Teuchos::ArrayView< T > & array,
740  const Teuchos::Array< dim_type > & dims,
741  const Teuchos::Array< size_type > & strides,
742  const Layout layout) :
743  _dimensions(dims),
744  _strides(strides),
745  _array(array),
746  _layout(layout),
747  _ptr(_array.getRawPtr()),
748  _next_axis(0)
749 {
750  const size_type required = computeSize< const size_type,
751  const dim_type >(dims(),strides());
752  TEUCHOS_TEST_FOR_EXCEPTION(
753  array.size() < required,
754  RangeError,
755  "Teuchos::ArrayView size too small for "
756  "dimensions and strides");
757 }
758 
760 
761 template< typename T >
763  _dimensions(array._dimensions),
764  _strides(array._strides),
765  _array(array._array),
766  _layout(array._layout),
767  _ptr(_array.getRawPtr()),
768  _next_axis(0)
769 {
770 }
771 
773 
774 template< typename T >
776  int axis,
777  dim_type index) :
778  _dimensions(),
779  _strides(),
780  _array(),
781  _layout(parent._layout),
782  _ptr(),
783  _next_axis(0)
784 {
785  // Make sure axis and index are valid
786  parent.assertAxis(axis);
787  parent.assertIndex(index, axis);
788  // Find the offset to the new MDArrayView
789  size_type offset = index * parent._strides[axis];
790  // Compute the dimensions of the new MDArrayView
791  size_type n = parent._dimensions.size();
792  // Compute the new dimensions and strides
793  if (n == 1)
794  {
795  _dimensions.push_back(1);
796  _strides.push_back(1);
797  }
798  else
799  {
800  for (int myAxis = 0; myAxis < n; myAxis++)
801  if (myAxis != axis)
802  {
803  _dimensions.push_back(parent._dimensions[myAxis]);
804  _strides.push_back(parent._strides[myAxis]);
805  }
806  }
807  // Compute the new MDArrayView and pointer
808  _array = parent._array.view(offset,
809  computeSize(_dimensions(),
810  _strides()));
811  _ptr = _array.getRawPtr();
812 }
813 
815 
816 template< typename T >
817 MDArrayView< T >::MDArrayView(const MDArrayView< T > & parent,
818  int axis,
819  Slice slice) :
820  _dimensions(parent._dimensions),
821  _strides(parent._strides),
822  _array(),
823  _layout(parent._layout),
824  _ptr(),
825  _next_axis(0)
826 {
827  // Make sure axis is valid
828  parent.assertAxis(axis);
829  // Note: the Slice.bounds() method produces safe indexes
830  Slice bounds = slice.bounds(_dimensions[axis]);
831  // Find the offset to the new MDArrayView
832  size_type offset = bounds.start() * _strides[axis];
833  // Compute the dimensions of the new MDArrayView
834  _dimensions[axis] = (bounds.stop() - bounds.start()) / bounds.step();
835  // Compute the strides of the new MDArrayView
836  _strides[axis] *= bounds.step();
837  // Compute the new MDArrayView and pointer
838  _array = parent._array.view(offset,
839  computeSize(_dimensions(),
840  _strides()));
841  _ptr = _array.getRawPtr();
842 }
843 
845 
846 template< typename T >
847 MDArrayView< T > &
849 {
850  _dimensions = array._dimensions;
851  _strides = array._strides;
852  _array = array._array;
853  _layout = array._layout;
854  _ptr = array._ptr;
855  _next_axis = array._next_axis;
856  return *this;
857 }
858 
860 
861 template< typename T >
863 {
864 }
865 
867 
868 template< typename T >
869 int
871 {
872  return _dimensions.size();
873 }
874 
876 
877 template< typename T >
878 const Teuchos::Array< dim_type > &
880 {
881  return _dimensions;
882 }
883 
885 
886 template< typename T >
887 dim_type
889 {
890 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
891  assertAxis(axis);
892 #endif
893  return _dimensions[axis];
894 }
895 
897 
898 template< typename T >
899 size_type
901 {
902  return computeSize(_dimensions(), _strides());
903 }
904 
906 
907 template< typename T >
908 const Teuchos::Array< size_type > &
910 {
911  return _strides;
912 }
913 
915 
916 template< typename T >
917 const Teuchos::ArrayView< T > &
919 {
920  return _array;
921 }
922 
924 
925 template< typename T >
926 const Teuchos::ArrayView< const T > &
928 {
929  return Teuchos::av_const_cast< const T >(_array);
930 }
931 
933 
934 template< typename T >
935 Layout
937 {
938  return _layout;
939 }
940 
942 
943 template< typename T >
944 bool
946 {
947  // Temporarily compute the strides this MDArrayView would have if
948  // its memory were contiguous with no stride gaps
949  Teuchos::Array< size_type > contig_strides =
950  computeStrides< size_type, dim_type >(_dimensions, _layout);
951  // If these strides are the same as the actual strides, then the
952  // MDArrayView is contiguous
953  return (contig_strides == _strides);
954 }
955 
957 
958 template< typename T >
961 {
962  return iterator(*this);
963 }
964 
966 
967 template< typename T >
970 {
971  // Return the iterator corresponding to the last element
972  return iterator(*this, true);
973 }
974 
976 
977 template< typename T >
980 {
981  return const_iterator(getConst());
982 }
983 
985 
986 template< typename T >
989 {
990  // Return the iterator corresponding to the last element
991  return const_iterator(getConst(), true);
992 }
993 
995 
996 template< typename T >
999 {
1000  return const_iterator(getConst());
1001 }
1002 
1004 
1005 template< typename T >
1008 {
1009  // Return the iterator corresponding to the last element
1010  return const_iterator(getConst(), true);
1011 }
1012 
1014 
1015 template< typename T >
1018 {
1019  return reverse_iterator(*this);
1020 }
1021 
1023 
1024 template< typename T >
1027 {
1028  // Return the reverse_iterator corresponding to the last element
1029  return reverse_iterator(*this, true);
1030 }
1031 
1033 
1034 template< typename T >
1037 {
1038  return const_reverse_iterator(*this);
1039 }
1040 
1042 
1043 template< typename T >
1046 {
1047  // Return the reverse_iterator corresponding to the last element
1048  return const_reverse_iterator(*this, true);
1049 }
1050 
1052 
1053 template< typename T >
1056 {
1057  return MDArrayView< const T >(_array.getConst(),
1058  _dimensions,
1059  _strides,
1060  _layout);
1061 }
1062 
1064 
1065 template< typename T >
1068 {
1069  // Construct the new MDArrayView
1070  MDArrayView< T > result(*this, _next_axis, i);
1071  // Correct the next axis of the new MDArrayView
1072  if (_next_axis < result.numDims())
1073  result._next_axis = _next_axis;
1074  // Return the result
1075  return result;
1076 }
1077 
1079 
1080 template< typename T >
1081 const MDArrayView< T >
1083 {
1084  // Construct the new MDArrayView
1085  MDArrayView< T > result(*this, _next_axis, i);
1086  // Correct the next axis of the new MDArrayView
1087  if (_next_axis < result.numDims())
1088  result._next_axis = _next_axis;
1089  // Return the result
1090  return result;
1091 }
1092 
1094 
1095 template< typename T >
1098 {
1099  // Construct the new MDArrayView
1100  MDArrayView< T > result(*this, _next_axis, s);
1101  // Correct the next axis of the new MDArrayView
1102  result._next_axis = _next_axis + 1;
1103  if (result._next_axis >= _dimensions.size())
1104  result._next_axis = 0;
1105  // Return the result
1106  return result;
1107 }
1108 
1110 
1111 template< typename T >
1112 const MDArrayView< T >
1114 {
1115  // Construct the new MDArrayView
1116  MDArrayView< T > result(*this, _next_axis, s);
1117  // Correct the next axis of the new MDArrayView
1118  result._next_axis = _next_axis + 1;
1119  if (result._next_axis >= _dimensions.size())
1120  result._next_axis = 0;
1121  // Return the result
1122  return result;
1123 }
1124 
1126 
1127 template< typename T >
1128 T &
1130 {
1131 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1132  TEUCHOS_TEST_FOR_EXCEPTION(
1133  (_dimensions.size() != 1), RangeError,
1134  "Attempt to access " << _dimensions.size() << "D array with 1 index"
1135  );
1136  assertIndex(i, 0);
1137 #endif
1138  return _ptr[i * _strides[0]];
1139 }
1140 
1142 
1143 template< typename T >
1144 T &
1146  dim_type j)
1147 {
1148 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1149  TEUCHOS_TEST_FOR_EXCEPTION(
1150  (_dimensions.size() != 2), RangeError,
1151  "Attempt to access " << _dimensions.size() << "D array with 2 indexes"
1152  );
1153  assertIndex(i, 0);
1154  assertIndex(j, 1);
1155 #endif
1156  return _ptr[i * _strides[0] + j * _strides[1]];
1157 }
1158 
1160 
1161 template< typename T >
1162 T &
1164  dim_type j,
1165  dim_type k)
1166 {
1167 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1168  TEUCHOS_TEST_FOR_EXCEPTION(
1169  (_dimensions.size() != 3), RangeError,
1170  "Attempt to access " << _dimensions.size() << "D array with 3 indexes"
1171  );
1172  assertIndex(i, 0);
1173  assertIndex(j, 1);
1174  assertIndex(k, 2);
1175 #endif
1176  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2]];
1177 }
1178 
1180 
1181 template< typename T >
1182 T &
1184  dim_type j,
1185  dim_type k,
1186  dim_type m)
1187 {
1188 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1189  TEUCHOS_TEST_FOR_EXCEPTION(
1190  (_dimensions.size() != 4), RangeError,
1191  "Attempt to access " << _dimensions.size() << "D array with 4 indexes"
1192  );
1193  assertIndex(i, 0);
1194  assertIndex(j, 1);
1195  assertIndex(k, 2);
1196  assertIndex(m, 3);
1197 #endif
1198  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1199  m * _strides[3]];
1200 }
1201 
1203 
1204 template< typename T >
1205 T &
1207  dim_type j,
1208  dim_type k,
1209  dim_type m,
1210  dim_type n)
1211 {
1212 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1213  TEUCHOS_TEST_FOR_EXCEPTION(
1214  (_dimensions.size() != 5), RangeError,
1215  "Attempt to access " << _dimensions.size() << "D array with 5 indexes"
1216  );
1217  assertIndex(i, 0);
1218  assertIndex(j, 1);
1219  assertIndex(k, 2);
1220  assertIndex(m, 3);
1221  assertIndex(n, 4);
1222 #endif
1223  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1224  m * _strides[3] + n * _strides[4]];
1225 }
1226 
1228 
1229 template< typename T >
1230 T &
1232  dim_type j,
1233  dim_type k,
1234  dim_type m,
1235  dim_type n,
1236  dim_type p,
1237  ...)
1238 {
1239 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1240  TEUCHOS_TEST_FOR_EXCEPTION(
1241  (_dimensions.size() < 6), RangeError,
1242  "Attempt to access " << _dimensions.size() << "D array with too many indexes"
1243  );
1244  assertIndex(i, 0);
1245  assertIndex(j, 1);
1246  assertIndex(k, 2);
1247  assertIndex(m, 3);
1248  assertIndex(n, 4);
1249  assertIndex(p, 5);
1250 #endif
1251  va_list indexes;
1252  size_type offset = i * _strides[0] + j * _strides[1] + k * _strides[2] +
1253  m * _strides[3] + n * _strides[4] + p * _strides[5];
1254  va_start(indexes, p);
1255  for (int axis = 6; axis < _dimensions.size(); axis++)
1256  {
1257  dim_type q = va_arg(indexes, dim_type);
1258 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1259  assertIndex(q, axis);
1260 #endif
1261  offset += q * _strides[axis];
1262  }
1263  va_end(indexes);
1264  return _ptr[offset];
1265 }
1266 
1268 
1269 template< typename T >
1270 const T &
1272 {
1273 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1274  TEUCHOS_TEST_FOR_EXCEPTION(
1275  (_dimensions.size() != 1), RangeError,
1276  "Attempt to access " << _dimensions.size() << "D array with 1 index"
1277  );
1278  assertIndex(i, 0);
1279 #endif
1280  return _ptr[i * _strides[0]];
1281 }
1282 
1284 
1285 template< typename T >
1286 const T &
1288  dim_type j) const
1289 {
1290 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1291  TEUCHOS_TEST_FOR_EXCEPTION(
1292  (_dimensions.size() != 2), RangeError,
1293  "Attempt to access " << _dimensions.size() << "D array with 2 indexes"
1294  );
1295  assertIndex(i, 0);
1296  assertIndex(j, 1);
1297 #endif
1298  return _ptr[i * _strides[0] + j * _strides[1]];
1299 }
1300 
1302 
1303 template< typename T >
1304 const T &
1306  dim_type j,
1307  dim_type k) const
1308 {
1309 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1310  TEUCHOS_TEST_FOR_EXCEPTION(
1311  (_dimensions.size() != 3), RangeError,
1312  "Attempt to access " << _dimensions.size() << "D array with 3 indexes"
1313  );
1314  assertIndex(i, 0);
1315  assertIndex(j, 1);
1316  assertIndex(k, 2);
1317 #endif
1318  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2]];
1319 }
1320 
1322 
1323 template< typename T >
1324 const T &
1326  dim_type j,
1327  dim_type k,
1328  dim_type m) const
1329 {
1330 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1331  TEUCHOS_TEST_FOR_EXCEPTION(
1332  (_dimensions.size() != 4), RangeError,
1333  "Attempt to access " << _dimensions.size() << "D array with 4 indexes"
1334  );
1335  assertIndex(i, 0);
1336  assertIndex(j, 1);
1337  assertIndex(k, 2);
1338  assertIndex(m, 3);
1339 #endif
1340  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1341  m * _strides[3]];
1342 }
1343 
1345 
1346 template< typename T >
1347 const T &
1349  dim_type j,
1350  dim_type k,
1351  dim_type m,
1352  dim_type n) const
1353 {
1354 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1355  TEUCHOS_TEST_FOR_EXCEPTION(
1356  (_dimensions.size() != 5), RangeError,
1357  "Attempt to access " << _dimensions.size() << "D array with 5 indexes"
1358  );
1359  assertIndex(i, 0);
1360  assertIndex(j, 1);
1361  assertIndex(k, 2);
1362  assertIndex(m, 3);
1363  assertIndex(n, 4);
1364 #endif
1365  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1366  m * _strides[3] + n * _strides[4]];
1367 }
1368 
1370 
1371 template< typename T >
1372 const T &
1374  dim_type j,
1375  dim_type k,
1376  dim_type m,
1377  dim_type n,
1378  dim_type p,
1379  ...) const
1380 {
1381 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1382  TEUCHOS_TEST_FOR_EXCEPTION(
1383  (_dimensions.size() < 6), RangeError,
1384  "Attempt to access " << _dimensions.size() << "D array with too many indexes"
1385  );
1386  assertIndex(i, 0);
1387  assertIndex(j, 1);
1388  assertIndex(k, 2);
1389  assertIndex(m, 3);
1390  assertIndex(n, 4);
1391  assertIndex(p, 5);
1392 #endif
1393  va_list indexes;
1394  size_type offset = i * _strides[0] + j * _strides[1] + k * _strides[2] +
1395  m * _strides[3] + n * _strides[4] + p * _strides[5];
1396  va_start(indexes, p);
1397  for (int axis = 6; axis < _dimensions.size(); axis++)
1398  {
1399  dim_type q = va_arg(indexes, dim_type);
1400 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1401  assertIndex(q, axis);
1402 #endif
1403  offset += q * _strides[axis];
1404  }
1405  va_end(indexes);
1406  return _ptr[offset];
1407 }
1408 
1410 
1411 template< typename T >
1412 void
1414 {
1415  for (iterator it = begin(); it != end(); ++it)
1416  *it = value;
1417 }
1418 
1420 
1421 template< typename T >
1422 T &
1423 MDArrayView< T >::at(dim_type i, ...)
1424 {
1425  assertIndex(i, 0);
1426  va_list indexes;
1427  size_type offset = i * _strides[0];
1428  va_start(indexes, i);
1429  for (int axis = 1; axis < _dimensions.size(); axis++)
1430  {
1431  dim_type j = va_arg(indexes, dim_type);
1432  assertIndex(j, axis);
1433  offset += j * _strides[axis];
1434  }
1435  va_end(indexes);
1436  return _array[offset];
1437 }
1438 
1440 
1441 template< typename T >
1442 const T &
1443 MDArrayView< T >::at(dim_type i, ...) const
1444 {
1445  assertIndex(i, 0);
1446  va_list indexes;
1447  size_type offset = i * _strides[0];
1448  va_start(indexes, i);
1449  for (int axis = 1; axis < _dimensions.size(); axis++)
1450  {
1451  dim_type j = va_arg(indexes, dim_type);
1452  assertIndex(j, axis);
1453  offset += j * _strides[axis];
1454  }
1455  va_end(indexes);
1456  return _array[offset];
1457 }
1458 
1460 
1461 template< typename T >
1462 bool
1464 {
1465 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1466  return true;
1467 #else
1468  return false;
1469 #endif
1470 }
1471 
1473 
1474 template< typename T >
1475 std::string
1477 {
1478  // Call the private version of toString() with an indentation level
1479  // of zero
1480  return toString(0);
1481 }
1482 
1484 
1485 template< typename T >
1486 std::string
1487 MDArrayView< T >::toString(int indent) const
1488 {
1489  std::stringstream ss;
1490  ss << "[";
1491  for (size_type i = 0; i < _dimensions[0]; i++)
1492  {
1493  // If 1D, output an element, else output a sub-array recursively
1494  if (numDims() == 1)
1495  ss << operator()(i);
1496  else
1497  ss << operator[](i).toString(indent+1);
1498  // If not the last item along this axis, output a comma
1499  if (i < _dimensions[0]-1)
1500  {
1501  ss << ",";
1502  // If 1D, follow the comma with a space, else a newline and
1503  // indentation spacing
1504  if (numDims() == 1)
1505  ss << " ";
1506  else
1507  {
1508  ss << std::endl << " ";
1509  for (int ii = 0; ii < indent; ii++) ss << " ";
1510  }
1511  }
1512  }
1513  ss << "]";
1514  return ss.str();
1515 }
1516 
1518 
1519 template< typename T >
1520 const T *
1522 {
1523  return _array.getRawPtr();
1524 }
1525 
1527 
1528 template< typename T >
1529 T *
1531 {
1532  return _array.getRawPtr();
1533 }
1534 
1536 
1537 template< typename T >
1538 bool operator==(const MDArrayView< T > & a1, const MDArrayView< T > & a2)
1539 {
1540  if (a1._dimensions != a2._dimensions) return false;
1541  if (a1._layout != a2._layout ) return false;
1542  typename MDArrayView< T >::const_iterator it1 = a1.begin();
1543  typename MDArrayView< T >::const_iterator it2 = a2.begin();
1544  for ( ; it1 != a1.end() && it2 != a2.end(); ++it1, ++it2)
1545  {
1546  if (*it1 != *it2) return false;
1547  }
1548  return true;
1549 }
1550 
1552 
1553 template< typename T >
1554 bool operator!=(const MDArrayView< T > & a1, const MDArrayView< T > & a2)
1555 {
1556  return not (a1 == a2);
1557 }
1558 
1560 
1561 template< typename T >
1562 void swap(MDArrayView< T > & a1, MDArrayView< T > & a2)
1563 {
1564  a1.swap(a2);
1565 }
1566 
1568 
1569 template< typename T >
1570 std::ostream & operator<<(std::ostream & os, const MDArrayView< T > & a)
1571 {
1572  os << a.toString();
1573  return os;
1574 }
1575 
1577 // Private implementations //
1579 
1580 template< typename T >
1581 void
1582 MDArrayView< T >::assertAxis(int axis) const
1583 {
1584  TEUCHOS_TEST_FOR_EXCEPTION(
1585  !(0 <= axis && axis < _dimensions.size()),
1586  RangeError,
1587  "MDArrayView<T>::assertAxis(axis=" << axis << "): out of "
1588  << "range axis in [0, " << _dimensions.size() << ")"
1589  );
1590 }
1591 
1592 template< typename T >
1593 void
1594 MDArrayView< T >::assertIndex(dim_type i, int axis) const
1595 {
1596  TEUCHOS_TEST_FOR_EXCEPTION(
1597  !(0 <= i && i < _dimensions[axis]), RangeError,
1598  "MDArrayView<T>::assertIndex(i=" << i << ",axis=" << axis << "): out of "
1599  << "range i in [0, " << _dimensions[axis] << ")"
1600  );
1601 }
1602 
1603 } // End namespace Domi
1604 
1605 #endif // DOMI_MDARRAYVIEW_HPP
const Teuchos::ArrayView< const T > & arrayViewConst() const
Return const version of the underlying Teuchos::ArrayView
Definition: Domi_MDArrayView.hpp:927
const T * const_pointer
Const pointer type.
Definition: Domi_MDArrayView.hpp:128
T & at(dim_type i,...)
Non-const single element access method with bounds checking.
Definition: Domi_MDArrayView.hpp:1423
void assign(const T &value)
Assign a value to all elements of the MDArrayView
Definition: Domi_MDArrayView.hpp:1413
const_reverse_iterator crbegin() const
Return the beginning const_reverse_iterator.
Definition: Domi_MDArrayView.hpp:1036
T value_type
Value type.
Definition: Domi_MDArrayView.hpp:122
iterator begin()
Return the beginning iterator.
Definition: Domi_MDArrayView.hpp:960
Iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDIterator.hpp:100
iterator end()
Return the ending iterator.
Definition: Domi_MDArrayView.hpp:969
std::string toString() const
Convert the MDArrayView to a string representation.
Definition: Domi_MDArrayView.hpp:1476
Range Error exception type.
Definition: Domi_Exceptions.hpp:65
int numDims() const
Return the number of dimensions.
Definition: Domi_MDArrayView.hpp:870
dim_type dimension(int axis) const
Return the dimension of the given axis.
Definition: Domi_MDArrayView.hpp:888
friend bool operator!=(const MDArrayView< T2 > &a1, const MDArrayView< T2 > &a2)
Inequality operator.
MDArrayView< T > operator[](dim_type i)
Sub-array access operator. The returned MDArrayView object will have one fewer dimensions than the ca...
Definition: Domi_MDArrayView.hpp:1067
MDArrayView(Teuchos::ENull null_arg=Teuchos::null)
Default constructor.
Definition: Domi_MDArrayView.hpp:707
T * pointer
Pointer type.
Definition: Domi_MDArrayView.hpp:125
reverse_iterator rend()
Return the ending reverse_iterator.
Definition: Domi_MDArrayView.hpp:1026
A Slice defines a subset of a container.
const_iterator cend() const
Return the ending const_iterator.
Definition: Domi_MDArrayView.hpp:1007
bool contiguous() const
Return whether the MDArrayView is contiguous in memory.
Definition: Domi_MDArrayView.hpp:945
MDArrayView< const T > getConst() const
Return an MDArrayView&lt; const T &gt; of an MDArrayView&lt; T &gt; object.
Definition: Domi_MDArrayView.hpp:1055
A Slice contains a start, stop, and step index, describing a subset of an ordered container...
Definition: Domi_Slice.hpp:137
T & operator()(dim_type i)
Non-const 1D element access operator.
Definition: Domi_MDArrayView.hpp:1129
const_reverse_iterator crend() const
Return the ending const_reverse_iterator.
Definition: Domi_MDArrayView.hpp:1045
~MDArrayView()
Destructor.
Definition: Domi_MDArrayView.hpp:862
const_iterator cbegin() const
Return the beginning const_iterator.
Definition: Domi_MDArrayView.hpp:998
const T & const_reference
Const reference type.
Definition: Domi_MDArrayView.hpp:134
size_type size() const
Return the total size of the MDArrayView
Definition: Domi_MDArrayView.hpp:900
Memory-safe templated multi-dimensional array view class.
Definition: Domi_MDArrayView.hpp:70
const Teuchos::Array< size_type > & strides() const
Return the indexing strides.
Definition: Domi_MDArrayView.hpp:909
Layout layout() const
Return the storage order.
Definition: Domi_MDArrayView.hpp:936
reverse_iterator rbegin()
Return the beginning reverse_iterator.
Definition: Domi_MDArrayView.hpp:1017
T & reference
Reference type.
Definition: Domi_MDArrayView.hpp:131
const Teuchos::Array< dim_type > & dimensions() const
Return the array of dimensions.
Definition: Domi_MDArrayView.hpp:879
friend void swap(MDArrayView< T2 > &a1, MDArrayView< T2 > &a2)
Swap function.
const Teuchos::ArrayView< T > & arrayView() const
Return the underlying Teuchos::ArrayView
Definition: Domi_MDArrayView.hpp:918
friend std::ostream & operator<<(std::ostream &os, const MDArrayView< T2 > &a)
Stream output operator.
MDArrayView< T > & operator=(const MDArrayView< T > &array)
Assignment operator.
Definition: Domi_MDArrayView.hpp:848
Reverse iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDRevIterator.hpp:98
const T * getRawPtr() const
Return a const raw pointer to the beginning of the MDArrayView or NULL if unsized.
Definition: Domi_MDArrayView.hpp:1521
static bool hasBoundsChecking()
Return true if MDArrayView has been compiled with bounds checking on.
Definition: Domi_MDArrayView.hpp:1463
Memory-safe, reference-counted, templated, multi-dimensional array class.
Definition: Domi_MDArrayRCP.hpp:63
friend bool operator==(const MDArrayView< T2 > &a1, const MDArrayView< T2 > &a2)
Equality operator.

Generated on Fri Sep 1 2023 07:56:17 for Domi by doxygen 1.8.5