Domi
Multi-dimensional, distributed data structures
 All Classes Files Functions Variables Typedefs Friends
Domi_MDArray.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_MDARRAY_HPP
44 #define DOMI_MDARRAY_HPP
45 
46 // Standard includes
47 #include <cstdarg>
48 
49 // Teuchos includes
50 #include "Teuchos_Array.hpp"
51 
52 // Domi includes
53 #include "Domi_ConfigDefs.hpp"
54 #include "Domi_Utils.hpp"
55 #include "Domi_MDIterator.hpp"
56 #include "Domi_MDRevIterator.hpp"
57 #include "Domi_MDArrayView.hpp"
58 
59 namespace Domi
60 {
61 
62 // I put these non-member template functions here for the same reason
63 // that Ross did the same thing for the Teuchos::Array class. See
64 // Teuchos_Array.hpp for details.
65 template< typename T > class MDArray;
66 
71 template< typename T >
72 bool operator==(const MDArray< T > & a1,
73  const MDArray< T > & a2);
74 
80 template< typename T >
81 bool operator==(const MDArray< T > & a1,
82  const MDArrayView< T > & a2);
83 
89 template< typename T >
90 bool operator==(const MDArrayView< T > & a1,
91  const MDArray< T > & a2);
92 
97 template< typename T >
98 bool operator!=(const MDArray< T > & a1,
99  const MDArray< T > & a2);
100 
105 template< typename T >
106 bool operator!=(const MDArray< T > & a1,
107  const MDArrayView< T > & a2);
108 
114 template< typename T >
115 bool operator!=(const MDArrayView< T > & a1,
116  const MDArray< T > & a2);
117 
122 template< typename T >
123 void swap(MDArray< T > & a1, MDArray< T > & a2);
124 
285 template< typename T >
286 class MDArray
287 {
288 public:
289 
292 
294  typedef T value_type;
295 
297  typedef T* pointer;
298 
300  typedef const T* const_pointer;
301 
303  typedef T& reference;
304 
306  typedef const T& const_reference;
307 
309 
312 
317  inline MDArray();
318 
326  inline MDArray(const Teuchos::ArrayView< dim_type > & dims);
327 
342  inline MDArray(const Teuchos::ArrayView< dim_type > & dims,
343  const T & value,
344  const Layout layout = DEFAULT_ORDER);
345 
360  inline MDArray(const Teuchos::ArrayView< dim_type > & dims,
361  const Layout layout,
362  const T & value = value_type());
363 
368  inline MDArray(const MDArray< T > & source);
369 
374  MDArray(const MDArrayView< T > & source);
375 
378  ~MDArray();
379 
381 
384 
387  inline int numDims() const;
388 
391  inline const Teuchos::Array< dim_type > & dimensions() const;
392 
398  inline dim_type dimension(int axis) const;
399 
402  inline size_type size() const;
403 
406  inline const Teuchos::Array< size_type > & strides() const;
407 
410  inline const Teuchos::Array< T > & array() const;
411 
414  inline const Layout layout() const;
415 
417 
420 
421  friend class MDIterator< MDArray< T > >;
422  friend class MDIterator< MDArray< const T > >;
423  friend class MDRevIterator< MDArray< T > >;
424  friend class MDRevIterator< MDArray< const T > >;
425 
430 
433  iterator begin();
434 
437  iterator end();
438 
441  const_iterator begin() const;
442 
445  const_iterator end() const;
446 
449  const_iterator cbegin() const;
450 
453  const_iterator cend() const;
454 
458 
462 
466 
470 
472 
475 
480 
484  const MDArrayView< T > mdArrayView() const;
485 
490 
495 
496 #ifndef SWIG
497 
500  inline operator MDArrayView< T >() const;
501 
505  inline operator MDArrayView< const T >() const;
506 #endif
507 
509 
512 
522  MDArrayView< T > operator[](dim_type i);
523 
533  const MDArrayView< T > operator[](dim_type i) const;
534 
545 
555  const MDArrayView< T > operator[](Slice s) const;
556 
559  inline MDArrayView< T > operator()();
560 
563  inline const MDArrayView< T > operator()() const;
564 
566 
570 
579  inline T & operator()(dim_type i);
580 
591  inline T & operator()(dim_type i, dim_type j);
592 
605  inline T & operator()(dim_type i, dim_type j, dim_type k);
606 
621  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m);
622 
639  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m,
640  dim_type n);
641 
663  inline T & operator()(dim_type i, dim_type j, dim_type k, dim_type m,
664  dim_type n, dim_type p, ...);
665 
674  inline const T & operator()(dim_type i) const;
675 
686  inline const T & operator()(dim_type i, dim_type j) const;
687 
700  inline const T & operator()(dim_type i, dim_type j, dim_type k) const;
701 
716  inline const T & operator()(dim_type i, dim_type j, dim_type k,
717  dim_type m) const;
718 
735  inline const T & operator()(dim_type i, dim_type j, dim_type k,
736  dim_type m, dim_type n) const;
737 
759  inline const T & operator()(dim_type i, dim_type j, dim_type k,
760  dim_type m, dim_type n, dim_type p, ...) const;
761 
763 
766 
771  void assign(const T & value);
772 
781  T & at(dim_type i, ...);
782 
791  const T & at(dim_type i, ...) const;
792 
795  inline size_type capacity() const;
796 
799  void clear();
800 
803  inline bool empty() const;
804 
807  inline size_type max_size() const;
808 
813  void resize(const Teuchos::ArrayView< dim_type > & dims);
814 
817  void swap(MDArray<T> & a);
818 
822  inline static bool hasBoundsChecking();
823 
826  std::string toString() const;
827 
831  inline const T * getRawPtr() const;
832 
836  inline T * getRawPtr();
837 
839 
840  // These operators are declared as friends so that the compiler will
841  // do automatic type conversion.
842 
845 
848  template< typename T2 >
849  friend bool operator==(const MDArray< T2 > & a1,
850  const MDArray< T2 > & a2);
851 
854  template< typename T2 >
855  friend bool operator==(const MDArray< T2 > & a1,
856  const MDArrayView< T2 > & a2);
857 
860  template< typename T2 >
861  friend bool operator==(const MDArrayView< T2 > & a1,
862  const MDArray< T2 > & a2);
863 
866  template< typename T2 >
867  friend bool operator!=(const MDArray< T2 > & a1,
868  const MDArray< T2 > & a2);
869 
872  template< typename T2 >
873  friend bool operator!=(const MDArray< T2 > & a1,
874  const MDArrayView< T2 > & a2);
875 
878  template< typename T2 >
879  friend bool operator!=(const MDArrayView< T2 > & a1,
880  const MDArray< T2 > & a2);
881 
884  template< typename T2 >
885  friend std::ostream & operator<<(std::ostream & os,
886  const MDArray< T2 > & a);
887 
890  template< typename T2 >
891  friend void swap(MDArray< T2 > & a1,
892  MDArray< T2 > & a2);
893 
895 
896 private:
897  Teuchos::Array< dim_type > _dimensions;
898  Teuchos::Array< size_type > _strides;
899  Teuchos::Array< T > _array;
900  Layout _layout;
901  pointer _ptr;
902 
903  // Used for array bounds checking
904  void assertAxis(int axis) const;
905 
906  // Used for array bounds checking
907  void assertIndex(dim_type i, int axis) const;
908 };
909 
911 // Implementations //
913 
914 template< typename T >
916  _dimensions(Teuchos::tuple< dim_type >(0)),
917  _strides(Teuchos::tuple< size_type >(1)),
918  _array(),
919  _layout(DEFAULT_ORDER),
920  _ptr()
921 {
922 }
923 
925 
926 template< typename T >
927 MDArray< T >::MDArray(const Teuchos::ArrayView< dim_type > & dims) :
928  _dimensions(dims),
929  _strides(computeStrides< size_type, dim_type >(dims, DEFAULT_ORDER)),
930  _array(computeSize(dims)),
931  _layout(DEFAULT_ORDER),
932  _ptr(_array.getRawPtr())
933 {
934 }
935 
937 
938 template< typename T >
939 MDArray< T >::MDArray(const Teuchos::ArrayView< dim_type > & dims,
940  const T & value,
941  const Layout layout) :
942  _dimensions(dims),
943  _strides(computeStrides< size_type, dim_type >(dims, layout)),
944  _array(computeSize(dims), value),
945  _layout(layout),
946  _ptr(_array.getRawPtr())
947 {
948 }
949 
951 
952 template< typename T >
953 MDArray< T >::MDArray(const Teuchos::ArrayView< dim_type > & dims,
954  const Layout layout,
955  const T & value) :
956  _dimensions(dims),
957  _strides(computeStrides< size_type, dim_type >(dims, layout)),
958  _array(computeSize(dims), value),
959  _layout(layout),
960  _ptr(_array.getRawPtr())
961 {
962 }
963 
965 
966 template< typename T >
968  _dimensions(source._dimensions),
969  _strides(source._strides),
970  _array(source._array),
971  _layout(source._layout),
972  _ptr(_array.getRawPtr())
973 {
974 }
975 
977 
978 template< typename T >
980  _dimensions(source.dimensions()),
981  _strides(computeStrides< size_type, dim_type >(source.dimensions(),
982  source.layout())),
983  _array(computeSize(source.dimensions())),
984  _layout(source.layout()),
985  _ptr(_array.getRawPtr())
986 {
987  // Copy the values from the MDArrayView to the MDArray
988  iterator thisit = begin();
989  typename MDArrayView< T >::const_iterator srcit = source.cbegin();
990  for ( ; srcit != source.cend(); ++thisit, ++srcit)
991  {
992  *thisit = *srcit;
993  }
994 }
995 
997 
998 template< typename T >
1000 {
1001 }
1002 
1004 
1005 template< typename T >
1006 int
1008 {
1009  return _dimensions.size();
1010 }
1011 
1013 
1014 template< typename T >
1015 const Teuchos::Array< dim_type > &
1017 {
1018  return _dimensions;
1019 }
1020 
1022 
1023 template< typename T >
1024 dim_type
1026 {
1027 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1028  assertAxis(axis);
1029 #endif
1030  return _dimensions[axis];
1031 }
1032 
1034 
1035 template< typename T >
1036 size_type
1038 {
1039  return _array.size();
1040 }
1041 
1043 
1044 template< typename T >
1045 const Teuchos::Array< size_type > &
1047 {
1048  return _strides;
1049 }
1050 
1052 
1053 template< typename T >
1054 const Teuchos::Array< T > &
1056 {
1057  return _array;
1058 }
1059 
1061 
1062 template< typename T >
1063 const Layout
1065 {
1066  return _layout;
1067 }
1068 
1070 
1071 template< typename T >
1072 typename MDArray< T >::iterator
1074 {
1075  return iterator(*this);
1076 }
1077 
1079 
1080 template< typename T >
1081 typename MDArray< T >::iterator
1083 {
1084  // Return the iterator corresponding to the last element
1085  return iterator(*this, true);
1086 }
1087 
1089 
1090 template< typename T >
1093 {
1094  return const_iterator(*this);
1095 }
1096 
1098 
1099 template< typename T >
1102 {
1103  // Return the iterator corresponding to the last element
1104  return const_iterator(*this, true);
1105 }
1106 
1108 
1109 template< typename T >
1112 {
1113  return const_iterator(*this);
1114 }
1115 
1117 
1118 template< typename T >
1121 {
1122  // Return the iterator corresponding to the last element
1123  return const_iterator(*this, true);
1124 }
1125 
1127 
1128 template< typename T >
1131 {
1132  return reverse_iterator(*this);
1133 }
1134 
1136 
1137 template< typename T >
1140 {
1141  // Return the reverse_iterator corresponding to the last element
1142  return reverse_iterator(*this, true);
1143 }
1144 
1146 
1147 template< typename T >
1150 {
1151  return const_reverse_iterator(*this);
1152 }
1153 
1155 
1156 template< typename T >
1159 {
1160  // Return the reverse_iterator corresponding to the last element
1161  return const_reverse_iterator(*this, true);
1162 }
1163 
1165 
1166 template< typename T >
1169 {
1170  return MDArrayView< T >(_array(), _dimensions, _layout);
1171 }
1172 
1174 
1175 template< typename T >
1176 const MDArrayView< T >
1178 {
1179  Teuchos::ArrayView< T > array(const_cast< T* >(_array.getRawPtr()),
1180  _array.size());
1181  Teuchos::Array< dim_type > dims(_dimensions);
1182  return MDArrayView< T >(array, dims(), _layout);
1183 }
1184 
1186 
1187 template< typename T >
1190 {
1191  return MDArrayView< const T >(_array, _dimensions(), _layout);
1192 }
1193 
1195 
1196 template< typename T >
1199 {
1200  return MDArrayView< const T >(_array, _dimensions(), _layout);
1201 }
1202 
1204 
1205 #ifndef SWIG
1206 template< typename T >
1208 {
1209  return mdArrayView();
1210 }
1211 
1213 
1214 template< typename T >
1216 {
1217  return mdArrayViewConst();
1218 }
1219 #endif
1220 
1222 
1223 template< typename T >
1226 {
1227  // Note: array bounds checking, if active, will be performed by the
1228  // MDArrayView class
1229  return mdArrayView()[i];
1230 }
1231 
1233 
1234 template< typename T >
1235 const MDArrayView< T >
1236 MDArray< T >::operator[](dim_type i) const
1237 {
1238  // Note: array bounds checking, if active, will be performed by the
1239  // MDArrayView class
1240  return mdArrayView()[i];
1241 }
1242 
1244 
1245 template< typename T >
1248 {
1249  // Note: Slices produce safe indexes
1250  return mdArrayView()[s];
1251 }
1252 
1254 
1255 template< typename T >
1256 const MDArrayView< T >
1258 {
1259  // Note: Slices produce safe indexes
1260  return mdArrayView()[s];
1261 }
1262 
1264 
1265 template< typename T >
1268 {
1269  return mdArrayView();
1270 }
1271 
1273 
1274 template< typename T >
1275 const MDArrayView< T >
1277 {
1278  return mdArrayView();
1279 }
1280 
1282 
1283 template< typename T >
1284 T &
1286 {
1287 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1288  TEUCHOS_TEST_FOR_EXCEPTION(
1289  (_dimensions.size() != 1), RangeError,
1290  "Attempt to access " << _dimensions.size() << "D array with 1 index"
1291  );
1292  assertIndex(i, 0);
1293 #endif
1294  return _ptr[i * _strides[0]];
1295 }
1296 
1298 
1299 template< typename T >
1300 T &
1302  dim_type j)
1303 {
1304 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1305  TEUCHOS_TEST_FOR_EXCEPTION(
1306  (_dimensions.size() != 2), RangeError,
1307  "Attempt to access " << _dimensions.size() << "D array with 2 indexes"
1308  );
1309  assertIndex(i, 0);
1310  assertIndex(j, 1);
1311 #endif
1312  return _ptr[i * _strides[0] + j * _strides[1]];
1313 }
1314 
1316 
1317 template< typename T >
1318 T &
1320  dim_type j,
1321  dim_type k)
1322 {
1323 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1324  TEUCHOS_TEST_FOR_EXCEPTION(
1325  (_dimensions.size() != 3), RangeError,
1326  "Attempt to access " << _dimensions.size() << "D array with 3 indexes"
1327  );
1328  assertIndex(i, 0);
1329  assertIndex(j, 1);
1330  assertIndex(k, 2);
1331 #endif
1332  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2]];
1333 }
1334 
1336 
1337 template< typename T >
1338 T &
1340  dim_type j,
1341  dim_type k,
1342  dim_type m)
1343 {
1344 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1345  TEUCHOS_TEST_FOR_EXCEPTION(
1346  (_dimensions.size() != 4), RangeError,
1347  "Attempt to access " << _dimensions.size() << "D array with 4 indexes"
1348  );
1349  assertIndex(i, 0);
1350  assertIndex(j, 1);
1351  assertIndex(k, 2);
1352  assertIndex(m, 3);
1353 #endif
1354  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1355  m * _strides[3]];
1356 }
1357 
1359 
1360 template< typename T >
1361 T &
1363  dim_type j,
1364  dim_type k,
1365  dim_type m,
1366  dim_type n)
1367 {
1368 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1369  TEUCHOS_TEST_FOR_EXCEPTION(
1370  (_dimensions.size() != 5), RangeError,
1371  "Attempt to access " << _dimensions.size() << "D array with 5 indexes"
1372  );
1373  assertIndex(i, 0);
1374  assertIndex(j, 1);
1375  assertIndex(k, 2);
1376  assertIndex(m, 3);
1377  assertIndex(n, 4);
1378 #endif
1379  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1380  m * _strides[3] + n * _strides[4]];
1381 }
1382 
1384 
1385 template< typename T >
1386 T &
1388  dim_type j,
1389  dim_type k,
1390  dim_type m,
1391  dim_type n,
1392  dim_type p,
1393  ...)
1394 {
1395 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1396  TEUCHOS_TEST_FOR_EXCEPTION(
1397  (_dimensions.size() < 6), RangeError,
1398  "Attempt to access " << _dimensions.size() << "D array with too many indexes"
1399  );
1400  assertIndex(i, 0);
1401  assertIndex(j, 1);
1402  assertIndex(k, 2);
1403  assertIndex(m, 3);
1404  assertIndex(n, 4);
1405  assertIndex(p, 5);
1406 #endif
1407  va_list indexes;
1408  size_type offset = i * _strides[0] + j * _strides[1] + k * _strides[2] +
1409  m * _strides[3] + n * _strides[4] + p * _strides[5];
1410  va_start(indexes, p);
1411  for (int axis = 6; axis < _dimensions.size(); axis++)
1412  {
1413  dim_type q = va_arg(indexes, dim_type);
1414 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1415  assertIndex(q, axis);
1416 #endif
1417  offset += q * _strides[axis];
1418  }
1419  va_end(indexes);
1420  return _ptr[offset];
1421 }
1422 
1424 
1425 template< typename T >
1426 const T &
1427 MDArray< T >::operator()(dim_type i) const
1428 {
1429 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1430  TEUCHOS_TEST_FOR_EXCEPTION(
1431  (_dimensions.size() != 1), RangeError,
1432  "Attempt to access " << _dimensions.size() << "D array with 1 index"
1433  );
1434  assertIndex(i, 0);
1435 #endif
1436  return _ptr[i * _strides[0]];
1437 }
1438 
1440 
1441 template< typename T >
1442 const T &
1444  dim_type j) const
1445 {
1446 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1447  TEUCHOS_TEST_FOR_EXCEPTION(
1448  (_dimensions.size() != 2), RangeError,
1449  "Attempt to access " << _dimensions.size() << "D array with 2 indexes"
1450  );
1451  assertIndex(i, 0);
1452  assertIndex(j, 1);
1453 #endif
1454  return _ptr[i * _strides[0] + j * _strides[1]];
1455 }
1456 
1458 
1459 template< typename T >
1460 const T &
1462  dim_type j,
1463  dim_type k) const
1464 {
1465 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1466  TEUCHOS_TEST_FOR_EXCEPTION(
1467  (_dimensions.size() != 3), RangeError,
1468  "Attempt to access " << _dimensions.size() << "D array with 3 indexes"
1469  );
1470  assertIndex(i, 0);
1471  assertIndex(j, 1);
1472  assertIndex(k, 2);
1473 #endif
1474  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2]];
1475 }
1476 
1478 
1479 template< typename T >
1480 const T &
1482  dim_type j,
1483  dim_type k,
1484  dim_type m) const
1485 {
1486 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1487  TEUCHOS_TEST_FOR_EXCEPTION(
1488  (_dimensions.size() != 4), RangeError,
1489  "Attempt to access " << _dimensions.size() << "D array with 4 indexes"
1490  );
1491  assertIndex(i, 0);
1492  assertIndex(j, 1);
1493  assertIndex(k, 2);
1494  assertIndex(m, 3);
1495 #endif
1496  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1497  m * _strides[3]];
1498 }
1499 
1501 
1502 template< typename T >
1503 const T &
1505  dim_type j,
1506  dim_type k,
1507  dim_type m,
1508  dim_type n) const
1509 {
1510 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1511  TEUCHOS_TEST_FOR_EXCEPTION(
1512  (_dimensions.size() != 5), RangeError,
1513  "Attempt to access " << _dimensions.size() << "D array with 5 indexes"
1514  );
1515  assertIndex(i, 0);
1516  assertIndex(j, 1);
1517  assertIndex(k, 2);
1518  assertIndex(m, 3);
1519  assertIndex(n, 4);
1520 #endif
1521  return _ptr[i * _strides[0] + j * _strides[1] + k * _strides[2] +
1522  m * _strides[3] + n * _strides[4]];
1523 }
1524 
1526 
1527 template< typename T >
1528 const T &
1530  dim_type j,
1531  dim_type k,
1532  dim_type m,
1533  dim_type n,
1534  dim_type p,
1535  ...) const
1536 {
1537 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1538  TEUCHOS_TEST_FOR_EXCEPTION(
1539  (_dimensions.size() < 6), RangeError,
1540  "Attempt to access " << _dimensions.size() << "D array with too many indexes"
1541  );
1542  assertIndex(i, 0);
1543  assertIndex(j, 1);
1544  assertIndex(k, 2);
1545  assertIndex(m, 3);
1546  assertIndex(n, 4);
1547  assertIndex(p, 5);
1548 #endif
1549  va_list indexes;
1550  size_type offset = i * _strides[0] + j * _strides[1] + k * _strides[2] +
1551  m * _strides[3] + n * _strides[4] + p * _strides[5];
1552  va_start(indexes, p);
1553  for (int axis = 6; axis < _dimensions.size(); axis++)
1554  {
1555  dim_type q = va_arg(indexes, dim_type);
1556 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1557  assertIndex(q, axis);
1558 #endif
1559  offset += q * _strides[axis];
1560  }
1561  va_end(indexes);
1562  return _ptr[offset];
1563 }
1564 
1566 
1567 template< typename T >
1568 void
1569 MDArray< T >::assign(const T & value)
1570 {
1571  for (iterator it = begin(); it != end(); ++it)
1572  *it = value;
1573 }
1574 
1576 
1577 template< typename T >
1578 T &
1579 MDArray< T >::at(dim_type i, ...)
1580 {
1581  assertIndex(i, 0);
1582  va_list indexes;
1583  size_type offset = i * _strides[0];
1584  va_start(indexes, i);
1585  for (int axis = 1; axis < _dimensions.size(); axis++)
1586  {
1587  dim_type j = va_arg(indexes, dim_type);
1588  assertIndex(j, axis);
1589  offset += j * _strides[axis];
1590  }
1591  va_end(indexes);
1592  return _ptr[offset];
1593 }
1594 
1596 
1597 template< typename T >
1598 const T &
1599 MDArray< T >::at(dim_type i, ...) const
1600 {
1601  assertIndex(i, 0);
1602  va_list indexes;
1603  size_type offset = i * _strides[0];
1604  va_start(indexes, i);
1605  for (int axis = 1; axis < _dimensions.size(); axis++)
1606  {
1607  dim_type j = va_arg(indexes, dim_type);
1608  assertIndex(j, axis);
1609  offset += j * _strides[axis];
1610  }
1611  va_end(indexes);
1612  return _ptr[offset];
1613 }
1614 
1616 
1617 template< typename T >
1618 size_type
1620 {
1621  return _array.capacity();
1622 }
1623 
1625 
1626 template< typename T >
1627 void
1629 {
1630  _dimensions.resize(1);
1631  _dimensions[0] = 0;
1632  _strides.resize(1);
1633  _strides[0] = 1;
1634  _array.clear();
1635  _ptr = _array.getRawPtr();
1636 }
1637 
1639 
1640 template< typename T >
1641 bool
1643 {
1644  return _array.empty();
1645 }
1646 
1648 
1649 template< typename T >
1650 size_type
1652 {
1653  return _array.max_size();
1654 }
1655 
1657 
1658 template< typename T >
1659 void
1660 MDArray< T >::resize(const Teuchos::ArrayView< dim_type > & dims)
1661 {
1662  _dimensions.assign(dims.begin(), dims.end());
1663  _strides = computeStrides< size_type, dim_type >(dims, _layout);
1664  _array.resize(computeSize(dims));
1665  _ptr = _array.getRawPtr();
1666 }
1667 
1669 
1670 template< typename T >
1671 void
1673 {
1674  // Use Teuchos::swap() to swap the dimensions, strides and
1675  // underlying array
1676  Teuchos::swap(_dimensions, a._dimensions);
1677  Teuchos::swap(_strides, a._strides );
1678  Teuchos::swap(_array, a._array );
1679  // Perform a raw swap of the storage order
1680  Layout tmp = _layout;
1681  _layout = a._layout;
1682  a._layout = tmp;
1683  // Make sure the pointers are correct
1684  _ptr = _array.getRawPtr();
1685  a._ptr = a._array.getRawPtr();
1686 }
1687 
1689 
1690 template< typename T >
1691 bool
1693 {
1694 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
1695  return true;
1696 #else
1697  return false;
1698 #endif
1699 }
1700 
1702 
1703 template< typename T >
1704 std::string
1706 {
1707  return mdArrayView().toString();
1708 }
1709 
1711 
1712 template< typename T >
1713 const T *
1715 {
1716  return _array.getRawPtr();
1717 }
1718 
1720 
1721 template< typename T >
1722 T *
1724 {
1725  return _array.getRawPtr();
1726 }
1727 
1729 
1730 template< typename T >
1731 bool operator==(const MDArray< T > & a1, const MDArray< T > & a2)
1732 {
1733  return (a1() == a2());
1734 }
1735 
1737 
1738 template< typename T >
1739 bool operator==(const MDArray< T > & a1, const MDArrayView< T > & a2)
1740 {
1741  return (a1() == a2);
1742 }
1743 
1745 
1746 template< typename T >
1747 bool operator==(const MDArrayView< T > & a1, const MDArray< T > & a2)
1748 {
1749  return (a1 == a2());
1750 }
1751 
1753 
1754 template< typename T >
1755 bool operator!=(const MDArray< T > & a1, const MDArray< T > & a2)
1756 {
1757  return not (a1 == a2);
1758 }
1759 
1761 
1762 template< typename T >
1763 bool operator!=(const MDArray< T > & a1, const MDArrayView< T > & a2)
1764 {
1765  return (a1() != a2);
1766 }
1767 
1769 
1770 template< typename T >
1771 bool operator!=(const MDArrayView< T > & a1, const MDArray< T > & a2)
1772 {
1773  return (a1 != a2());
1774 }
1775 
1777 
1778 template< typename T >
1779 std::ostream & operator<<(std::ostream & os, const MDArray< T > & a)
1780 {
1781  os << a.toString();
1782  return os;
1783 }
1784 
1786 
1787 template< typename T >
1788 void swap(MDArray< T > & a1, MDArray< T > & a2)
1789 {
1790  a1.swap(a2);
1791 }
1792 
1794 // Private implementations //
1796 
1797 template< typename T >
1798 void
1799 MDArray< T >::assertAxis(int axis) const
1800 {
1801  TEUCHOS_TEST_FOR_EXCEPTION(
1802  !(0 <= axis && axis < _dimensions.size()),
1803  RangeError,
1804  "MDArray<T>::assertAxis(axis=" << axis << "): out of range "
1805  << "axis in [0, " << _dimensions.size() << ")"
1806  );
1807 }
1808 
1810 
1811 template< typename T >
1812 void
1813 MDArray< T >::assertIndex(dim_type i, int axis) const
1814 {
1815  TEUCHOS_TEST_FOR_EXCEPTION(
1816  !(0 <= i && i < _dimensions[axis]), RangeError,
1817  "MDArray<T>::assertIndex(i=" << i << ",axis=" << axis << "): out of range "
1818  << "i in [0, " << _dimensions[axis] << ")"
1819  );
1820 }
1821 
1822 } // end namespace Domi
1823 
1824 #endif
bool empty() const
Return whether the MDArray is empty.
Definition: Domi_MDArray.hpp:1642
friend std::ostream & operator<<(std::ostream &os, const MDArray< T2 > &a)
Stream output operator.
int numDims() const
Return the number of dimensions.
Definition: Domi_MDArray.hpp:1007
const_iterator cbegin() const
Return the beginning const_iterator.
Definition: Domi_MDArray.hpp:1111
void swap(MDArray< T > &a)
Swap this MDArray with the given MDArray
Definition: Domi_MDArray.hpp:1672
~MDArray()
Destructor.
Definition: Domi_MDArray.hpp:999
Iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDIterator.hpp:100
Range Error exception type.
Definition: Domi_Exceptions.hpp:65
const T * getRawPtr() const
Return a const raw pointer to the beginning of the MDArray or NULL if unsized.
Definition: Domi_MDArray.hpp:1714
iterator begin()
Return the beginning iterator.
Definition: Domi_MDArray.hpp:1073
const T & const_reference
Const reference type.
Definition: Domi_MDArray.hpp:306
const Teuchos::Array< dim_type > & dimensions() const
Return an array of dimensions.
Definition: Domi_MDArray.hpp:1016
T & at(dim_type i,...)
Non-const single element access method with bounds checking.
Definition: Domi_MDArray.hpp:1579
void clear()
Clear the MDArray
Definition: Domi_MDArray.hpp:1628
const_iterator cend() const
Return the ending const_iterator.
Definition: Domi_MDArrayView.hpp:1007
const_reverse_iterator crbegin() const
Return the beginning const_reverse_iterator.
Definition: Domi_MDArray.hpp:1149
void assign(const T &value)
Assign a value to all elements of the MDArray
Definition: Domi_MDArray.hpp:1569
MDArrayView< T > operator[](dim_type i)
Sub-array access operator. The returned MDArrayView object will have one fewer dimensions than the ca...
Definition: Domi_MDArray.hpp:1225
const_reverse_iterator crend() const
Return the ending const_reverse_iterator.
Definition: Domi_MDArray.hpp:1158
A Slice contains a start, stop, and step index, describing a subset of an ordered container...
Definition: Domi_Slice.hpp:137
MDArrayView< T > operator()()
Conversion to non-const MDArrayView
Definition: Domi_MDArray.hpp:1267
const Teuchos::Array< size_type > & strides() const
Return the indexing strides.
Definition: Domi_MDArray.hpp:1046
const T * const_pointer
Const pointer type.
Definition: Domi_MDArray.hpp:300
T value_type
Value type.
Definition: Domi_MDArray.hpp:294
reverse_iterator rend()
Return the ending reverse_iterator.
Definition: Domi_MDArray.hpp:1139
const_iterator cbegin() const
Return the beginning const_iterator.
Definition: Domi_MDArrayView.hpp:998
dim_type dimension(int axis) const
Return the dimension of the given axis.
Definition: Domi_MDArray.hpp:1025
const_iterator cend() const
Return the ending const_iterator.
Definition: Domi_MDArray.hpp:1120
void resize(const Teuchos::ArrayView< dim_type > &dims)
Resize the MDArray based on the given dimensions.
Definition: Domi_MDArray.hpp:1660
std::string toString() const
Convert the MDArray to a string representation.
Definition: Domi_MDArray.hpp:1705
size_type capacity() const
Return the capacity of the underlying Teuchos::Array
Definition: Domi_MDArray.hpp:1619
Memory-safe templated multi-dimensional array view class.
Definition: Domi_MDArrayView.hpp:70
size_type max_size() const
Return the maximum allowable size for the MDArray
Definition: Domi_MDArray.hpp:1651
const Teuchos::Array< T > & array() const
Return the underlying Teuchos::Array
Definition: Domi_MDArray.hpp:1055
T * pointer
Pointer type.
Definition: Domi_MDArray.hpp:297
MDArrayView< T > mdArrayView()
Perform an explicit conversion to a non-const MDArrayView&lt;T&gt;
Definition: Domi_MDArray.hpp:1168
friend bool operator==(const MDArray< T2 > &a1, const MDArray< T2 > &a2)
Equality operator.
friend bool operator!=(const MDArray< T2 > &a1, const MDArray< T2 > &a2)
Inequality operator.
size_type size() const
Return the total size of the MDArray
Definition: Domi_MDArray.hpp:1037
MDArrayView< const T > mdArrayViewConst()
Perform an explicit conversion to a non-const MDArrayView&lt;const T&gt;
Definition: Domi_MDArray.hpp:1189
reverse_iterator rbegin()
Return the beginning reverse_iterator.
Definition: Domi_MDArray.hpp:1130
T & reference
Reference type.
Definition: Domi_MDArray.hpp:303
MDArray()
Default constructor.
Definition: Domi_MDArray.hpp:915
Reverse iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDRevIterator.hpp:98
Memory-safe templated multi-dimensional array class.
Definition: Domi_MDArray.hpp:65
iterator end()
Return the ending iterator.
Definition: Domi_MDArray.hpp:1082
static bool hasBoundsChecking()
Return true if MDArray has been compiled with bounds checking on.
Definition: Domi_MDArray.hpp:1692
const Layout layout() const
Return the storage order.
Definition: Domi_MDArray.hpp:1064

Generated on Fri Nov 22 2024 09:26:41 for Domi by doxygen 1.8.5