00001 #pragma once
00002 #ifndef MARRAY_HXX
00003 #define MARRAY_HXX
00004
00005 #include <cassert>
00006 #include <stdexcept>
00007 #include <limits>
00008 #include <string>
00009 #include <sstream>
00010 #include <cstring>
00011 #include <iterator>
00012 #include <vector>
00013 #include <set>
00014 #include <iostream>
00015 #include <memory>
00016 #include <numeric>
00017
00019 namespace marray {
00020
00021 enum StringStyle {TableStyle, MatrixStyle};
00022 enum CoordinateOrder {FirstMajorOrder, LastMajorOrder};
00023 struct InitializationSkipping { };
00024
00025 static const bool Const = true;
00026 static const bool Mutable = false;
00027 static const CoordinateOrder defaultOrder = LastMajorOrder;
00028 static const InitializationSkipping SkipInitialization = InitializationSkipping();
00029
00030 template<class E, class T>
00031 class ViewExpression;
00032
00033 template<class E, class T, class UnaryFunctor>
00034 class UnaryViewExpression;
00035 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
00036 class BinaryViewExpression;
00037 template<class E, class T, class S, class BinaryFunctor>
00038 class BinaryViewExpressionScalarFirst;
00039 template<class E, class T, class S, class BinaryFunctor>
00040 class BinaryViewExpressionScalarSecond;
00041
00042 template<class T, bool isConst = false, class A = std::allocator<size_t> >
00043 class View;
00044 #ifdef HAVE_CPP0X_TEMPLATE_ALIASES
00045 template<class T, class A> using ConstView = View<T, true, A>;
00046 #endif
00047 template<class T, bool isConst, class A = std::allocator<size_t> >
00048 class Iterator;
00049 template<class T, class A = std::allocator<size_t> > class Vector;
00050 template<class T, class A = std::allocator<size_t> > class Matrix;
00051 template<class T, class A = std::allocator<size_t> > class Marray;
00052
00053
00054 #ifdef NDEBUG
00055 const bool MARRAY_NO_DEBUG = true;
00056 const bool MARRAY_NO_ARG_TEST = true;
00057 #else
00058 const bool MARRAY_NO_DEBUG = false;
00059 const bool MARRAY_NO_ARG_TEST = false;
00060 #endif
00061
00062
00063 namespace marray_detail {
00064
00065 template <bool PREDICATE, class TRUECASE, class FALSECASE>
00066 struct IfBool;
00067 template <class TRUECASE, class FALSECASE>
00068 struct IfBool<true, TRUECASE, FALSECASE>
00069 { typedef TRUECASE type; };
00070 template <class TRUECASE, class FALSECASE>
00071 struct IfBool<false, TRUECASE, FALSECASE>
00072 { typedef FALSECASE type; };
00073
00074 template <class T1, class T2>
00075 struct IsEqual
00076 { static const bool type = false; };
00077 template <class T>
00078 struct IsEqual<T, T>
00079 { static const bool type = true; };
00080
00081 template<class T> struct TypeTraits
00082 { static const unsigned char position = 255; };
00083 template<> struct TypeTraits<char>
00084 { static const unsigned char position = 0; };
00085 template<> struct TypeTraits<unsigned char>
00086 { static const unsigned char position = 1; };
00087 template<> struct TypeTraits<short>
00088 { static const unsigned char position = 2; };
00089 template<> struct TypeTraits<unsigned short>
00090 { static const unsigned char position = 3; };
00091 template<> struct TypeTraits<int>
00092 { static const unsigned char position = 4; };
00093 template<> struct TypeTraits<unsigned int>
00094 { static const unsigned char position = 5; };
00095 template<> struct TypeTraits<long>
00096 { static const unsigned char position = 6; };
00097 template<> struct TypeTraits<unsigned long>
00098 { static const unsigned char position = 7; };
00099 template<> struct TypeTraits<float>
00100 { static const unsigned char position = 8; };
00101 template<> struct TypeTraits<double>
00102 { static const unsigned char position = 9; };
00103 template<> struct TypeTraits<long double>
00104 { static const unsigned char position = 10; };
00105 template<class A, class B> struct PromoteType
00106 { typedef typename IfBool<TypeTraits<A>::position >= TypeTraits<B>::position, A, B>::type type; };
00107
00108
00109 template<class A> inline void Assert(A assertion) {
00110 if(!assertion) throw std::runtime_error("Assertion failed.");
00111 }
00112
00113
00114 template<class A = std::allocator<size_t> > class Geometry;
00115 template<class ShapeIterator, class StridesIterator>
00116 inline void stridesFromShape(ShapeIterator, ShapeIterator,
00117 StridesIterator, const CoordinateOrder& = defaultOrder);
00118
00119
00120 template<class Functor, class T, class A>
00121 inline void operate(View<T, false, A>&, Functor);
00122 template<class Functor, class T, class A>
00123 inline void operate(View<T, false, A>&, const T&, Functor);
00124 template<class Functor, class T1, class T2, bool isConst, class A>
00125 inline void operate(View<T1, false, A>&, const View<T2, isConst, A>&, Functor);
00126 template<class Functor, class T1, class A, class E, class T2>
00127 inline void operate(View<T1, false, A>& v, const ViewExpression<E, T2>& expression, Functor f);
00128
00129
00130 template<unsigned short N, class Functor, class T, class A>
00131 struct OperateHelperUnary;
00132 template<unsigned short N, class Functor, class T1, class T2, class A>
00133 struct OperateHelperBinaryScalar;
00134 template<unsigned short N, class Functor, class T1, class T2,
00135 bool isConst, class A1, class A2>
00136 struct OperateHelperBinary;
00137 template<bool isConstTo, class TFrom, class TTo, class AFrom, class ATo>
00138 struct AssignmentOperatorHelper;
00139 template<bool isIntegral>
00140 struct AccessOperatorHelper;
00141
00142
00143 template<class T>
00144 struct Negative { void operator()(T& x) { x = -x; } };
00145 template<class T>
00146 struct PrefixIncrement { void operator()(T& x) { ++x; } };
00147 template<class T>
00148 struct PostfixIncrement { void operator()(T& x) { x++; } };
00149 template<class T>
00150 struct PrefixDecrement { void operator()(T& x) { --x; } };
00151 template<class T>
00152 struct PostfixDecrement { void operator()(T& x) { x--; } };
00153
00154
00155 template<class T1, class T2>
00156 struct Assign { void operator()(T1& x, const T2& y) { x = y; } };
00157 template<class T1, class T2>
00158 struct PlusEqual { void operator()(T1& x, const T2& y) { x += y; } };
00159 template<class T1, class T2>
00160 struct MinusEqual { void operator()(T1& x, const T2& y) { x -= y; } };
00161 template<class T1, class T2>
00162 struct TimesEqual { void operator()(T1& x, const T2& y) { x *= y; } };
00163 template<class T1, class T2>
00164 struct DividedByEqual { void operator()(T1& x, const T2& y) { x /= y; } };
00165
00166
00167 template<class T>
00168 struct Negate { T operator()(const T& x) const { return -x; } };
00169
00170
00171 template<class T1, class T2, class U>
00172 struct Plus { U operator()(const T1& x, const T2& y) const { return x + y; } };
00173 template<class T1, class T2, class U>
00174 struct Minus { U operator()(const T1& x, const T2& y) const { return x - y; } };
00175 template<class T1, class T2, class U>
00176 struct Times { U operator()(const T1& x, const T2& y) const { return x * y; } };
00177 template<class T1, class T2, class U>
00178 struct DividedBy { U operator()(const T1& x, const T2& y) const { return x / y; } };
00179 }
00180
00181
00200 template<class T, bool isConst, class A>
00201 class View
00202 : public ViewExpression<View<T, isConst, A>, T>
00203 {
00204 public:
00205 typedef T value_type;
00206 typedef T ValueType;
00207 typedef typename marray_detail::IfBool<isConst, const T*, T*>::type pointer;
00208 typedef const T* const_pointer;
00209 typedef typename marray_detail::IfBool<isConst, const T&, T&>::type reference;
00210 typedef const T& const_reference;
00211 typedef Iterator<T, isConst, A> iterator;
00212 typedef Iterator<T, true, A> const_iterator;
00213 typedef std::reverse_iterator<iterator> reverse_iterator;
00214 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00215 typedef ViewExpression<View<T, isConst, A>, T> base;
00216 typedef typename A::template rebind<value_type>::other allocator_type;
00217
00218
00219 View(const allocator_type& = allocator_type());
00220 View(pointer, const allocator_type& = allocator_type());
00221 View(const View<T, false, A>&);
00222 template<class ShapeIterator>
00223 View(ShapeIterator, ShapeIterator, pointer,
00224 const CoordinateOrder& = defaultOrder,
00225 const CoordinateOrder& = defaultOrder,
00226 const allocator_type& = allocator_type());
00227 template<class ShapeIterator, class StrideIterator>
00228 View(ShapeIterator, ShapeIterator, StrideIterator,
00229 pointer, const CoordinateOrder&,
00230 const allocator_type& = allocator_type());
00231 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00232 View(std::initializer_list<size_t>, pointer,
00233 const CoordinateOrder& = defaultOrder,
00234 const CoordinateOrder& = defaultOrder,
00235 const allocator_type& = allocator_type());
00236 View(std::initializer_list<size_t>, std::initializer_list<size_t>,
00237 pointer, const CoordinateOrder&,
00238 const allocator_type& = allocator_type());
00239 #endif
00240
00241
00242 View<T, isConst, A>& operator=(const T&);
00243 View<T, isConst, A>& operator=(const View<T, true, A>&);
00244 View<T, isConst, A>& operator=(const View<T, false, A>&);
00245 template<class TLocal, bool isConstLocal, class ALocal>
00246 View<T, isConst, A>& operator=(const View<TLocal, isConstLocal, ALocal>&);
00247 template<class E, class Te>
00248 View<T, isConst, A>&
00249 operator=(const ViewExpression<E, Te>&);
00250
00251 void assign(const allocator_type& = allocator_type());
00252 template<class ShapeIterator>
00253 void assign(ShapeIterator, ShapeIterator, pointer,
00254 const CoordinateOrder& = defaultOrder,
00255 const CoordinateOrder& = defaultOrder,
00256 const allocator_type& = allocator_type());
00257 template<class ShapeIterator, class StrideIterator>
00258 void assign(ShapeIterator, ShapeIterator, StrideIterator,
00259 pointer, const CoordinateOrder&,
00260 const allocator_type& = allocator_type());
00261 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00262 void assign(std::initializer_list<size_t>, pointer,
00263 const CoordinateOrder& = defaultOrder,
00264 const CoordinateOrder& = defaultOrder,
00265 const allocator_type& = allocator_type());
00266 void assign(std::initializer_list<size_t>,
00267 std::initializer_list<size_t>, pointer,
00268 const CoordinateOrder&,
00269 const allocator_type& = allocator_type());
00270 #endif
00271
00272
00273 const size_t dimension() const;
00274 const size_t size() const;
00275 const size_t shape(const size_t) const;
00276 const size_t* shapeBegin() const;
00277 const size_t* shapeEnd() const;
00278 const size_t strides(const size_t) const;
00279 const size_t* stridesBegin() const;
00280 const size_t* stridesEnd() const;
00281 const CoordinateOrder& coordinateOrder() const;
00282 const bool isSimple() const;
00283 template<class TLocal, bool isConstLocal, class ALocal>
00284 bool overlaps(const View<TLocal, isConstLocal, ALocal>&) const;
00285
00286
00287 template<class U> reference operator()(U);
00288 template<class U> reference operator()(U) const;
00289 #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
00290 reference operator()(const size_t, const size_t);
00291 reference operator()(const size_t, const size_t) const;
00292 reference operator()(const size_t, const size_t, const size_t);
00293 reference operator()(const size_t, const size_t, const size_t) const;
00294 reference operator()(const size_t, const size_t, const size_t,
00295 const size_t);
00296 reference operator()(const size_t, const size_t, const size_t,
00297 const size_t) const;
00298 reference operator()(const size_t, const size_t, const size_t,
00299 const size_t, const size_t);
00300 reference operator()(const size_t, const size_t, const size_t,
00301 const size_t, const size_t) const;
00302 reference operator()(const size_t, const size_t, const size_t,
00303 const size_t, const size_t, const size_t, const size_t,
00304 const size_t, const size_t, const size_t);
00305 reference operator()(const size_t, const size_t, const size_t,
00306 const size_t, const size_t, const size_t, const size_t,
00307 const size_t, const size_t, const size_t) const;
00308 #else
00309 reference operator()(const size_t);
00310 reference operator()(const size_t) const;
00311 template<typename... Args>
00312 reference operator()(const size_t, const Args...);
00313 template<typename... Args>
00314 reference operator()(const size_t, const Args...) const;
00315 private:
00316 size_t elementAccessHelper(const size_t, const size_t);
00317 size_t elementAccessHelper(const size_t, const size_t) const;
00318 template<typename... Args>
00319 size_t elementAccessHelper(const size_t, const size_t,
00320 const Args...);
00321 template<typename... Args>
00322 size_t elementAccessHelper(const size_t, const size_t,
00323 const Args...) const;
00324 public:
00325 #endif
00326
00327
00328 template<class BaseIterator, class ShapeIterator>
00329 void view(BaseIterator, ShapeIterator, View<T, isConst, A>&) const;
00330 template<class BaseIterator, class ShapeIterator>
00331 void view(BaseIterator, ShapeIterator, const CoordinateOrder&,
00332 View<T, isConst, A>&) const;
00333 template<class BaseIterator, class ShapeIterator>
00334 View<T, isConst, A> view(BaseIterator, ShapeIterator) const;
00335 template<class BaseIterator, class ShapeIterator>
00336 View<T, isConst, A> view(BaseIterator, ShapeIterator,
00337 const CoordinateOrder&) const;
00338 template<class BaseIterator, class ShapeIterator>
00339 void constView(BaseIterator, ShapeIterator, View<T, true, A>&) const;
00340 template<class BaseIterator, class ShapeIterator>
00341 void constView(BaseIterator, ShapeIterator, const CoordinateOrder&,
00342 View<T, true, A>&) const;
00343 template<class BaseIterator, class ShapeIterator>
00344 View<T, true, A> constView(BaseIterator, ShapeIterator) const;
00345 template<class BaseIterator, class ShapeIterator>
00346 View<T, true, A> constView(BaseIterator, ShapeIterator,
00347 const CoordinateOrder&) const;
00348 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00349 void view(std::initializer_list<size_t>,
00350 std::initializer_list<size_t>, View<T, isConst, A>&) const;
00351 void view(std::initializer_list<size_t>,
00352 std::initializer_list<size_t>, const CoordinateOrder&,
00353 View<T, isConst, A>&) const;
00354 void constView(std::initializer_list<size_t>,
00355 std::initializer_list<size_t>, View<T, true, A>&) const;
00356 void constView(std::initializer_list<size_t>,
00357 std::initializer_list<size_t>, const CoordinateOrder&,
00358 View<T, true, A>&) const;
00359 #endif
00360
00361
00362 iterator begin();
00363 iterator end();
00364 const_iterator begin() const;
00365 const_iterator end() const;
00366 reverse_iterator rbegin();
00367 reverse_iterator rend();
00368 const_reverse_iterator rbegin() const;
00369 const_reverse_iterator rend() const;
00370
00371
00372 template<class ShapeIterator>
00373 void reshape(ShapeIterator, ShapeIterator);
00374 template<class CoordinateIterator>
00375 void permute(CoordinateIterator);
00376 void transpose(const size_t, const size_t);
00377 void transpose();
00378 void shift(const int);
00379 void squeeze();
00380
00381 template<class ShapeIterator>
00382 View<T, isConst, A> reshapedView(ShapeIterator, ShapeIterator) const;
00383 template<class CoordinateIterator>
00384 View<T, isConst, A> permutedView(CoordinateIterator) const;
00385 View<T, isConst, A> transposedView(const size_t, const size_t) const;
00386 View<T, isConst, A> transposedView() const;
00387 View<T, isConst, A> shiftedView(const int) const;
00388 View<T, isConst, A> boundView(const size_t, const size_t = 0) const;
00389 View<T, isConst, A> squeezedView() const;
00390
00391 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00392 void reshape(std::initializer_list<size_t>);
00393 void permute(std::initializer_list<size_t>);
00394
00395 View<T, isConst, A> reshapedView(std::initializer_list<size_t>) const;
00396 View<T, isConst, A> permutedView(std::initializer_list<size_t>) const;
00397 #endif
00398
00399
00400 template<class CoordinateIterator>
00401 void coordinatesToIndex(CoordinateIterator, size_t&) const;
00402 template<class CoordinateIterator>
00403 void coordinatesToOffset(CoordinateIterator, size_t&) const;
00404 template<class CoordinateIterator>
00405 void indexToCoordinates(size_t, CoordinateIterator) const;
00406 void indexToOffset(size_t, size_t&) const;
00407 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00408 void coordinatesToIndex(std::initializer_list<size_t>,
00409 size_t&) const;
00410 void coordinatesToOffset(std::initializer_list<size_t>,
00411 size_t&) const;
00412 #endif
00413
00414
00415 std::string asString(const StringStyle& = MatrixStyle) const;
00416
00417 private:
00418 typedef typename marray_detail::Geometry<A> geometry_type;
00419
00420 View(pointer, const geometry_type&);
00421
00422 void updateSimplicity();
00423 void testInvariant() const;
00424
00425
00426 const T& operator[](const size_t) const;
00427 T& operator[](const size_t);
00428
00429
00430 pointer data_;
00431 geometry_type geometry_;
00432
00433 template<class TLocal, bool isConstLocal, class ALocal>
00434 friend class View;
00435 template<class TLocal, class ALocal>
00436 friend class Marray;
00437 template<class TLocal, class ALocal>
00438 friend class Vector;
00439 template<class TLocal, class ALocal>
00440 friend class Matrix;
00441
00442 template<bool isConstTo, class TFrom, class TTo, class AFrom, class ATo>
00443 friend struct marray_detail::AssignmentOperatorHelper;
00444 friend struct marray_detail::AccessOperatorHelper<true>;
00445 friend struct marray_detail::AccessOperatorHelper<false>;
00446
00447 template<class E, class U>
00448 friend class ViewExpression;
00449 template<class E, class U, class UnaryFunctor>
00450 friend class UnaryViewExpression;
00451 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
00452 friend class BinaryViewExpression;
00453 template<class E, class U, class S, class BinaryFunctor>
00454 friend class BinaryViewExpressionScalarFirst;
00455 template<class E, class U, class S, class BinaryFunctor>
00456 friend class BinaryViewExpressionScalarSecond;
00457
00458 template<class Functor, class T1, class Alocal, class E, class T2>
00459 friend void marray_detail::operate(View<T1, false, Alocal>& v, const ViewExpression<E, T2>& expression, Functor f);
00460
00461 };
00462
00468 template<class T, bool isConst, class A>
00469 class Iterator
00470 {
00471 public:
00472
00473 typedef typename std::random_access_iterator_tag iterator_category;
00474 typedef T value_type;
00475
00476 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6
00477 typedef std::ptrdiff_t difference_type;
00478 #else
00479 typedef ptrdiff_t difference_type;
00480 #endif
00481 typedef typename marray_detail::IfBool<isConst, const T*, T*>::type pointer;
00482 typedef typename marray_detail::IfBool<isConst, const T&, T&>::type reference;
00483
00484
00485 typedef typename marray_detail::IfBool<isConst, const View<T, true, A>*,
00486 View<T, false, A>*>::type view_pointer;
00487 typedef typename marray_detail::IfBool<isConst, const View<T, true, A>&,
00488 View<T, false, A>&>::type view_reference;
00489
00490
00491 Iterator();
00492 Iterator(const View<T, false, A>&, const size_t = 0);
00493 Iterator(View<T, false, A>&, const size_t = 0);
00494 Iterator(const View<T, true, A>&, const size_t = 0);
00495 Iterator(const Iterator<T, false, A>&);
00496
00497
00498
00499 reference operator*() const;
00500 pointer operator->() const;
00501 reference operator[](const size_t) const;
00502 Iterator<T, isConst, A>& operator+=(const difference_type&);
00503 Iterator<T, isConst, A>& operator-=(const difference_type&);
00504 Iterator<T, isConst, A>& operator++();
00505
00506 Iterator<T, isConst, A>& operator--();
00507 Iterator<T, isConst, A> operator++(int);
00508 Iterator<T, isConst, A> operator--(int);
00509 Iterator<T, isConst, A> operator+(const difference_type&) const;
00510 Iterator<T, isConst, A> operator-(const difference_type&) const;
00511 template<bool isConstLocal>
00512 difference_type operator-(const Iterator<T, isConstLocal, A>&) const;
00513 template<bool isConstLocal>
00514 bool operator==(const Iterator<T, isConstLocal, A>&) const;
00515 template<bool isConstLocal>
00516 bool operator!=(const Iterator<T, isConstLocal, A>&) const;
00517 template<bool isConstLocal>
00518 bool operator<(const Iterator<T, isConstLocal, A>&) const;
00519 template<bool isConstLocal>
00520 bool operator>(const Iterator<T, isConstLocal, A>&) const;
00521 template<bool isConstLocal>
00522 bool operator<=(const Iterator<T, isConstLocal, A>&) const;
00523 template<bool isConstLocal>
00524 bool operator>=(const Iterator<T, isConstLocal, A>&) const;
00525
00526
00527 bool hasMore() const;
00528 size_t index() const;
00529 template<class CoordinateIterator>
00530 void coordinate(CoordinateIterator) const;
00531
00532 private:
00533 void testInvariant() const;
00534
00535
00536 view_pointer view_;
00537 pointer pointer_;
00538 size_t index_;
00539 std::vector<size_t> coordinates_;
00540
00541 friend class Marray<T, A>;
00542 friend class Iterator<T, !isConst, A>;
00543 };
00544
00546 template<class T, class A>
00547 class Marray
00548 : public View<T, false, A>
00549 {
00550 public:
00551 typedef View<T, false, A> base;
00552 typedef typename base::value_type value_type;
00553 typedef typename base::pointer pointer;
00554 typedef typename base::const_pointer const_pointer;
00555 typedef typename base::reference reference;
00556 typedef typename base::const_reference const_reference;
00557 typedef typename base::iterator iterator;
00558 typedef typename base::reverse_iterator reverse_iterator;
00559 typedef typename base::const_iterator const_iterator;
00560 typedef typename base::const_reverse_iterator const_reverse_iterator;
00561 typedef typename A::template rebind<value_type>::other allocator_type;
00562
00563
00564 Marray(const allocator_type& = allocator_type());
00565 Marray(const T&, const CoordinateOrder& = defaultOrder,
00566 const allocator_type& = allocator_type());
00567 template<class ShapeIterator>
00568 Marray(ShapeIterator, ShapeIterator, const T& = T(),
00569 const CoordinateOrder& = defaultOrder,
00570 const allocator_type& = allocator_type());
00571 template<class ShapeIterator>
00572 Marray(const InitializationSkipping&, ShapeIterator, ShapeIterator,
00573 const CoordinateOrder& = defaultOrder,
00574 const allocator_type& = allocator_type());
00575 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00576 Marray(std::initializer_list<size_t>, const T& = T(),
00577 const CoordinateOrder& = defaultOrder,
00578 const allocator_type& = allocator_type());
00579 #endif
00580 Marray(const Marray<T, A>&);
00581 template<class E, class Te>
00582 Marray(const ViewExpression<E, Te>&,
00583 const allocator_type& = allocator_type());
00584 template<class TLocal, bool isConstLocal, class ALocal>
00585 Marray(const View<TLocal, isConstLocal, ALocal>&);
00586 ~Marray();
00587
00588
00589 Marray<T, A>& operator=(const T&);
00590 Marray<T, A>& operator=(const Marray<T, A>&);
00591 template<class TLocal, bool isConstLocal, class ALocal>
00592 Marray<T, A>& operator=(const View<TLocal, isConstLocal, ALocal>&);
00593 template<class E, class Te>
00594 Marray<T, A>& operator=(const ViewExpression<E, Te>&);
00595 void assign(const allocator_type& = allocator_type());
00596
00597
00598 template<class ShapeIterator>
00599 void resize(ShapeIterator, ShapeIterator, const T& = T());
00600 template<class ShapeIterator>
00601 void resize(const InitializationSkipping&, ShapeIterator, ShapeIterator);
00602 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00603 void resize(std::initializer_list<size_t>, const T& = T());
00604 void resize(const InitializationSkipping&, std::initializer_list<size_t>);
00605 #endif
00606
00607 private:
00608 typedef typename base::geometry_type geometry_type;
00609
00610
00611 template<class CoordinateIterator>
00612 void permute(CoordinateIterator) {}
00613 void transpose(const size_t, const size_t) {}
00614 void transpose() {}
00615 void shift(const int) {}
00616 void squeeze() {}
00617
00618 void testInvariant() const;
00619 template<bool SKIP_INITIALIZATION, class ShapeIterator>
00620 void resizeHelper(ShapeIterator, ShapeIterator, const T& = T());
00621
00622 allocator_type dataAllocator_;
00623
00624 friend class Vector<T, A>;
00625 friend class Matrix<T, A>;
00626 };
00627
00629 template<class T, class A>
00630 class Vector
00631 : public Marray<T, A>
00632 {
00633 public:
00634 typedef Marray<T, A> base;
00635 typedef typename base::value_type value_type;
00636 typedef typename base::pointer pointer;
00637 typedef typename base::const_pointer const_pointer;
00638 typedef typename base::reference reference;
00639 typedef typename base::const_reference const_reference;
00640 typedef typename base::iterator iterator;
00641 typedef typename base::reverse_iterator reverse_iterator;
00642 typedef typename base::const_iterator const_iterator;
00643 typedef typename base::const_reverse_iterator const_reverse_iterator;
00644 typedef typename base::allocator_type allocator_type;
00645
00646
00647 Vector(const allocator_type& = allocator_type());
00648 template<class TLocal, bool isConstLocal, class ALocal>
00649 Vector(const View<TLocal, isConstLocal, ALocal>&);
00650 Vector(const size_t, const T& = T(),
00651 const allocator_type& = allocator_type());
00652 Vector(const InitializationSkipping&, const size_t,
00653 const allocator_type& = allocator_type());
00654 template<class E, class Te>
00655 Vector(const ViewExpression<E, Te>&,
00656 const allocator_type& = allocator_type());
00657 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00658 Vector(std::initializer_list<T> list,
00659 const allocator_type& = allocator_type());
00660 #endif
00661
00662
00663 Vector<T, A>& operator=(const T&);
00664 Vector<T, A>& operator=(const Vector<T, A>&);
00665 template<class TLocal, bool isConstLocal, class ALocal>
00666 Vector<T, A>& operator=(const View<TLocal, isConstLocal, ALocal>&);
00667 template<class E, class Te>
00668 Vector<T, A>& operator=(const ViewExpression<E, Te>&);
00669
00670
00671 T& operator[](const size_t);
00672 const T& operator[](const size_t) const;
00673
00674
00675 void reshape(const size_t);
00676 void resize(const size_t, const T& = T());
00677 void resize(const InitializationSkipping&, const size_t);
00678
00679 private:
00680 void testInvariant() const;
00681 };
00682
00684 template<class T, class A>
00685 class Matrix
00686 : public Marray<T, A>
00687 {
00688 public:
00689 typedef Marray<T, A> base;
00690
00691 typedef typename base::value_type value_type;
00692 typedef typename base::pointer pointer;
00693
00694 typedef typename base::const_pointer const_pointer;
00695 typedef typename base::reference reference;
00696 typedef typename base::const_reference const_reference;
00697 typedef typename base::iterator iterator;
00698 typedef typename base::reverse_iterator reverse_iterator;
00699 typedef typename base::const_iterator const_iterator;
00700 typedef typename base::const_reverse_iterator const_reverse_iterator;
00701 typedef typename base::allocator_type allocator_type;
00702
00703
00704 Matrix(const allocator_type& = allocator_type());
00705 template<class TLocal, bool isConstLocal, class ALocal>
00706 Matrix(const View<TLocal, isConstLocal, ALocal>&);
00707 Matrix(const size_t, const size_t, const T& = T(),
00708 const CoordinateOrder& = defaultOrder,
00709 const allocator_type& = allocator_type());
00710 Matrix(const InitializationSkipping&,
00711 const size_t, const size_t,
00712 const CoordinateOrder& = defaultOrder,
00713 const allocator_type& = allocator_type());
00714 template<class E, class Te>
00715 Matrix(const ViewExpression<E, Te>&,
00716 const allocator_type& = allocator_type());
00717
00718
00719 Matrix<T, A>& operator=(const T&);
00720 Matrix<T, A>& operator=(const Matrix<T, A>&);
00721
00722 template<class TLocal, bool isConstLocal, class ALocal>
00723 Matrix<T, A>& operator=(const View<TLocal, isConstLocal, ALocal>&);
00724 template<class E, class Te>
00725 Matrix<T, A>& operator=(const ViewExpression<E, Te>&);
00726
00727
00728 void reshape(const size_t, const size_t);
00729 void resize(const size_t, const size_t, const T& = T());
00730 void resize(const InitializationSkipping&, const size_t, const size_t);
00731
00732 private:
00733 void testInvariant() const;
00734 };
00735
00736
00737
00738 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00739
00740
00741
00742
00743
00744
00745 template<class T, bool isConst, class A>
00746 inline void
00747 View<T, isConst, A>::coordinatesToIndex
00748 (
00749 std::initializer_list<size_t> coordinate,
00750 size_t& out
00751 ) const
00752 {
00753 coordinatesToIndex(coordinate.begin(), out);
00754 }
00755 #endif
00756
00763 template<class T, bool isConst, class A>
00764 template<class CoordinateIterator>
00765 inline void
00766 View<T, isConst, A>::coordinatesToIndex
00767 (
00768 CoordinateIterator it,
00769 size_t& out
00770 ) const
00771 {
00772 testInvariant();
00773 out = 0;
00774 for(size_t j=0; j<this->dimension(); ++j, ++it) {
00775 marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<size_t>(*it) < shape(j));
00776 out += static_cast<size_t>(*it) * geometry_.shapeStrides(j);
00777 }
00778 }
00779
00780 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
00781
00782
00783
00784
00785
00786
00787 template<class T, bool isConst, class A>
00788 inline void
00789 View<T, isConst, A>::coordinatesToOffset
00790 (
00791 std::initializer_list<size_t> coordinate,
00792 size_t& out
00793 ) const
00794 {
00795 coordinatesToOffset(coordinate.begin(), out);
00796 }
00797 #endif
00798
00805 template<class T, bool isConst, class A>
00806 template<class CoordinateIterator>
00807 inline void
00808 View<T, isConst, A>::coordinatesToOffset
00809 (
00810 CoordinateIterator it,
00811 size_t& out
00812 ) const
00813 {
00814 testInvariant();
00815 out = 0;
00816 for(size_t j=0; j<this->dimension(); ++j, ++it) {
00817 marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<size_t>(*it) < shape(j));
00818 out += static_cast<size_t>(*it) * strides(j);
00819 }
00820 }
00821
00829 template<class T, bool isConst, class A>
00830 template<class CoordinateIterator>
00831 inline void
00832 View<T, isConst, A>::indexToCoordinates
00833 (
00834 size_t index,
00835 CoordinateIterator outit
00836 ) const
00837 {
00838 testInvariant();
00839 marray_detail::Assert(MARRAY_NO_DEBUG || this->dimension() > 0);
00840 marray_detail::Assert(MARRAY_NO_ARG_TEST || index < this->size());
00841 if(coordinateOrder() == FirstMajorOrder) {
00842 for(size_t j=0; j<this->dimension(); ++j, ++outit) {
00843 *outit = size_t(index / geometry_.shapeStrides(j));
00844 index = index % geometry_.shapeStrides(j);
00845 }
00846 }
00847 else {
00848 size_t j = this->dimension()-1;
00849 outit += j;
00850 for(;;) {
00851 *outit = size_t(index / geometry_.shapeStrides(j));
00852 index = index % geometry_.shapeStrides(j);
00853 if(j == 0) {
00854 break;
00855 }
00856 else {
00857 --outit;
00858 --j;
00859 }
00860 }
00861 }
00862 }
00863
00870 template<class T, bool isConst, class A>
00871 inline void
00872 View<T, isConst, A>::indexToOffset
00873 (
00874 size_t index,
00875 size_t& out
00876 ) const
00877 {
00878 testInvariant();
00879 marray_detail::Assert(MARRAY_NO_ARG_TEST || index < this->size());
00880 if(isSimple()) {
00881 out = index;
00882 }
00883 else {
00884 out = 0;
00885 if(coordinateOrder() == FirstMajorOrder) {
00886 for(size_t j=0; j<this->dimension(); ++j) {
00887 out += geometry_.strides(j) * (index / geometry_.shapeStrides(j));
00888 index = index % geometry_.shapeStrides(j);
00889 }
00890 }
00891 else {
00892 if(this->dimension() == 0) {
00893 marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
00894 return;
00895 }
00896 else {
00897 size_t j = this->dimension()-1;
00898 for(;;) {
00899 out += geometry_.strides(j) * (index / geometry_.shapeStrides(j));
00900 index = index % geometry_.shapeStrides(j);
00901 if(j == 0) {
00902 break;
00903 }
00904 else {
00905 --j;
00906 }
00907 }
00908 }
00909 }
00910 }
00911 }
00912
00920 template<class T, bool isConst, class A>
00921 inline
00922 View<T, isConst, A>::View
00923 (
00924 const allocator_type& allocator
00925 )
00926 : data_(0),
00927 geometry_(geometry_type(allocator))
00928 {
00929 testInvariant();
00930 }
00931
00932
00933 template<class T, bool isConst, class A>
00934 inline
00935 View<T, isConst, A>::View
00936 (
00937 pointer data,
00938 const geometry_type& geometry
00939 )
00940 : data_(data),
00941 geometry_(geometry)
00942 {
00943 testInvariant();
00944 }
00945
00951 template<class T, bool isConst, class A>
00952 inline
00953 View<T, isConst, A>::View
00954 (
00955 pointer data,
00956 const allocator_type& allocator
00957 )
00958 : data_(data),
00959 geometry_(geometry_type(0, defaultOrder, 1, true, allocator))
00960 {
00961 testInvariant();
00962 }
00963
00968 template<class T, bool isConst, class A>
00969 inline
00970 View<T, isConst, A>::View
00971 (
00972 const View<T, false, A>& in
00973 )
00974 : data_(in.data_),
00975 geometry_(in.geometry_)
00976 {
00977 testInvariant();
00978 }
00979
00992
00993 template<class T, bool isConst, class A>
00994 template<class ShapeIterator>
00995 inline
00996 View<T, isConst, A>::View
00997 (
00998 ShapeIterator begin,
00999 ShapeIterator end,
01000 pointer data,
01001 const CoordinateOrder& externalCoordinateOrder,
01002 const CoordinateOrder& internalCoordinateOrder,
01003 const allocator_type& allocator
01004 )
01005 : data_(data),
01006 geometry_(begin, end, externalCoordinateOrder,
01007 internalCoordinateOrder, allocator)
01008 {
01009 testInvariant();
01010 }
01011
01024 template<class T, bool isConst, class A>
01025 template<class ShapeIterator, class StrideIterator>
01026 inline
01027 View<T, isConst, A>::View
01028 (
01029 ShapeIterator begin,
01030 ShapeIterator end,
01031 StrideIterator it,
01032 pointer data,
01033 const CoordinateOrder& internalCoordinateOrder,
01034 const allocator_type& allocator
01035 )
01036 : data_(data),
01037 geometry_(begin, end, it, internalCoordinateOrder, allocator)
01038 {
01039 testInvariant();
01040 }
01041
01042 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 template<class T, bool isConst, class A>
01054 inline
01055 View<T, isConst, A>::View
01056 (
01057 std::initializer_list<size_t> shape,
01058 pointer data,
01059 const CoordinateOrder& externalCoordinateOrder,
01060 const CoordinateOrder& internalCoordinateOrder,
01061 const allocator_type& allocator
01062 )
01063 : data_(data),
01064 geometry_(shape.begin(), shape.end(), externalCoordinateOrder,
01065 internalCoordinateOrder, allocator)
01066 {
01067 testInvariant();
01068 }
01069
01078 template<class T, bool isConst, class A>
01079 inline
01080 View<T, isConst, A>::View
01081 (
01082 std::initializer_list<size_t> shape,
01083 std::initializer_list<size_t> strides,
01084 pointer data,
01085 const CoordinateOrder& internalCoordinateOrder,
01086 const allocator_type& allocator
01087 )
01088 : data_(data),
01089 geometry_(shape.begin(), shape.end(), strides.begin(),
01090 internalCoordinateOrder, allocator)
01091 {
01092 testInvariant();
01093 }
01094 #endif
01095
01103 template<class T, bool isConst, class A>
01104 inline void
01105 View<T, isConst, A>::assign
01106 (
01107 const allocator_type& allocator
01108 )
01109 {
01110 geometry_ = geometry_type(allocator);
01111 data_ = 0;
01112 testInvariant();
01113 }
01114
01127 template<class T, bool isConst, class A>
01128 template<class ShapeIterator>
01129 inline void
01130 View<T, isConst, A>::assign
01131 (
01132 ShapeIterator begin,
01133 ShapeIterator end,
01134 pointer data,
01135 const CoordinateOrder& externalCoordinateOrder,
01136 const CoordinateOrder& internalCoordinateOrder,
01137 const allocator_type& allocator
01138 )
01139 {
01140
01141
01142
01143 geometry_ = typename marray_detail::Geometry<A>(begin, end,
01144 externalCoordinateOrder, internalCoordinateOrder, allocator);
01145 data_ = data;
01146 testInvariant();
01147 }
01148
01161 template<class T, bool isConst, class A>
01162 template<class ShapeIterator, class StrideIterator>
01163 inline void
01164 View<T, isConst, A>::assign
01165 (
01166 ShapeIterator begin,
01167 ShapeIterator end,
01168 StrideIterator it,
01169 pointer data,
01170 const CoordinateOrder& internalCoordinateOrder,
01171 const allocator_type& allocator
01172 )
01173 {
01174
01175
01176
01177 geometry_ = typename marray_detail::Geometry<A>(begin, end,
01178 it, internalCoordinateOrder, allocator);
01179 data_ = data;
01180 testInvariant();
01181 }
01182
01183 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 template<class T, bool isConst, class A>
01195 inline void
01196 View<T, isConst, A>::assign
01197 (
01198 std::initializer_list<size_t> shape,
01199 pointer data,
01200 const CoordinateOrder& externalCoordinateOrder,
01201 const CoordinateOrder& internalCoordinateOrder,
01202 const allocator_type& allocator
01203 )
01204 {
01205 assign(shape.begin(), shape.end(), data, externalCoordinateOrder,
01206 internalCoordinateOrder, allocator);
01207 }
01208
01219 template<class T, bool isConst, class A>
01220 inline void
01221 View<T, isConst, A>::assign
01222 (
01223 std::initializer_list<size_t> shape,
01224 std::initializer_list<size_t> strides,
01225 pointer data,
01226 const CoordinateOrder& internalCoordinateOrder,
01227 const allocator_type& allocator
01228 )
01229 {
01230 assign(shape.begin(), shape.end(), strides.begin(), data,
01231 internalCoordinateOrder, allocator);
01232 }
01233 #endif
01234
01242 template<class T, bool isConst, class A>
01243 template<class U>
01244 inline typename View<T, isConst, A>::reference
01245 View<T, isConst, A>::operator()
01246 (
01247 U u
01248 )
01249 {
01250 return marray_detail::AccessOperatorHelper<std::numeric_limits<U>::is_integer>::execute(*this, u);
01251 }
01252
01260 template<class T, bool isConst, class A>
01261 template<class U>
01262 inline typename View<T, isConst, A>::reference
01263 View<T, isConst, A>::operator()
01264 (
01265 U u
01266 ) const
01267 {
01268 return marray_detail::AccessOperatorHelper<std::numeric_limits<U>::is_integer>::execute(*this, u);
01269 }
01270
01271 #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
01272
01281 template<class T, bool isConst, class A>
01282 inline typename View<T, isConst, A>::reference
01283 View<T, isConst, A>::operator()
01284 (
01285 const size_t c0,
01286 const size_t c1
01287 )
01288 {
01289 testInvariant();
01290 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 2));
01291 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)));
01292 return data_[c0*strides(0) + c1*strides(1)];
01293 }
01294
01303 template<class T, bool isConst, class A>
01304 inline typename View<T, isConst, A>::reference
01305 View<T, isConst, A>::operator()
01306 (
01307 const size_t c0,
01308 const size_t c1
01309 ) const
01310 {
01311 testInvariant();
01312 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 2));
01313 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)));
01314 return data_[c0*strides(0) + c1*strides(1)];
01315 }
01316
01326 template<class T, bool isConst, class A>
01327 inline typename View<T, isConst, A>::reference
01328 View<T, isConst, A>::operator()
01329 (
01330 const size_t c0,
01331 const size_t c1,
01332 const size_t c2
01333 )
01334 {
01335 testInvariant();
01336 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 3));
01337 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01338 && c2 < shape(2)));
01339 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)];
01340 }
01341
01351 template<class T, bool isConst, class A>
01352 inline typename View<T, isConst, A>::reference
01353 View<T, isConst, A>::operator()
01354 (
01355 const size_t c0,
01356 const size_t c1,
01357 const size_t c2
01358 ) const
01359 {
01360 testInvariant();
01361 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 3));
01362 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01363 && c2 < shape(2)));
01364 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)];
01365 }
01366
01377 template<class T, bool isConst, class A>
01378 inline typename View<T, isConst, A>::reference
01379 View<T, isConst, A>::operator()
01380 (
01381 const size_t c0,
01382 const size_t c1,
01383 const size_t c2,
01384 const size_t c3
01385 )
01386 {
01387 testInvariant();
01388 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 4));
01389 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01390 && c2 < shape(2) && c3 < shape(3)));
01391 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01392 + c3*strides(3)];
01393 }
01394
01405 template<class T, bool isConst, class A>
01406 inline typename View<T, isConst, A>::reference
01407 View<T, isConst, A>::operator()
01408 (
01409 const size_t c0,
01410 const size_t c1,
01411 const size_t c2,
01412 const size_t c3
01413 ) const
01414 {
01415 testInvariant();
01416 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 4));
01417 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01418 && c2 < shape(2) && c3 < shape(3)));
01419 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01420 + c3*strides(3)];
01421 }
01422
01434 template<class T, bool isConst, class A>
01435 inline typename View<T, isConst, A>::reference
01436 View<T, isConst, A>::operator()
01437 (
01438 const size_t c0,
01439 const size_t c1,
01440 const size_t c2,
01441 const size_t c3,
01442 const size_t c4
01443 )
01444 {
01445 testInvariant();
01446 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 5));
01447 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01448 && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)));
01449 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01450 + c3*strides(3) + c4*strides(4)];
01451 }
01452
01464 template<class T, bool isConst, class A>
01465 inline typename View<T, isConst, A>::reference
01466 View<T, isConst, A>::operator()
01467 (
01468 const size_t c0,
01469 const size_t c1,
01470 const size_t c2,
01471 const size_t c3,
01472 const size_t c4
01473 ) const
01474 {
01475 testInvariant();
01476 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 5));
01477 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01478 && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)));
01479 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01480 + c3*strides(3) + c4*strides(4)];
01481 }
01482
01486
01500 template<class T, bool isConst, class A>
01501 inline typename View<T, isConst, A>::reference
01502 View<T, isConst, A>::operator()
01503 (
01504 const size_t c0,
01505 const size_t c1,
01506 const size_t c2,
01507 const size_t c3,
01508 const size_t c4,
01509 const size_t c5,
01510 const size_t c6,
01511 const size_t c7,
01512 const size_t c8,
01513 const size_t c9
01514 )
01515 {
01516 testInvariant();
01517 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 10));
01518 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01519 && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)
01520 && c5 < shape(5) && c6 < shape(6) && c7 < shape(7)
01521 && c8 < shape(8) && c9 < shape(9)));
01522 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01523 + c3*strides(3) + c4*strides(4) + c5*strides(5) + c6*strides(6)
01524 + c7*strides(7) + c8*strides(8) + c9*strides(9)];
01525 }
01526
01543 template<class T, bool isConst, class A>
01544 inline typename View<T, isConst, A>::reference
01545 View<T, isConst, A>::operator()
01546 (
01547 const size_t c0,
01548 const size_t c1,
01549 const size_t c2,
01550 const size_t c3,
01551 const size_t c4,
01552 const size_t c5,
01553 const size_t c6,
01554 const size_t c7,
01555 const size_t c8,
01556 const size_t c9
01557 ) const
01558 {
01559 testInvariant();
01560 marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 10));
01561 marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
01562 && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)
01563 && c5 < shape(5) && c6 < shape(6) && c7 < shape(7)
01564 && c8 < shape(8) && c9 < shape(9)));
01565 return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
01566 + c3*strides(3) + c4*strides(4) + c5*strides(5) + c6*strides(6)
01567 + c7*strides(7) + c8*strides(8) + c9*strides(9)];
01568 }
01569
01570 #else
01571
01572 template<class T, bool isConst, class A>
01573 inline size_t
01574 View<T, isConst, A>::elementAccessHelper
01575 (
01576 const size_t Dim,
01577 const size_t value
01578 )
01579 {
01580 marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1) ) );
01581 return strides(Dim-1) * value;
01582 }
01583
01584 template<class T, bool isConst, class A>
01585 inline size_t
01586 View<T, isConst, A>::elementAccessHelper
01587 (
01588 const size_t Dim,
01589 const size_t value
01590 ) const
01591 {
01592 marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1) ) );
01593 return strides(Dim-1) * value;
01594 }
01595
01596 template<class T, bool isConst, class A>
01597 template<typename... Args>
01598 inline size_t
01599 View<T, isConst, A>::elementAccessHelper
01600 (
01601 const size_t Dim,
01602 const size_t value,
01603 const Args... args
01604 )
01605 {
01606 marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1-sizeof...(args)) ) );
01607 return value * strides(Dim-1-sizeof...(args)) + elementAccessHelper(Dim, args...);
01608 }
01609
01610 template<class T, bool isConst, class A>
01611 template<typename... Args>
01612 inline size_t
01613 View<T, isConst, A>::elementAccessHelper
01614 (
01615 const size_t Dim,
01616 const size_t value,
01617 const Args... args
01618 ) const
01619 {
01620 marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1-sizeof...(args)) ) );
01621 return value * strides(Dim-1-sizeof...(args)) + elementAccessHelper(Dim, args...);
01622 }
01623
01624 template<class T, bool isConst, class A>
01625 inline typename View<T, isConst, A>::reference
01626 View<T, isConst, A>::operator()
01627 (
01628 const size_t value
01629 )
01630 {
01631 testInvariant();
01632 if(dimension() == 0) {
01633 marray_detail::Assert(MARRAY_NO_ARG_TEST || value == 0);
01634 return data_[0];
01635 }
01636 else {
01637 size_t offset;
01638 indexToOffset(value, offset);
01639 return data_[offset];
01640 }
01641 }
01642
01643 template<class T, bool isConst, class A>
01644 inline typename View<T, isConst, A>::reference
01645 View<T, isConst, A>::operator()
01646 (
01647 const size_t value
01648 ) const
01649 {
01650 testInvariant();
01651 if(dimension() == 0) {
01652 marray_detail::Assert(MARRAY_NO_ARG_TEST || value == 0);
01653 return data_[0];
01654 }
01655 else {
01656 size_t offset;
01657 indexToOffset(value, offset);
01658 return data_[offset];
01659 }
01660 }
01661
01662 template<class T, bool isConst, class A>
01663 template<typename... Args>
01664 inline typename View<T, isConst, A>::reference
01665 View<T, isConst, A>::operator()
01666 (
01667 const size_t value,
01668 const Args... args
01669 )
01670 {
01671 testInvariant();
01672 marray_detail::Assert( MARRAY_NO_DEBUG || ( data_ != 0 && sizeof...(args)+1 == dimension() ) );
01673 return data_[strides(0)*value + elementAccessHelper(sizeof...(args)+1, args...) ];
01674 }
01675
01676 template<class T, bool isConst, class A>
01677 template<typename... Args>
01678 inline typename View<T, isConst, A>::reference
01679 View<T, isConst, A>::operator()
01680 (
01681 const size_t value,
01682 const Args... args
01683 ) const
01684 {
01685 testInvariant();
01686 marray_detail::Assert( MARRAY_NO_DEBUG || ( data_ != 0 && sizeof...(args)+1 == dimension() ) );
01687 return data_[ strides(0) * static_cast<size_t>(value)
01688 + static_cast<size_t>(elementAccessHelper(sizeof...(args)+1, args...)) ];
01689 }
01690
01691 #endif // #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
01692
01697 template<class T, bool isConst, class A>
01698 inline const size_t
01699 View<T, isConst, A>::size() const
01700 {
01701 return geometry_.size();
01702 }
01703
01710 template<class T, bool isConst, class A>
01711 inline const size_t
01712 View<T, isConst, A>::dimension() const
01713 {
01714 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
01715 return geometry_.dimension();
01716 }
01717
01723 template<class T, bool isConst, class A>
01724 inline const size_t
01725 View<T, isConst, A>::shape
01726 (
01727 const size_t dimension
01728 ) const
01729 {
01730 testInvariant();
01731 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01732 marray_detail::Assert(MARRAY_NO_ARG_TEST || dimension < this->dimension());
01733 return geometry_.shape(dimension);
01734 }
01735
01741 template<class T, bool isConst, class A>
01742 inline const size_t*
01743 View<T, isConst, A>::shapeBegin() const
01744 {
01745 testInvariant();
01746 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01747 return geometry_.shapeBegin();
01748 }
01749
01755 template<class T, bool isConst, class A>
01756 inline const size_t*
01757 View<T, isConst, A>::shapeEnd() const
01758 {
01759 testInvariant();
01760 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01761 return geometry_.shapeEnd();
01762 }
01763
01769 template<class T, bool isConst, class A>
01770 inline const size_t
01771 View<T, isConst, A>::strides
01772 (
01773 const size_t dimension
01774 ) const
01775 {
01776 testInvariant();
01777 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01778 marray_detail::Assert(MARRAY_NO_ARG_TEST || dimension < this->dimension());
01779 return geometry_.strides(dimension);
01780 }
01781
01787 template<class T, bool isConst, class A>
01788 inline const size_t*
01789 View<T, isConst, A>::stridesBegin() const
01790 {
01791 testInvariant();
01792 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01793 return geometry_.stridesBegin();
01794 }
01795
01801 template<class T, bool isConst, class A>
01802 inline const size_t*
01803 View<T, isConst, A>::stridesEnd() const
01804 {
01805 testInvariant();
01806 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01807 return geometry_.stridesEnd();
01808 }
01809
01814 template<class T, bool isConst, class A>
01815 inline const CoordinateOrder&
01816 View<T, isConst, A>::coordinateOrder() const
01817 {
01818 testInvariant();
01819 return geometry_.coordinateOrder();
01820 }
01821
01826 template<class T, bool isConst, class A>
01827 inline const bool
01828 View<T, isConst, A>::isSimple() const
01829 {
01830 testInvariant();
01831 return geometry_.isSimple();
01832 }
01833
01873 template<class T, bool isConst, class A>
01874 inline View<T, isConst, A>&
01875 View<T, isConst, A>::operator=
01876 (
01877 const View<T, true, A>& in
01878 )
01879 {
01880 testInvariant();
01881 marray_detail::AssignmentOperatorHelper<isConst, T, T, A, A>::execute(in, *this);
01882 testInvariant();
01883 return *this;
01884 }
01885
01888 template<class T, bool isConst, class A>
01889 inline View<T, isConst, A>&
01890 View<T, isConst, A>::operator=
01891 (
01892 const View<T, false, A>& in
01893 )
01894 {
01895 testInvariant();
01896 marray_detail::AssignmentOperatorHelper<isConst, T, T, A, A>::execute(in, *this);
01897 testInvariant();
01898 return *this;
01899 }
01900
01903 template<class T, bool isConst, class A>
01904 template<class TLocal, bool isConstLocal, class ALocal>
01905 inline View<T, isConst, A>&
01906 View<T, isConst, A>::operator=
01907 (
01908 const View<TLocal, isConstLocal, ALocal>& in
01909 )
01910 {
01911 testInvariant();
01912 marray_detail::AssignmentOperatorHelper<isConst, TLocal, T, ALocal, A>::execute(in, *this);
01913 testInvariant();
01914 return *this;
01915 }
01916
01923 template<class T, bool isConst, class A>
01924 inline View<T, isConst, A>&
01925 View<T, isConst, A>::operator=
01926 (
01927 const T& value
01928 )
01929 {
01930 marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
01931 if(isSimple()) {
01932 for(size_t j=0; j<geometry_.size(); ++j) {
01933 data_[j] = value;
01934 }
01935 }
01936 else if(dimension() == 1)
01937 marray_detail::OperateHelperBinaryScalar<1, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01938 else if(dimension() == 2)
01939 marray_detail::OperateHelperBinaryScalar<2, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01940 else if(dimension() == 3)
01941 marray_detail::OperateHelperBinaryScalar<3, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01942 else if(dimension() == 4)
01943 marray_detail::OperateHelperBinaryScalar<4, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01944 else if(dimension() == 5)
01945 marray_detail::OperateHelperBinaryScalar<5, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01946 else if(dimension() == 6)
01947 marray_detail::OperateHelperBinaryScalar<6, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01948 else if(dimension() == 7)
01949 marray_detail::OperateHelperBinaryScalar<7, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01950 else if(dimension() == 8)
01951 marray_detail::OperateHelperBinaryScalar<8, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01952 else if(dimension() == 9)
01953 marray_detail::OperateHelperBinaryScalar<9, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01954 else if(dimension() == 10)
01955 marray_detail::OperateHelperBinaryScalar<10, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
01956 else {
01957 for(iterator it = begin(); it.hasMore(); ++it) {
01958 *it = value;
01959 }
01960 }
01961 return *this;
01962 }
01963
01964 template<class T, bool isConst, class A>
01965 template<class E, class Te>
01966 inline View<T, isConst, A>&
01967 View<T, isConst, A>::operator=
01968 (
01969 const ViewExpression<E, Te>& expression
01970 )
01971 {
01972 marray_detail::operate(*this, expression, marray_detail::Assign<T, Te>());
01973 return *this;
01974 }
01975
01984 template<class T, bool isConst, class A>
01985 template<class BaseIterator, class ShapeIterator>
01986 inline void
01987 View<T, isConst, A>::view
01988 (
01989 BaseIterator bit,
01990 ShapeIterator sit,
01991 View<T, isConst, A>& out
01992 ) const
01993 {
01994 view(bit, sit, coordinateOrder(), out);
01995 }
01996
02007 template<class T, bool isConst, class A>
02008 template<class BaseIterator, class ShapeIterator>
02009 inline void
02010 View<T, isConst, A>::view
02011 (
02012 BaseIterator bit,
02013 ShapeIterator sit,
02014 const CoordinateOrder& internalCoordinateOrder,
02015 View<T, isConst, A>& out
02016 ) const
02017 {
02018 testInvariant();
02019 size_t offset = 0;
02020 coordinatesToOffset(bit, offset);
02021 out.assign(sit, sit+dimension(), geometry_.stridesBegin(),
02022 data_+offset, internalCoordinateOrder);
02023 }
02024
02033 template<class T, bool isConst, class A>
02034 template<class BaseIterator, class ShapeIterator>
02035 inline View<T, isConst, A>
02036 View<T, isConst, A>::view
02037 (
02038 BaseIterator bit,
02039 ShapeIterator sit
02040 ) const
02041 {
02042 View<T, isConst, A> v;
02043 this->view(bit, sit, v);
02044 return v;
02045 }
02046
02057 template<class T, bool isConst, class A>
02058 template<class BaseIterator, class ShapeIterator>
02059 inline View<T, isConst, A>
02060 View<T, isConst, A>::view
02061 (
02062 BaseIterator bit,
02063 ShapeIterator sit,
02064 const CoordinateOrder& internalCoordinateOrder
02065 ) const
02066 {
02067 View<T, isConst, A> v;
02068 this->view(bit, sit, internalCoordinateOrder, v);
02069 return v;
02070 }
02071
02081 template<class T, bool isConst, class A>
02082 template<class BaseIterator, class ShapeIterator>
02083 inline void
02084 View<T, isConst, A>::constView
02085 (
02086 BaseIterator bit,
02087 ShapeIterator sit,
02088 View<T, true, A>& out
02089 ) const
02090 {
02091 constView(bit, sit, coordinateOrder(), out);
02092 }
02093
02104 template<class T, bool isConst, class A>
02105 template<class BaseIterator, class ShapeIterator>
02106 inline void
02107 View<T, isConst, A>::constView
02108 (
02109 BaseIterator bit,
02110 ShapeIterator sit,
02111 const CoordinateOrder& internalCoordinateOrder,
02112 View<T, true, A>& out
02113 ) const
02114 {
02115 testInvariant();
02116 size_t offset = 0;
02117 coordinatesToOffset(bit, offset);
02118 out.assign(sit, sit+dimension(),
02119 geometry_.stridesBegin(),
02120 static_cast<const T*>(data_) + offset,
02121 internalCoordinateOrder);
02122 }
02123
02133 template<class T, bool isConst, class A>
02134 template<class BaseIterator, class ShapeIterator>
02135 inline View<T, true, A>
02136 View<T, isConst, A>::constView
02137 (
02138 BaseIterator bit,
02139 ShapeIterator sit
02140 ) const
02141 {
02142 View<T, true, A> v;
02143 this->constView(bit, sit, v);
02144 return v;
02145 }
02146
02157 template<class T, bool isConst, class A>
02158 template<class BaseIterator, class ShapeIterator>
02159 inline View<T, true, A>
02160 View<T, isConst, A>::constView
02161 (
02162 BaseIterator bit,
02163 ShapeIterator sit,
02164 const CoordinateOrder& internalCoordinateOrder
02165 ) const
02166 {
02167 View<T, true, A> v;
02168 this->constView(bit, sit, internalCoordinateOrder, v);
02169 return v;
02170 }
02171
02172 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182 template<class T, bool isConst, class A>
02183 inline void
02184 View<T, isConst, A>::view
02185 (
02186 std::initializer_list<size_t> b,
02187 std::initializer_list<size_t> s,
02188 const CoordinateOrder& internalCoordinateOrder,
02189 View<T, isConst, A>& out
02190 ) const
02191 {
02192 view(b.begin(), s.begin(), internalCoordinateOrder, out);
02193 }
02194
02203 template<class T, bool isConst, class A>
02204 inline void
02205 View<T, isConst, A>::view
02206 (
02207 std::initializer_list<size_t> b,
02208 std::initializer_list<size_t> s,
02209 View<T, isConst, A>& out
02210 ) const
02211 {
02212 view(b.begin(), s.begin(), coordinateOrder(), out);
02213 }
02214
02224 template<class T, bool isConst, class A>
02225 inline void
02226 View<T, isConst, A>::constView
02227 (
02228 std::initializer_list<size_t> b,
02229 std::initializer_list<size_t> s,
02230 const CoordinateOrder& internalCoordinateOrder,
02231 View<T, true, A>& out
02232 ) const
02233 {
02234 constView(b.begin(), s.begin(), internalCoordinateOrder, out);
02235 }
02236
02246 template<class T, bool isConst, class A>
02247 inline void
02248 View<T, isConst, A>::constView
02249 (
02250 std::initializer_list<size_t> b,
02251 std::initializer_list<size_t> s,
02252 View<T, true, A>& out
02253 ) const
02254 {
02255 constView(b.begin(), s.begin(), coordinateOrder(), out);
02256 }
02257 #endif
02258
02272 template<class T, bool isConst, class A>
02273 template<class ShapeIterator>
02274 inline void
02275 View<T, isConst, A>::reshape
02276 (
02277 ShapeIterator begin,
02278 ShapeIterator end
02279 )
02280 {
02281 testInvariant();
02282 marray_detail::Assert(MARRAY_NO_DEBUG || isSimple());
02283 if(!MARRAY_NO_ARG_TEST) {
02284 size_t size = std::accumulate(begin, end, 1, std::multiplies<size_t>());
02285 marray_detail::Assert(size == this->size());
02286 }
02287 assign(begin, end, data_, coordinateOrder(), coordinateOrder());
02288 testInvariant();
02289 }
02290
02304 template<class T, bool isConst, class A>
02305 template<class ShapeIterator>
02306 inline View<T, isConst, A>
02307 View<T, isConst, A>::reshapedView
02308 (
02309 ShapeIterator begin,
02310 ShapeIterator end
02311 ) const
02312 {
02313 View<T, isConst, A> out = *this;
02314 out.reshape(begin, end);
02315 return out;
02316 }
02317
02318 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330 template<class T, bool isConst, class A>
02331 inline void
02332 View<T, isConst, A>::reshape
02333 (
02334 std::initializer_list<size_t> shape
02335 )
02336 {
02337 reshape(shape.begin(), shape.end());
02338 }
02339
02351 template<class T, bool isConst, class A>
02352 inline View<T, isConst, A>
02353 View<T, isConst, A>::reshapedView
02354 (
02355 std::initializer_list<size_t> shape
02356 ) const
02357 {
02358 return reshapedView(shape.begin(), shape.end());
02359 }
02360 #endif
02361
02372 template<class T, bool isConst, class A>
02373 View<T, isConst, A>
02374 View<T, isConst, A>::boundView
02375 (
02376 const size_t dimension,
02377 const size_t value
02378 ) const
02379 {
02380 testInvariant();
02381 marray_detail::Assert(MARRAY_NO_ARG_TEST || (dimension < this->dimension()
02382 && value < shape(dimension)));
02383 if(this->dimension() == 1) {
02384 View v(&((*this)(value)));
02385 v.geometry_.coordinateOrder() = coordinateOrder();
02386 return v;
02387 }
02388 else {
02389 View v;
02390 v.geometry_.resize(this->dimension()-1);
02391 v.geometry_.coordinateOrder() = coordinateOrder();
02392 v.geometry_.size() = size() / shape(dimension);
02393 for(size_t j=0, k=0; j<this->dimension(); ++j) {
02394 if(j != dimension) {
02395 v.geometry_.shape(k) = shape(j);
02396 v.geometry_.strides(k) = strides(j);
02397 ++k;
02398 }
02399 }
02400 marray_detail::stridesFromShape(v.geometry_.shapeBegin(), v.geometry_.shapeEnd(),
02401 v.geometry_.shapeStridesBegin(), v.geometry_.coordinateOrder());
02402 v.data_ = data_ + strides(dimension) * value;
02403 v.updateSimplicity();
02404 v.testInvariant();
02405 return v;
02406 }
02407 }
02408
02413 template<class T, bool isConst, class A>
02414 void
02415 View<T, isConst, A>::squeeze()
02416 {
02417 testInvariant();
02418 if(dimension() != 0) {
02419 size_t newDimension = dimension();
02420 for(size_t j=0; j<dimension(); ++j) {
02421 if(shape(j) == 1) {
02422 --newDimension;
02423 }
02424 }
02425 if(newDimension != dimension()) {
02426 if(newDimension == 0) {
02427 geometry_.resize(0);
02428 geometry_.size() = 1;
02429 }
02430 else {
02431 for(size_t j=0, k=0; j<geometry_.dimension(); ++j) {
02432 if(geometry_.shape(j) != 1) {
02433 geometry_.shape(k) = geometry_.shape(j);
02434 geometry_.strides(k) = geometry_.strides(j);
02435 ++k;
02436 }
02437 }
02438 geometry_.resize(newDimension);
02439 marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
02440 geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
02441 updateSimplicity();
02442 }
02443 }
02444 }
02445 testInvariant();
02446 }
02447
02453 template<class T, bool isConst, class A>
02454 inline View<T, isConst, A>
02455 View<T, isConst, A>::squeezedView() const
02456 {
02457 View<T, isConst, A> v = *this;
02458 v.squeeze();
02459 return v;
02460 }
02461
02462 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
02463
02464
02465
02466
02467
02468
02469
02470
02471 template<class T, bool isConst, class A>
02472 void
02473 View<T, isConst, A>::permute
02474 (
02475 std::initializer_list<size_t> permutation
02476 )
02477 {
02478 permute(permutation.begin());
02479 }
02480 #endif
02481
02490 template<class T, bool isConst, class A>
02491 template<class CoordinateIterator>
02492 void
02493 View<T, isConst, A>::permute
02494 (
02495 CoordinateIterator begin
02496 )
02497 {
02498 testInvariant();
02499 if(!MARRAY_NO_ARG_TEST) {
02500 marray_detail::Assert(dimension() != 0);
02501 std::set<size_t> s1, s2;
02502 CoordinateIterator it = begin;
02503 for(size_t j=0; j<dimension(); ++j) {
02504 s1.insert(j);
02505 s2.insert(*it);
02506 ++it;
02507 }
02508 marray_detail::Assert(s1 == s2);
02509 }
02510
02511 std::vector<size_t> newShape = std::vector<size_t>(dimension());
02512 std::vector<size_t> newStrides = std::vector<size_t>(dimension());
02513 for(size_t j=0; j<dimension(); ++j) {
02514 newShape[j] = geometry_.shape(static_cast<size_t>(*begin));
02515 newStrides[j] = geometry_.strides(static_cast<size_t>(*begin));
02516 ++begin;
02517 }
02518 for(size_t j=0; j<dimension(); ++j) {
02519 geometry_.shape(j) = newShape[j];
02520 geometry_.strides(j) = newStrides[j];
02521 }
02522 marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
02523 geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
02524 updateSimplicity();
02525 testInvariant();
02526 }
02527
02537 template<class T, bool isConst, class A>
02538 template<class CoordinateIterator>
02539 inline View<T, isConst, A>
02540 View<T, isConst, A>::permutedView
02541 (
02542 CoordinateIterator begin
02543 ) const
02544 {
02545 View<T, isConst, A> out = *this;
02546 out.permute(begin);
02547 return out;
02548 }
02549
02556 template<class T, bool isConst, class A>
02557 void
02558 View<T, isConst, A>::transpose
02559 (
02560 const size_t c1,
02561 const size_t c2
02562 )
02563 {
02564 testInvariant();
02565 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
02566 (dimension() != 0 && c1 < dimension() && c2 < dimension()));
02567
02568 size_t j1 = c1;
02569 size_t j2 = c2;
02570 size_t c;
02571 size_t d;
02572
02573
02574 c = geometry_.shape(j2);
02575 geometry_.shape(j2) = geometry_.shape(j1);
02576 geometry_.shape(j1) = c;
02577
02578
02579 d = geometry_.strides(j2);
02580 geometry_.strides(j2) = geometry_.strides(j1);
02581 geometry_.strides(j1) = d;
02582
02583
02584 marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
02585 geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
02586
02587 updateSimplicity();
02588 testInvariant();
02589 }
02590
02596 template<class T, bool isConst, class A>
02597 void
02598 View<T, isConst, A>::transpose()
02599 {
02600 testInvariant();
02601 for(size_t j=0; j<dimension()/2; ++j) {
02602 size_t k = dimension()-j-1;
02603
02604
02605 size_t tmp = geometry_.shape(j);
02606 geometry_.shape(j) = geometry_.shape(k);
02607 geometry_.shape(k) = tmp;
02608
02609
02610 tmp = geometry_.strides(j);
02611 geometry_.strides(j) = geometry_.strides(k);
02612 geometry_.strides(k) = tmp;
02613 }
02614 marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
02615 geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
02616 updateSimplicity();
02617 testInvariant();
02618
02619 }
02620
02629 template<class T, bool isConst, class A>
02630 inline View<T, isConst, A>
02631 View<T, isConst, A>::transposedView
02632 (
02633 const size_t c1,
02634 const size_t c2
02635 ) const
02636 {
02637 View<T, isConst, A> out = *this;
02638 out.transpose(c1, c2);
02639 return out;
02640 }
02641
02648 template<class T, bool isConst, class A>
02649 inline View<T, isConst, A>
02650 View<T, isConst, A>::transposedView() const
02651 {
02652 View<T, isConst, A> out = *this;
02653 out.transpose();
02654 return out;
02655 }
02656
02663 template<class T, bool isConst, class A>
02664 inline void
02665 View<T, isConst, A>::shift
02666 (
02667 const int n
02668 )
02669 {
02670 testInvariant();
02671 marray_detail::Assert(MARRAY_NO_DEBUG || dimension() != 0);
02672 if(n <= -static_cast<int>(dimension()) || n >= static_cast<int>(dimension())) {
02673 shift(n % static_cast<int>(dimension()));
02674 }
02675 else {
02676 if(n > 0) {
02677 shift(n - static_cast<int>(dimension()));
02678 }
02679 else {
02680 std::vector<size_t> p(dimension());
02681 for(size_t j=0; j<dimension(); ++j) {
02682 p[j] = static_cast<size_t>((static_cast<int>(j) - n)) % dimension();
02683 }
02684 permute(p.begin());
02685 }
02686 }
02687 testInvariant();
02688 }
02689
02695 template<class T, bool isConst, class A>
02696 inline View<T, isConst, A>
02697 View<T, isConst, A>::shiftedView
02698 (
02699 const int n
02700 ) const
02701 {
02702 View<T, isConst, A> out = *this;
02703 out.shift(n);
02704 return out;
02705 }
02706
02712
02713 template<class T, bool isConst, class A>
02714 inline typename View<T, isConst, A>::iterator
02715 View<T, isConst, A>::begin()
02716 {
02717 testInvariant();
02718 return Iterator<T, isConst, A>(*this, 0);
02719 }
02720
02726 template<class T, bool isConst, class A>
02727 inline typename View<T, isConst, A>::iterator
02728 View<T, isConst, A>::end()
02729 {
02730 testInvariant();
02731 return Iterator<T, isConst, A>(*this, geometry_.size());
02732 }
02733
02739 template<class T, bool isConst, class A>
02740 inline typename View<T, isConst, A>::const_iterator
02741 View<T, isConst, A>::begin() const
02742 {
02743 testInvariant();
02744 return Iterator<T, true>(*this, 0);
02745 }
02746
02752 template<class T, bool isConst, class A>
02753 inline typename View<T, isConst, A>::const_iterator
02754
02755 View<T, isConst, A>::end() const
02756 {
02757 testInvariant();
02758 return Iterator<T, true>(*this, geometry_.size());
02759 }
02760
02766 template<class T, bool isConst, class A>
02767 inline typename View<T, isConst, A>::reverse_iterator
02768 View<T, isConst, A>::rbegin()
02769 {
02770 return reverse_iterator(end());
02771 }
02772
02778 template<class T, bool isConst, class A>
02779 inline typename View<T, isConst, A>::reverse_iterator
02780 View<T, isConst, A>::rend()
02781 {
02782 return reverse_iterator(begin());
02783 }
02784
02790 template<class T, bool isConst, class A>
02791 inline typename View<T, isConst, A>::const_reverse_iterator
02792 View<T, isConst, A>::rbegin() const
02793 {
02794 return const_reverse_iterator(end());
02795 }
02796
02802 template<class T, bool isConst, class A>
02803 inline typename View<T, isConst, A>::const_reverse_iterator
02804 View<T, isConst, A>::rend() const
02805 {
02806 return const_reverse_iterator(begin());
02807 }
02808
02815 template<class T, bool isConst, class A>
02816 inline void
02817 View<T, isConst, A>::updateSimplicity()
02818 {
02819
02820
02821 geometry_.updateSimplicity();
02822 }
02823
02832 template<class T, bool isConst, class A>
02833 inline const T&
02834 View<T, isConst, A>::operator[]
02835 (
02836 const size_t offset
02837 )
02838 const
02839 {
02840 return data_[offset];
02841 }
02842
02851 template<class T, bool isConst, class A>
02852 inline T&
02853 View<T, isConst, A>::operator[]
02854 (
02855 const size_t offset
02856 )
02857 {
02858 return data_[offset];
02859 }
02860
02866 template<class T, bool isConst, class A>
02867 inline void
02868 View<T, isConst, A>::testInvariant() const
02869 {
02870 if(!MARRAY_NO_DEBUG) {
02871 if(geometry_.dimension() == 0) {
02872 marray_detail::Assert(geometry_.isSimple() == true);
02873 if(data_ != 0) {
02874 marray_detail::Assert(geometry_.size() == 1);
02875 }
02876 }
02877 else {
02878 marray_detail::Assert(data_ != 0);
02879
02880
02881 size_t testSize = 1;
02882 for(size_t j=0; j<geometry_.dimension(); ++j) {
02883 testSize *= geometry_.shape(j);
02884 }
02885 marray_detail::Assert(geometry_.size() == testSize);
02886
02887
02888 if(geometry_.coordinateOrder() == FirstMajorOrder) {
02889 size_t tmp = 1;
02890 for(size_t j=0; j<geometry_.dimension(); ++j) {
02891 marray_detail::Assert(geometry_.shapeStrides(geometry_.dimension()-j-1) == tmp);
02892 tmp *= geometry_.shape(geometry_.dimension()-j-1);
02893 }
02894 }
02895 else {
02896 size_t tmp = 1;
02897 for(size_t j=0; j<geometry_.dimension(); ++j) {
02898 marray_detail::Assert(geometry_.shapeStrides(j) == tmp);
02899 tmp *= geometry_.shape(j);
02900 }
02901 }
02902
02903
02904 if(geometry_.isSimple()) {
02905 for(size_t j=0; j<geometry_.dimension(); ++j) {
02906 marray_detail::Assert(geometry_.strides(j) == geometry_.shapeStrides(j));
02907 }
02908 }
02909 }
02910 }
02911 }
02912
02928 template<class T, bool isConst, class A>
02929 template<class TLocal, bool isConstLocal, class ALocal>
02930 inline bool View<T, isConst, A>::overlaps
02931 (
02932 const View<TLocal, isConstLocal, ALocal>& v
02933 ) const
02934 {
02935 testInvariant();
02936 if(!MARRAY_NO_ARG_TEST) {
02937 v.testInvariant();
02938 }
02939 if(data_ == 0 || v.data_ == 0) {
02940 return false;
02941 }
02942 else {
02943 const void* dataPointer_ = data_;
02944 const void* vDataPointer_ = v.data_;
02945 const void* maxPointer = & (*this)(this->size()-1);
02946 const void* maxPointerV = & v(v.size()-1);
02947 if( (dataPointer_ <= vDataPointer_ && vDataPointer_ <= maxPointer)
02948 || (vDataPointer_ <= dataPointer_ && dataPointer_ <= maxPointerV) )
02949 {
02950 return true;
02951 }
02952 }
02953 return false;
02954 }
02955
02958 template<class T, bool isConst, class A>
02959 std::string
02960 View<T, isConst, A>::asString
02961 (
02962 const StringStyle& style
02963 ) const
02964 {
02965 testInvariant();
02966 std::ostringstream out(std::ostringstream::out);
02967 if(style == MatrixStyle) {
02968 if(dimension() == 0) {
02969
02970 out << "A = " << (*this)(0) << std::endl;
02971 }
02972 else if(dimension() == 1) {
02973
02974 out << "A = (";
02975 for(size_t j=0; j<this->size(); ++j) {
02976 out << (*this)(j) << ", ";
02977 }
02978 out << "\b\b)" << std::endl;
02979 }
02980 else if(dimension() == 2) {
02981
02982 if(coordinateOrder() == FirstMajorOrder) {
02983 out << "A(r,c) =" << std::endl;
02984 for(size_t y=0; y<this->shape(0); ++y) {
02985 for(size_t x=0; x<this->shape(1); ++x) {
02986 out << (*this)(y, x) << ' ';
02987 }
02988 out << std::endl;
02989 }
02990 }
02991 else {
02992 out << "A(c,r) =" << std::endl;
02993 for(size_t y=0; y<this->shape(1); ++y) {
02994 for(size_t x=0; x<this->shape(0); ++x) {
02995 out << (*this)(x, y) << ' ';
02996 }
02997 out << std::endl;
02998 }
02999 }
03000 }
03001 else {
03002
03003 std::vector<size_t> c1(dimension());
03004 std::vector<size_t> c2(dimension());
03005 unsigned short q = 2;
03006 if(coordinateOrder() == FirstMajorOrder) {
03007 q = dimension()-3;
03008 }
03009 for(const_iterator it = this->begin(); it.hasMore(); ++it) {
03010 it.coordinate(c2.begin());
03011 if(it.index() == 0 || c2[q] != c1[q]) {
03012 if(it.index() != 0) {
03013 out << std::endl << std::endl;
03014 }
03015 if(coordinateOrder() == FirstMajorOrder) {
03016 out << "A(";
03017 for(size_t j=0; j<dimension()-2; ++j) {
03018 out << c2[j] << ",";
03019 }
03020 }
03021 else {
03022 out << "A(c,r,";
03023 for(size_t j=2; j<dimension(); ++j) {
03024 out << c2[j] << ",";
03025 }
03026 }
03027 out << '\b';
03028 if(coordinateOrder() == FirstMajorOrder) {
03029 out << ",r,c";
03030 }
03031 out << ") =" << std::endl;
03032 }
03033 else if(c2[1] != c1[1]) {
03034 out << std::endl;
03035 }
03036 out << *it << " ";
03037 c1 = c2;
03038 }
03039 out << std::endl;
03040 }
03041 out << std::endl;
03042 }
03043 else if(style == TableStyle) {
03044 if(dimension() == 0) {
03045
03046 out << "A = " << (*this)(0) << std::endl;
03047 }
03048 else {
03049
03050 std::vector<size_t> c(dimension());
03051 for(const_iterator it = this->begin(); it.hasMore(); ++it) {
03052 out << "A(";
03053 it.coordinate(c.begin());
03054 for(size_t j=0; j<c.size(); ++j) {
03055 out << c[j] << ',';
03056 }
03057 out << "\b) = " << *it << std::endl;
03058 }
03059 }
03060 out << std::endl;
03061 }
03062 return out.str();
03063 }
03064
03065
03066
03067 template<class T1, class T2, bool isConst, class A>
03068 inline View<T1, false, A>&
03069 operator+=
03070 (
03071 View<T1, false, A>& v,
03072 const View<T2, isConst, A>& w
03073 )
03074 {
03075 marray_detail::operate(v, w, marray_detail::PlusEqual<T1, T2>());
03076 return v;
03077 }
03078
03079
03080 template<class T, class A>
03081 inline View<T, false, A>&
03082 operator++
03083 (
03084 View<T, false, A>& v
03085 )
03086 {
03087 marray_detail::operate(v, marray_detail::PrefixIncrement<T>());
03088 return v;
03089 }
03090
03091
03092 template<class T, class A>
03093 inline Marray<T, A>
03094 operator++
03095 (
03096 Marray<T, A>& in,
03097 int dummy
03098 )
03099 {
03100 Marray<T, A> out = in;
03101 marray_detail::operate(in, marray_detail::PostfixIncrement<T>());
03102 return out;
03103 }
03104
03105 template<class T1, class T2, bool isConst, class A>
03106 inline View<T1, false, A>&
03107 operator-=
03108 (
03109 View<T1, false, A>& v,
03110 const View<T2, isConst, A>& w
03111 )
03112 {
03113 marray_detail::operate(v, w, marray_detail::MinusEqual<T1, T2>());
03114 return v;
03115 }
03116
03117
03118 template<class T, class A>
03119 inline View<T, false, A>&
03120 operator--
03121 (
03122 View<T, false, A>& v
03123 )
03124 {
03125 marray_detail::operate(v, marray_detail::PrefixDecrement<T>());
03126 return v;
03127 }
03128
03129
03130 template<class T, class A>
03131 inline Marray<T, A>
03132 operator--
03133 (
03134 Marray<T, A>& in,
03135 int dummy
03136 )
03137 {
03138 Marray<T, A> out = in;
03139 marray_detail::operate(in, marray_detail::PostfixDecrement<T>());
03140 return out;
03141 }
03142
03143 template<class T1, class T2, bool isConst, class A>
03144 inline View<T1, false, A>&
03145 operator*=
03146 (
03147 View<T1, false, A>& v,
03148 const View<T2, isConst, A>& w
03149 )
03150 {
03151 marray_detail::operate(v, w, marray_detail::TimesEqual<T1, T2>());
03152 return v;
03153 }
03154
03155 template<class T1, class T2, bool isConst, class A>
03156 inline View<T1, false, A>&
03157 operator/=
03158 (
03159 View<T1, false, A>& v,
03160 const View<T2, isConst, A>& w
03161 )
03162 {
03163 marray_detail::operate(v, w, marray_detail::DividedByEqual<T1, T2>());
03164 return v;
03165 }
03166
03167 template<class E1, class T1, class E2, class T2>
03168 inline const BinaryViewExpression<E1, T1, E2, T2, marray_detail::Plus<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
03169 operator+
03170 (
03171 const ViewExpression<E1, T1>& expression1,
03172 const ViewExpression<E2, T2>& expression2
03173 )
03174 {
03175 typedef typename marray_detail::PromoteType<T1, T2>::type promoted_type;
03176 typedef marray_detail::Plus<T1, T2, promoted_type> Functor;
03177 typedef BinaryViewExpression<E1, T1, E2, T2, Functor> return_type;
03178 return return_type(expression1, expression2);
03179 }
03180
03181 template<class E, class T>
03182 inline const ViewExpression<E,T>&
03183 operator+
03184 (
03185 const ViewExpression<E,T>& expression
03186 )
03187 {
03188 return expression;
03189 }
03190
03191 #define MARRAY_UNARY_OPERATOR(datatype, operation, functorname) \
03192 template<class T, class A> \
03193 inline View<T, false, A>& \
03194 operator operation \
03195 ( \
03196 View<T, false, A>& v, \
03197 const datatype& x \
03198 ) \
03199 { \
03200 marray_detail::operate(v, static_cast<T>(x), marray_detail:: functorname <T, T>()); \
03201 return v; \
03202 } \
03203
03204 #define MARRAY_UNARY_OPERATOR_ALL_TYPES(op, functorname) \
03205 MARRAY_UNARY_OPERATOR(char, op, functorname) \
03206 MARRAY_UNARY_OPERATOR(unsigned char, op, functorname) \
03207 MARRAY_UNARY_OPERATOR(short, op, functorname) \
03208 MARRAY_UNARY_OPERATOR(unsigned short, op, functorname) \
03209 MARRAY_UNARY_OPERATOR(int, op, functorname) \
03210 MARRAY_UNARY_OPERATOR(unsigned int, op, functorname) \
03211 MARRAY_UNARY_OPERATOR(long, op, functorname) \
03212 MARRAY_UNARY_OPERATOR(unsigned long, op, functorname) \
03213 MARRAY_UNARY_OPERATOR(float, op, functorname) \
03214 MARRAY_UNARY_OPERATOR(double, op, functorname) \
03215 MARRAY_UNARY_OPERATOR(long double, op, functorname) \
03216
03217 MARRAY_UNARY_OPERATOR_ALL_TYPES(+=, PlusEqual)
03218 MARRAY_UNARY_OPERATOR_ALL_TYPES(-=, MinusEqual)
03219 MARRAY_UNARY_OPERATOR_ALL_TYPES(*=, TimesEqual)
03220 MARRAY_UNARY_OPERATOR_ALL_TYPES(/=, DividedByEqual)
03221
03222 template<class E1, class T1, class E2, class T2>
03223 inline const BinaryViewExpression<E1, T1, E2, T2,
03224 marray_detail::Minus<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
03225 operator-
03226 (
03227 const ViewExpression<E1, T1>& expression1,
03228 const ViewExpression<E2, T2>& expression2
03229 )
03230 {
03231 return BinaryViewExpression<E1, T1, E2, T2,
03232 marray_detail::Minus<T1, T2,
03233 typename marray_detail::PromoteType<T1, T2>::type> >(
03234 expression1, expression2);
03235 }
03236
03237 template<class E, class T>
03238 inline const UnaryViewExpression<E,T,marray_detail::Negate<T> >
03239 operator-
03240 (
03241 const ViewExpression<E,T>& expression
03242 )
03243 {
03244 return UnaryViewExpression<E,T,marray_detail::Negate<T> >(
03245 expression);
03246 }
03247
03248 template<class E1, class T1, class E2, class T2>
03249 inline const BinaryViewExpression<E1, T1, E2, T2,
03250 marray_detail::Times<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
03251 operator*
03252 (
03253 const ViewExpression<E1, T1>& expression1,
03254 const ViewExpression<E2, T2>& expression2
03255 )
03256 {
03257 return BinaryViewExpression<E1, T1, E2, T2,
03258 marray_detail::Times<T1, T2,
03259 typename marray_detail::PromoteType<T1, T2>::type > >(
03260 expression1, expression2);
03261 }
03262
03263 template<class E1, class T1, class E2, class T2>
03264 inline const BinaryViewExpression<E1, T1, E2, T2,
03265 marray_detail::DividedBy<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
03266 operator/
03267 (
03268 const ViewExpression<E1, T1>& expression1,
03269 const ViewExpression<E2, T2>& expression2
03270 )
03271 {
03272 return BinaryViewExpression<E1, T1, E2, T2,
03273 marray_detail::DividedBy<T1, T2,
03274 typename marray_detail::PromoteType<T1, T2>::type > >(
03275 expression1, expression2);
03276 }
03277
03278 #define MARRAY_BINARY_OPERATOR(datatype, operation, functorname) \
03279 template<class E, class T> \
03280 inline const BinaryViewExpressionScalarSecond< \
03281 E, T, datatype, marray_detail:: functorname < \
03282 T, datatype, typename marray_detail::PromoteType<T, datatype>::type \
03283 > \
03284 > \
03285 operator operation \
03286 ( \
03287 const ViewExpression<E, T>& expression, \
03288 const datatype& scalar \
03289 ) \
03290 { \
03291 typedef typename marray_detail::PromoteType<T, datatype>::type \
03292 promoted_type; \
03293 typedef marray_detail:: functorname <T, datatype, promoted_type> Functor; \
03294 typedef BinaryViewExpressionScalarSecond<E, T, datatype, Functor> \
03295 expression_type; \
03296 return expression_type(expression, scalar); \
03297 } \
03298 \
03299 template<class E, class T> \
03300 inline const BinaryViewExpressionScalarFirst \
03301 < \
03302 E, T, datatype, marray_detail:: functorname < \
03303 datatype, T, typename marray_detail::PromoteType<datatype, T>::type \
03304 > \
03305 > \
03306 operator operation \
03307 ( \
03308 const datatype& scalar, \
03309 const ViewExpression<E, T>& expression \
03310 ) \
03311 { \
03312 typedef typename marray_detail::PromoteType<T, datatype>::type \
03313 promoted_type; \
03314 typedef marray_detail:: functorname <datatype, T, promoted_type> Functor; \
03315 typedef BinaryViewExpressionScalarFirst<E, T, datatype, Functor> \
03316 expression_type; \
03317 return expression_type(expression, scalar); \
03318 }
03319
03320 #define MARRAY_BINARY_OPERATOR_ALL_TYPES(op, functorname) \
03321 MARRAY_BINARY_OPERATOR(char, op, functorname) \
03322 MARRAY_BINARY_OPERATOR(unsigned char, op, functorname) \
03323 MARRAY_BINARY_OPERATOR(short, op, functorname) \
03324 MARRAY_BINARY_OPERATOR(unsigned short, op, functorname) \
03325 MARRAY_BINARY_OPERATOR(int, op, functorname) \
03326 MARRAY_BINARY_OPERATOR(unsigned int, op, functorname) \
03327 MARRAY_BINARY_OPERATOR(long, op, functorname) \
03328 MARRAY_BINARY_OPERATOR(unsigned long, op, functorname) \
03329 MARRAY_BINARY_OPERATOR(float, op, functorname) \
03330 MARRAY_BINARY_OPERATOR(double, op, functorname) \
03331 MARRAY_BINARY_OPERATOR(long double, op, functorname) \
03332
03333 MARRAY_BINARY_OPERATOR_ALL_TYPES(+, Plus)
03334 MARRAY_BINARY_OPERATOR_ALL_TYPES(-, Minus)
03335 MARRAY_BINARY_OPERATOR_ALL_TYPES(*, Times)
03336 MARRAY_BINARY_OPERATOR_ALL_TYPES(/, DividedBy)
03337
03338
03339
03348 template<class T, class A>
03349 inline void
03350 Marray<T, A>::assign
03351 (
03352 const allocator_type& allocator
03353 )
03354 {
03355 if(this->data_ != 0) {
03356 dataAllocator_.deallocate(this->data_, this->size());
03357 this->data_ = 0;
03358 }
03359 dataAllocator_ = allocator;
03360 base::assign();
03361 }
03362
03367 template<class T, class A>
03368 inline
03369 Marray<T, A>::Marray
03370 (
03371 const allocator_type& allocator
03372 )
03373 : base(allocator),
03374 dataAllocator_(allocator)
03375 {
03376 testInvariant();
03377 }
03378
03388 template<class T, class A>
03389 inline
03390 Marray<T, A>::Marray
03391 (
03392 const T& value,
03393 const CoordinateOrder& coordinateOrder,
03394 const allocator_type& allocator
03395 )
03396 : dataAllocator_(allocator)
03397 {
03398 this->data_ = dataAllocator_.allocate(1);
03399 this->data_[0] = value;
03400 this->geometry_ = geometry_type(0, coordinateOrder, 1, true, allocator);
03401 testInvariant();
03402 }
03403
03408 template<class T, class A>
03409 inline
03410 Marray<T, A>::Marray
03411 (
03412 const Marray<T, A>& in
03413 )
03414 : dataAllocator_(in.dataAllocator_)
03415 {
03416 if(!MARRAY_NO_ARG_TEST) {
03417 in.testInvariant();
03418 }
03419 if(in.data_ == 0) {
03420 this->data_ = 0;
03421 }
03422 else {
03423 this->data_ = dataAllocator_.allocate(in.size());
03424 memcpy(this->data_, in.data_, (in.size())*sizeof(T));
03425 }
03426 this->geometry_ = in.geometry_;
03427 testInvariant();
03428 }
03429
03434 template<class T, class A>
03435 template<class TLocal, bool isConstLocal, class ALocal>
03436 inline
03437 Marray<T, A>::Marray
03438 (
03439 const View<TLocal, isConstLocal, ALocal>& in
03440 )
03441 : dataAllocator_()
03442 {
03443 if(!MARRAY_NO_ARG_TEST) {
03444 in.testInvariant();
03445 }
03446
03447
03448 this->geometry_ = in.geometry_;
03449 for(size_t j=0; j<in.dimension(); ++j) {
03450 this->geometry_.strides(j) = in.geometry_.shapeStrides(j);
03451 }
03452 this->geometry_.isSimple() = true;
03453
03454
03455 if(in.size() == 0) {
03456 this->data_ = 0;
03457 }
03458 else {
03459 this->data_ = dataAllocator_.allocate(in.size());
03460 }
03461 if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
03462 memcpy(this->data_, in.data_, (in.size())*sizeof(T));
03463 }
03464 else {
03465 typename View<TLocal, isConstLocal, ALocal>::const_iterator it = in.begin();
03466 for(size_t j=0; j<this->size(); ++j, ++it) {
03467 this->data_[j] = static_cast<T>(*it);
03468 }
03469 }
03470
03471 testInvariant();
03472 }
03473
03479 template<class T, class A>
03480 template<class E, class Te>
03481 inline
03482 Marray<T, A>::Marray
03483 (
03484 const ViewExpression<E, Te>& expression,
03485 const allocator_type& allocator
03486 )
03487 : dataAllocator_(allocator)
03488 {
03489 this->data_ = dataAllocator_.allocate(expression.size());
03490 if(expression.dimension() == 0) {
03491 this->geometry_ = geometry_type(0,
03492 static_cast<const E&>(expression).coordinateOrder(),
03493 1, true, dataAllocator_);
03494 }
03495 else {
03496 this->geometry_ = geometry_type(
03497 static_cast<const E&>(expression).shapeBegin(),
03498 static_cast<const E&>(expression).shapeEnd(),
03499 static_cast<const E&>(expression).coordinateOrder(),
03500 static_cast<const E&>(expression).coordinateOrder(),
03501 dataAllocator_);
03502
03503 }
03504 const E& e = static_cast<const E&>(expression);
03505 if(e.dimension() == 0) {
03506 marray_detail::Assert(MARRAY_NO_ARG_TEST || e.size() < 2);
03507 this->data_[0] = static_cast<T>(e(0));
03508 }
03509 else {
03510 marray_detail::Assert(MARRAY_NO_ARG_TEST || e.size() != 0);
03511 marray_detail::operate(*this, e, marray_detail::Assign<T, Te>());
03512 }
03513 testInvariant();
03514 }
03515
03526 template<class T, class A>
03527 template<class ShapeIterator>
03528 inline
03529 Marray<T, A>::Marray
03530 (
03531 ShapeIterator begin,
03532 ShapeIterator end,
03533 const T& value,
03534 const CoordinateOrder& coordinateOrder,
03535 const allocator_type& allocator
03536 )
03537 : dataAllocator_(allocator)
03538 {
03539 size_t size = std::accumulate(begin, end, static_cast<size_t>(1), std::multiplies<size_t>());
03540 marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
03541 base::assign(begin, end, dataAllocator_.allocate(size), coordinateOrder,
03542 coordinateOrder, allocator);
03543 for(size_t j=0; j<size; ++j) {
03544 this->data_[j] = value;
03545 }
03546 testInvariant();
03547 }
03548
03559 template<class T, class A>
03560 template<class ShapeIterator>
03561 inline
03562 Marray<T, A>::Marray
03563 (
03564 const InitializationSkipping& is,
03565 ShapeIterator begin,
03566 ShapeIterator end,
03567 const CoordinateOrder& coordinateOrder,
03568 const allocator_type& allocator
03569 )
03570 : dataAllocator_(allocator)
03571 {
03572 size_t size = std::accumulate(begin, end, 1, std::multiplies<size_t>());
03573 marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
03574 base::assign(begin, end, dataAllocator_.allocate(size), coordinateOrder,
03575 coordinateOrder, allocator);
03576 testInvariant();
03577 }
03578
03579 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
03580
03581
03582
03583
03584
03585
03586
03587
03588 template<class T, class A>
03589 inline
03590 Marray<T, A>::Marray
03591 (
03592 std::initializer_list<size_t> shape,
03593 const T& value,
03594 const CoordinateOrder& coordinateOrder,
03595 const allocator_type& allocator
03596
03597 )
03598 : dataAllocator_(allocator)
03599 {
03600 size_t size = std::accumulate(shape.begin(), shape.end(),
03601 1, std::multiplies<size_t>());
03602 marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
03603 base::assign(shape.begin(), shape.end(), dataAllocator_.allocate(size),
03604 coordinateOrder, coordinateOrder, allocator);
03605 for(size_t j=0; j<size; ++j) {
03606 this->data_[j] = value;
03607 }
03608 testInvariant();
03609 }
03610 #endif
03611
03614 template<class T, class A>
03615 inline
03616 Marray<T, A>::~Marray()
03617 {
03618 dataAllocator_.deallocate(this->data_, this->size());
03619 }
03620
03633 template<class T, class A>
03634
03635 Marray<T, A>&
03636 Marray<T, A>::operator=
03637 (
03638 const Marray<T, A>& in
03639 )
03640 {
03641 testInvariant();
03642 if(!MARRAY_NO_ARG_TEST) {
03643 in.testInvariant();
03644 }
03645 if(this != &in) {
03646
03647 if(in.data_ == 0) {
03648
03649 dataAllocator_.deallocate(this->data_, this->size());
03650 this->data_ = 0;
03651 }
03652 else {
03653 if(this->size() != in.size()) {
03654
03655 dataAllocator_.deallocate(this->data_, this->size());
03656 this->data_ = dataAllocator_.allocate(in.size());
03657 }
03658
03659 memcpy(this->data_, in.data_, in.size() * sizeof(T));
03660 }
03661 this->geometry_ = in.geometry_;
03662 }
03663 testInvariant();
03664 return *this;
03665 }
03666
03681 template<class T, class A>
03682 template<class TLocal, bool isConstLocal, class ALocal>
03683 Marray<T, A>&
03684 Marray<T, A>::operator=
03685 (
03686 const View<TLocal, isConstLocal, ALocal>& in
03687 )
03688 {
03689 if(!MARRAY_NO_ARG_TEST) {
03690 in.testInvariant();
03691 }
03692 if( (void*)(this) != (void*)(&in) ) {
03693 if(in.data_ == 0) {
03694 dataAllocator_.deallocate(this->data_, this->size());
03695 this->data_ = 0;
03696 this->geometry_ = in.geometry_;
03697 }
03698 else if(this->overlaps(in)) {
03699 Marray<T, A> m = in;
03700 (*this) = m;
03701 }
03702 else {
03703
03704 if(this->size() != in.size()) {
03705 dataAllocator_.deallocate(this->data_, this->size());
03706 this->data_ = dataAllocator_.allocate(in.size());
03707 }
03708
03709
03710 this->geometry_.resize(in.dimension());
03711 for(size_t j=0; j<in.dimension(); ++j) {
03712 this->geometry_.shape(j) = in.geometry_.shape(j);
03713 this->geometry_.shapeStrides(j) = in.geometry_.shapeStrides(j);
03714 this->geometry_.strides(j) = in.geometry_.shapeStrides(j);
03715 }
03716 this->geometry_.size() = in.size();
03717 this->geometry_.isSimple() = true;
03718 this->geometry_.coordinateOrder() = in.coordinateOrder();
03719
03720
03721 if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
03722 memcpy(this->data_, in.data_, (in.size())*sizeof(T));
03723 }
03724 else if(in.dimension() == 1)
03725 marray_detail::OperateHelperBinary<1, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03726 else if(in.dimension() == 2)
03727 marray_detail::OperateHelperBinary<2, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03728 else if(in.dimension() == 3)
03729 marray_detail::OperateHelperBinary<3, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03730 else if(in.dimension() == 4)
03731 marray_detail::OperateHelperBinary<4, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03732 else if(in.dimension() == 5)
03733 marray_detail::OperateHelperBinary<5, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03734 else if(in.dimension() == 6)
03735 marray_detail::OperateHelperBinary<6, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03736 else if(in.dimension() == 7)
03737 marray_detail::OperateHelperBinary<7, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03738 else if(in.dimension() == 8)
03739 marray_detail::OperateHelperBinary<8, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03740 else if(in.dimension() == 9)
03741 marray_detail::OperateHelperBinary<9, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03742 else if(in.dimension() == 10)
03743 marray_detail::OperateHelperBinary<10, marray_detail::Assign<T, TLocal>, T, TLocal, isConstLocal, A, ALocal>::operate(*this, in, marray_detail::Assign<T, TLocal>(), this->data_, &in(0));
03744 else {
03745 typename View<TLocal, isConstLocal, ALocal>::const_iterator it = in.begin();
03746 for(size_t j=0; j<this->size(); ++j, ++it) {
03747 this->data_[j] = static_cast<T>(*it);
03748 }
03749 }
03750 }
03751 }
03752 testInvariant();
03753 return *this;
03754 }
03755
03762 template<class T, class A>
03763 inline Marray<T, A>&
03764 Marray<T, A>::operator=
03765 (
03766 const T& value
03767 )
03768 {
03769 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
03770 for(size_t j=0; j<this->size(); ++j) {
03771 this->data_[j] = value;
03772 }
03773 return *this;
03774 }
03775
03776 template<class T, class A>
03777 template<class E, class Te>
03778 inline Marray<T, A>&
03779 Marray<T, A>::operator=
03780 (
03781 const ViewExpression<E, Te>& expression
03782 )
03783 {
03784 if(expression.overlaps(*this)) {
03785 Marray<T, A> m(expression);
03786 (*this) = m;
03787 }
03788 else {
03789
03790 if(this->size() != expression.size()) {
03791 dataAllocator_.deallocate(this->data_, this->size());
03792 this->data_ = dataAllocator_.allocate(expression.size());
03793 }
03794
03795
03796 this->geometry_.resize(expression.dimension());
03797 for(size_t j=0; j<expression.dimension(); ++j) {
03798 this->geometry_.shape(j) = expression.shape(j);
03799 }
03800 this->geometry_.size() = expression.size();
03801 this->geometry_.isSimple() = true;
03802 this->geometry_.coordinateOrder() = expression.coordinateOrder();
03803 if(this->geometry_.dimension() != 0) {
03804 marray_detail::stridesFromShape(this->geometry_.shapeBegin(), this->geometry_.shapeEnd(),
03805 this->geometry_.shapeStridesBegin(), this->geometry_.coordinateOrder());
03806 marray_detail::stridesFromShape(this->geometry_.shapeBegin(), this->geometry_.shapeEnd(),
03807 this->geometry_.stridesBegin(), this->geometry_.coordinateOrder());
03808 }
03809
03810
03811 marray_detail::operate(*this, expression, marray_detail::Assign<T, Te>());
03812 }
03813 return *this;
03814 }
03815
03816 template<class T, class A>
03817 template<bool SKIP_INITIALIZATION, class ShapeIterator>
03818 inline void
03819 Marray<T, A>::resizeHelper
03820 (
03821 ShapeIterator begin,
03822 ShapeIterator end,
03823 const T& value
03824 )
03825 {
03826 testInvariant();
03827
03828 std::vector<size_t> newShape;
03829 size_t newSize = 1;
03830 for(ShapeIterator it = begin; it != end; ++it) {
03831 size_t x = static_cast<size_t>(*it);
03832 marray_detail::Assert(MARRAY_NO_ARG_TEST || x > 0);
03833 newShape.push_back(x);
03834 newSize *= x;
03835 }
03836
03837 value_type* newData = dataAllocator_.allocate(newSize);
03838 if(!SKIP_INITIALIZATION) {
03839 for(size_t j=0; j<newSize; ++j) {
03840 newData[j] = value;
03841 }
03842 }
03843
03844 if(this->data_ != 0) {
03845 if(newSize == 1 || this->dimension() == 0) {
03846 newData[0] = this->data_[0];
03847 }
03848 else {
03849 std::vector<size_t> base1(this->dimension());
03850 std::vector<size_t> base2(newShape.size());
03851 std::vector<size_t> shape1(this->dimension(), 1);
03852 std::vector<size_t> shape2(newShape.size(), 1);
03853 for(size_t j=0; j<std::min(this->dimension(), newShape.size()); ++j) {
03854 shape1[j] = std::min(this->shape(j), newShape[j]);
03855 shape2[j] = shape1[j];
03856 }
03857 View<T, true, A> view1;
03858 this->constView(base1.begin(), shape1.begin(), view1);
03859 View<T, false, A> viewT(newShape.begin(), newShape.end(),
03860 newData, this->coordinateOrder(),
03861 this->coordinateOrder());
03862 View<T, false, A> view2;
03863 viewT.view(base2.begin(), shape2.begin(), view2);
03864 view1.squeeze();
03865 view2.squeeze();
03866 view2 = view1;
03867 }
03868 dataAllocator_.deallocate(this->data_, this->size());
03869 this->data_ = 0;
03870 }
03871 base::assign(begin, end, newData, this->geometry_.coordinateOrder(),
03872 this->geometry_.coordinateOrder());
03873 testInvariant();
03874 }
03875
03883 template<class T, class A>
03884 template<class ShapeIterator>
03885 void
03886 Marray<T, A>::resize
03887 (
03888 ShapeIterator begin,
03889 ShapeIterator end,
03890 const T& value
03891 )
03892 {
03893 if(std::distance(begin,end)==0) {
03894 if(this->size()>0) {
03895 *this=Marray<T,A>((*this).operator()(0));
03896 }
03897 else{
03898 *this=Marray<T,A>(T());
03899 }
03900
03901 }
03902 else
03903 {
03904 resizeHelper<false>(begin, end, value);
03905 }
03906 }
03907
03915 template<class T, class A>
03916 template<class ShapeIterator>
03917 void
03918 Marray<T, A>::resize
03919 (
03920 const InitializationSkipping& is,
03921 ShapeIterator begin,
03922 ShapeIterator end
03923 )
03924 {
03925 resizeHelper<true>(begin, end);
03926 }
03927
03928 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
03929
03930
03931
03932
03933
03934 template<class T, class A>
03935 inline void
03936 Marray<T, A>::resize
03937 (
03938 std::initializer_list<size_t> shape,
03939 const T& value
03940 )
03941 {
03942 resizeHelper<false>(shape.begin(), shape.end(), value);
03943 }
03944
03950 template<class T, class A>
03951 inline void
03952 Marray<T, A>::resize
03953 (
03954 const InitializationSkipping& si,
03955 std::initializer_list<size_t> shape
03956 )
03957 {
03958 resizeHelper<true>(shape.begin(), shape.end());
03959 }
03960 #endif
03961
03964 template<class T, class A>
03965 inline void
03966 Marray<T, A>::testInvariant() const
03967 {
03968 View<T, false, A>::testInvariant();
03969 marray_detail::Assert(MARRAY_NO_DEBUG || this->geometry_.isSimple());
03970 }
03971
03972
03973
03976 template<class T, bool isConst, class A>
03977 inline void
03978 Iterator<T, isConst, A>::testInvariant() const
03979 {
03980 if(!MARRAY_NO_DEBUG) {
03981 if(view_ == 0) {
03982 marray_detail::Assert(coordinates_.size() == 0
03983 && index_ == 0
03984 && pointer_ == 0);
03985 }
03986 else {
03987 if(view_->size() == 0) {
03988 marray_detail::Assert(coordinates_.size() == 0
03989 && index_ == 0
03990 && pointer_ == 0);
03991 }
03992 else {
03993 marray_detail::Assert(index_ <= view_->size());
03994 if(index_ == view_->size()) {
03995 marray_detail::Assert(pointer_ == &((*view_)(view_->size()-1)) + 1);
03996 }
03997 else {
03998 marray_detail::Assert(pointer_ == &((*view_)(index_)));
03999 }
04000 if(!view_->isSimple()) {
04001 marray_detail::Assert(coordinates_.size() == view_->dimension());
04002 if(index_ == view_->size()) {
04003 if(view_->coordinateOrder() == LastMajorOrder) {
04004 marray_detail::Assert(coordinates_[0] == view_->shape(0));
04005 for(size_t j=1; j<coordinates_.size(); ++j) {
04006 marray_detail::Assert(coordinates_[j] == view_->shape(j)-1);
04007 }
04008 }
04009 else {
04010 size_t d = view_->dimension() - 1;
04011 marray_detail::Assert(coordinates_[d] == view_->shape(d));
04012 for(size_t j=0; j<d; ++j) {
04013 marray_detail::Assert(coordinates_[j] == view_->shape(j)-1);
04014 }
04015 }
04016 }
04017 else {
04018 std::vector<size_t> testCoord(coordinates_.size());
04019 view_->indexToCoordinates(index_, testCoord.begin());
04020 for(size_t j=0; j<coordinates_.size(); ++j) {
04021 marray_detail::Assert(coordinates_[j] == testCoord[j]);
04022 }
04023 }
04024 }
04025 }
04026 }
04027 }
04028 }
04029
04031 template<class T, bool isConst, class A>
04032 inline Iterator<T, isConst, A>::Iterator()
04033 : view_(0),
04034 pointer_(0),
04035 index_(0),
04036 coordinates_(std::vector<size_t>())
04037 {
04038 testInvariant();
04039 }
04040
04046 template<class T, bool isConst, class A>
04047 inline Iterator<T, isConst, A>::Iterator
04048 (
04049 const View<T, true, A>& view,
04050 const size_t index
04051 )
04052 : view_(&view),
04053 pointer_(0),
04054 index_(index),
04055 coordinates_(std::vector<size_t>(view.dimension()))
04056
04057
04058
04059 {
04060 if(view.size() == 0) {
04061 marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
04062 }
04063 else {
04064 if(view.isSimple()) {
04065 marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
04066 pointer_ = &view(0) + index;
04067 }
04068 else {
04069 if(index >= view.size()) {
04070 if(view_->coordinateOrder() == LastMajorOrder) {
04071 coordinates_[0] = view.shape(0);
04072 for(size_t j=1; j<view.dimension(); ++j) {
04073 coordinates_[j] = view.shape(j)-1;
04074 }
04075 }
04076 else {
04077 size_t d = view_->dimension() - 1;
04078 coordinates_[d] = view.shape(d);
04079 for(size_t j=0; j<d; ++j) {
04080 coordinates_[j] = view.shape(j)-1;
04081 }
04082 }
04083 pointer_ = &view(view.size()-1) + 1;
04084 }
04085 else {
04086 view.indexToCoordinates(index, coordinates_.begin());
04087 pointer_ = &view(index);
04088 }
04089 }
04090 }
04091 testInvariant();
04092 }
04093
04099 template<class T, bool isConst, class A>
04100 inline Iterator<T, isConst, A>::Iterator
04101 (
04102 const View<T, false, A>& view,
04103 const size_t index
04104 )
04105 : view_(reinterpret_cast<view_pointer>(&view)),
04106 pointer_(0),
04107 index_(index),
04108 coordinates_(std::vector<size_t>(view.dimension()))
04109
04110
04111
04112
04113 {
04114 if(view.size() == 0) {
04115 marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
04116 }
04117 else {
04118 if(view.isSimple()) {
04119 marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
04120 pointer_ = &view(0) + index;
04121 }
04122 else {
04123 if(index >= view.size()) {
04124 if(view_->coordinateOrder() == LastMajorOrder) {
04125 coordinates_[0] = view.shape(0);
04126 for(size_t j=1; j<view.dimension(); ++j) {
04127 coordinates_[j] = view.shape(j)-1;
04128 }
04129 }
04130 else {
04131 size_t d = view_->dimension() - 1;
04132 coordinates_[d] = view.shape(d);
04133 for(size_t j=0; j<d; ++j) {
04134 coordinates_[j] = view.shape(j)-1;
04135 }
04136 }
04137 pointer_ = &view(view.size()-1) + 1;
04138 }
04139 else {
04140 view.indexToCoordinates(index, coordinates_.begin());
04141 pointer_ = &view(index);
04142 }
04143 }
04144 }
04145 testInvariant();
04146 }
04147
04153 template<class T, bool isConst, class A>
04154 inline Iterator<T, isConst, A>::Iterator
04155 (
04156 View<T, false, A>& view,
04157 const size_t index
04158 )
04159 : view_(reinterpret_cast<view_pointer>(&view)),
04160 pointer_(0),
04161 index_(index),
04162 coordinates_(std::vector<size_t>(view.dimension()))
04163
04164
04165
04166
04167 {
04168 if(view.size() == 0) {
04169 marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
04170 }
04171 else {
04172 if(view.isSimple()) {
04173 marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
04174 pointer_ = &view(0) + index;
04175 }
04176 else {
04177 if(index >= view.size()) {
04178 if(view_->coordinateOrder() == LastMajorOrder) {
04179 coordinates_[0] = view.shape(0);
04180 for(size_t j=1; j<view.dimension(); ++j) {
04181 coordinates_[j] = view.shape(j)-1;
04182 }
04183 }
04184 else {
04185 size_t d = view_->dimension() - 1;
04186 coordinates_[d] = view.shape(d);
04187 for(size_t j=0; j<d; ++j) {
04188 coordinates_[j] = view.shape(j)-1;
04189 }
04190 }
04191 pointer_ = &view(view.size()-1) + 1;
04192 }
04193 else {
04194 view.indexToCoordinates(index, coordinates_.begin());
04195 pointer_ = &view(index);
04196 }
04197 }
04198 }
04199 testInvariant();
04200 }
04201
04204 template<class T, bool isConst, class A>
04205 inline Iterator<T, isConst, A>::Iterator
04206 (
04207 const Iterator<T, false, A>& in
04208 )
04209 : view_(view_pointer(in.view_)),
04210 pointer_(pointer(in.pointer_)),
04211 index_(in.index_),
04212 coordinates_(in.coordinates_)
04213 {
04214 testInvariant();
04215 }
04216
04219 template<class T, bool isConst, class A>
04220 inline typename Iterator<T, isConst, A>::reference
04221 Iterator<T, isConst, A>::operator*() const
04222 {
04223 marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ < view_->size()));
04224 return *pointer_;
04225 }
04226
04229 template<class T, bool isConst, class A>
04230 inline typename Iterator<T, isConst, A>::pointer
04231 Iterator<T, isConst, A>::operator->() const
04232 {
04233 marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ < view_->size()));
04234 return pointer_;
04235 }
04236
04239 template<class T, bool isConst, class A>
04240 inline typename Iterator<T, isConst, A>::reference
04241 Iterator<T, isConst, A>::operator[]
04242 (
04243 const size_t x
04244 ) const
04245 {
04246 marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && x+index_ < view_->size()));
04247 return (*view_)(x+index_);
04248 }
04249
04250 template<class T, bool isConst, class A>
04251 inline Iterator<T, isConst, A>&
04252 Iterator<T, isConst, A>::operator+=
04253 (
04254 const difference_type& x
04255 )
04256 {
04257 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04258 if(index_ < view_->size()) {
04259 if(index_ + x < view_->size()) {
04260 index_ += x;
04261 if(view_->isSimple()) {
04262 pointer_ += x;
04263 }
04264 else {
04265 pointer_ = &((*view_)(index_));
04266 view_->indexToCoordinates(index_, coordinates_.begin());
04267 }
04268 }
04269 else {
04270
04271 index_ = view_->size();
04272 if(view_->isSimple()) {
04273 pointer_ = &(*view_)(0) + view_->size();
04274 }
04275 else {
04276 pointer_ = (&(*view_)(view_->size()-1)) + 1;
04277 view_->indexToCoordinates(view_->size()-1, coordinates_.begin());
04278 if(view_->coordinateOrder() == LastMajorOrder) {
04279 ++coordinates_[0];
04280 }
04281 else {
04282 ++coordinates_[view_->dimension()-1];
04283 }
04284 }
04285 }
04286 }
04287 testInvariant();
04288 return *this;
04289 }
04290
04291 template<class T, bool isConst, class A>
04292 inline Iterator<T, isConst, A>&
04293 Iterator<T, isConst, A>::operator-=
04294 (
04295 const difference_type& x
04296 )
04297 {
04298 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04299 marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<difference_type>(index_) >= x);
04300 index_ -= x;
04301 if(view_->isSimple()) {
04302 pointer_ -= x;
04303 }
04304 else {
04305 pointer_ = &((*view_)(index_));
04306 view_->indexToCoordinates(index_, coordinates_.begin());
04307 }
04308 testInvariant();
04309 return *this;
04310 }
04311
04314 template<class T, bool isConst, class A>
04315 inline Iterator<T, isConst, A>&
04316 Iterator<T, isConst, A>::operator++()
04317 {
04318 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04319 if(index_ < view_->size()) {
04320 ++index_;
04321 if(view_->isSimple()) {
04322 ++pointer_;
04323 }
04324 else {
04325 if(index_ < view_->size()) {
04326 if(view_->coordinateOrder() == LastMajorOrder) {
04327 for(size_t j=0; j<coordinates_.size(); ++j) {
04328 if(coordinates_[j] == view_->shape(j)-1) {
04329 pointer_ -= view_->strides(j) * coordinates_[j];
04330 coordinates_[j] = 0;
04331 }
04332 else {
04333 pointer_ += view_->strides(j);
04334 ++coordinates_[j];
04335 break;
04336 }
04337 }
04338 }
04339 else {
04340 size_t j = coordinates_.size() - 1;
04341 for(;;) {
04342 if(coordinates_[j] == view_->shape(j)-1) {
04343 pointer_ -= view_->strides(j) * coordinates_[j];
04344 coordinates_[j] = 0;
04345 }
04346 else {
04347 pointer_ += view_->strides(j);
04348 ++coordinates_[j];
04349 break;
04350 }
04351 if(j == 0) {
04352 break;
04353 }
04354 else {
04355 --j;
04356 }
04357 }
04358 }
04359 }
04360 else {
04361
04362 pointer_ = &((*view_)(view_->size()-1)) + 1;
04363 if(view_->coordinateOrder() == LastMajorOrder) {
04364 ++coordinates_[0];
04365 }
04366 else {
04367 ++coordinates_[view_->dimension()-1];
04368 }
04369 }
04370 }
04371 }
04372 testInvariant();
04373 return *this;
04374 }
04375
04378 template<class T, bool isConst, class A>
04379 inline Iterator<T, isConst, A>&
04380 Iterator<T, isConst, A>::operator--()
04381 {
04382 marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ > 0));
04383 --index_;
04384 if(view_->isSimple()) {
04385 --pointer_;
04386 }
04387 else {
04388 if(index_ == view_->size()) {
04389
04390 --pointer_;
04391 if(view_->coordinateOrder() == LastMajorOrder) {
04392 --coordinates_[0];
04393 }
04394 else {
04395 --coordinates_[view_->dimension() - 1];
04396 }
04397 }
04398 else {
04399 if(view_->coordinateOrder() == LastMajorOrder) {
04400 for(size_t j=0; j<coordinates_.size(); ++j) {
04401 if(coordinates_[j] == 0) {
04402 coordinates_[j] = view_->shape(j)-1;
04403 pointer_ += view_->strides(j) * coordinates_[j];
04404 }
04405 else {
04406 pointer_ -= view_->strides(j);
04407 --coordinates_[j];
04408 break;
04409 }
04410 }
04411 }
04412 else {
04413 size_t j = view_->dimension() - 1;
04414 for(;;) {
04415 if(coordinates_[j] == 0) {
04416 coordinates_[j] = view_->shape(j)-1;
04417 pointer_ += view_->strides(j) * coordinates_[j];
04418 }
04419 else {
04420 pointer_ -= view_->strides(j);
04421 --coordinates_[j];
04422 break;
04423 }
04424 if(j == 0) {
04425 break;
04426 }
04427 else {
04428 --j;
04429 }
04430 }
04431 }
04432 }
04433 }
04434 testInvariant();
04435 return *this;
04436 }
04437
04440 template<class T, bool isConst, class A>
04441 inline Iterator<T, isConst, A>
04442 Iterator<T, isConst, A>::operator++(int)
04443 {
04444 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04445 Iterator<T, isConst, A> copy = *this;
04446 ++(*this);
04447 return copy;
04448 }
04449
04452 template<class T, bool isConst, class A>
04453 inline Iterator<T, isConst, A>
04454 Iterator<T, isConst, A>::operator--(int)
04455 {
04456 marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ > 0));
04457 Iterator<T, isConst, A> copy = *this;
04458 --(*this);
04459 return copy;
04460 }
04461
04462 template<class T, bool isConst, class A>
04463 inline Iterator<T, isConst, A>
04464 Iterator<T, isConst, A>::operator+
04465 (
04466 const difference_type& x
04467 ) const
04468 {
04469 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04470 Iterator<T, isConst, A> tmp = *this;
04471 tmp += x;
04472 return tmp;
04473 }
04474
04475 template<class T, bool isConst, class A>
04476 inline Iterator<T, isConst, A>
04477 Iterator<T, isConst, A>::operator-
04478 (
04479 const difference_type& x
04480 ) const
04481 {
04482 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04483 Iterator<T, isConst, A> tmp = *this;
04484 tmp -= x;
04485 return tmp;
04486 }
04487
04488 template<class T, bool isConst, class A>
04489 template<bool isConstLocal>
04490 inline typename Iterator<T, isConst, A>::difference_type
04491 Iterator<T, isConst, A>::operator-
04492 (
04493 const Iterator<T, isConstLocal, A>& it
04494 ) const
04495 {
04496 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04497 marray_detail::Assert(MARRAY_NO_ARG_TEST || it.view_ != 0);
04498 return difference_type(index_)-difference_type(it.index_);
04499 }
04500
04501 template<class T, bool isConst, class A>
04502 template<bool isConstLocal>
04503 inline bool
04504 Iterator<T, isConst, A>::operator==
04505 (
04506 const Iterator<T, isConstLocal, A>& it
04507 ) const
04508 {
04509 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04510 marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && (void*)it.view_ == (void*)view_));
04511 return index_ == it.index_;
04512 }
04513
04514 template<class T, bool isConst, class A>
04515 template<bool isConstLocal>
04516 inline bool
04517 Iterator<T, isConst, A>::operator!=
04518 (
04519 const Iterator<T, isConstLocal, A>& it
04520 ) const
04521 {
04522 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04523 marray_detail::Assert(MARRAY_NO_ARG_TEST || it.view_ != 0);
04524 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
04525 static_cast<const void*>(it.view_) == static_cast<const void*>(view_));
04526 return index_ != it.index_;
04527 }
04528
04529 template<class T, bool isConst, class A>
04530 template<bool isConstLocal>
04531 inline bool
04532 Iterator<T, isConst, A>::operator<
04533 (
04534 const Iterator<T, isConstLocal, A>& it
04535 ) const
04536 {
04537 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04538 marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
04539 return(index_ < it.index_);
04540 }
04541
04542 template<class T, bool isConst, class A>
04543 template<bool isConstLocal>
04544 inline bool
04545 Iterator<T, isConst, A>::operator>
04546 (
04547 const Iterator<T, isConstLocal, A>& it
04548 ) const
04549 {
04550 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04551 marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
04552 return(index_ > it.index_);
04553 }
04554
04555 template<class T, bool isConst, class A>
04556 template<bool isConstLocal>
04557 inline bool
04558 Iterator<T, isConst, A>::operator<=
04559 (
04560 const Iterator<T, isConstLocal, A>& it
04561 ) const
04562 {
04563 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04564 marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
04565 return(index_ <= it.index_);
04566 }
04567
04568 template<class T, bool isConst, class A>
04569 template<bool isConstLocal>
04570 inline bool
04571 Iterator<T, isConst, A>::operator>=
04572 (
04573 const Iterator<T, isConstLocal, A>& it
04574 ) const
04575 {
04576 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04577 marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
04578 return(index_ >= it.index_);
04579 }
04580
04585 template<class T, bool isConst, class A>
04586 inline bool
04587 Iterator<T, isConst, A>::hasMore() const
04588 {
04589 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04590 return index_ < view_->size();
04591 }
04592
04597 template<class T, bool isConst, class A>
04598 inline size_t
04599 Iterator<T, isConst, A>::index() const
04600 {
04601 return index_;
04602 }
04603
04609 template<class T, bool isConst, class A>
04610 template<class CoordinateIterator>
04611 inline void
04612 Iterator<T, isConst, A>::coordinate
04613 (
04614 CoordinateIterator it
04615 ) const
04616 {
04617 marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
04618 marray_detail::Assert(MARRAY_NO_ARG_TEST || index_ < view_->size());
04619 if(view_->isSimple()) {
04620 view_->indexToCoordinates(index_, it);
04621 }
04622 else {
04623 for(size_t j=0; j<coordinates_.size(); ++j, ++it) {
04624 *it = coordinates_[j];
04625 }
04626 }
04627 }
04628
04629
04630
04635 template<class T, class A>
04636 inline
04637 Vector<T, A>::Vector
04638 (
04639 const allocator_type& allocator
04640 )
04641 : base(allocator)
04642 {
04643 testInvariant();
04644 }
04645
04650 template<class T, class A>
04651 template<class TLocal, bool isConstLocal, class ALocal>
04652 inline
04653 Vector<T, A>::Vector
04654 (
04655 const View<TLocal, isConstLocal, ALocal>& in
04656 )
04657 {
04658 in.testInvariant();
04659 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
04660 in.data_ == 0
04661 || (in.dimension() == 0 && in.size() == 1)
04662 || in.dimension() == 1
04663 );
04664 this->geometry_.size() = in.size();
04665 this->geometry_.coordinateOrder() = in.coordinateOrder();
04666 if(in.data_ != 0) {
04667 this->geometry_.resize(1);
04668 this->geometry_.shape(0) = in.size();
04669 this->geometry_.shapeStrides(0) = 1;
04670 this->geometry_.strides(0) = 1;
04671 this->data_ = this->dataAllocator_.allocate(this->size());
04672 if(in.dimension() == 0) {
04673 this->data_[0] = static_cast<T>(in(0));
04674 }
04675 else {
04676 if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
04677 memcpy(this->data_, in.data_, (this->size())*sizeof(T));
04678 }
04679 else {
04680 for(size_t j=0; j<in.size(); ++j) {
04681 this->data_[j] = static_cast<T>(in(j));
04682 }
04683 }
04684 }
04685 }
04686 testInvariant();
04687 }
04688
04695 template<class T, class A>
04696 inline
04697 Vector<T, A>::Vector
04698 (
04699 const size_t size,
04700 const T& value,
04701 const allocator_type& allocator
04702 )
04703 : base(allocator)
04704 {
04705 if(size != 0) {
04706 size_t shape[1] = {size};
04707 this->data_ = this->dataAllocator_.allocate(size);
04708 base::base::assign(&shape[0], &shape[1], this->data_);
04709 for(size_t j=0; j<size; ++j) {
04710 this->data_[j] = value;
04711 }
04712 }
04713 testInvariant();
04714 }
04715
04722 template<class T, class A>
04723 inline
04724 Vector<T, A>::Vector
04725 (
04726 const InitializationSkipping& is,
04727 const size_t size,
04728 const allocator_type& allocator
04729 )
04730 : base(allocator)
04731 {
04732 if(size != 0) {
04733 size_t shape[1] = {size};
04734 this->data_ = this->dataAllocator_.allocate(size);
04735 base::base::assign(&shape[0], &shape[1], this->data_);
04736 }
04737 testInvariant();
04738 }
04739
04745 template<class T, class A>
04746 template<class E, class Te>
04747 inline
04748 Vector<T, A>::Vector
04749 (
04750 const ViewExpression<E, Te>& expression,
04751 const allocator_type& allocator
04752 )
04753 : base(expression, allocator)
04754 {
04755 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 1);
04756 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
04757 testInvariant();
04758 }
04759
04760 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
04761
04762
04763
04764
04765
04766 template<class T, class A>
04767 inline
04768 Vector<T, A>::Vector
04769 (
04770 std::initializer_list<T> list,
04771 const allocator_type& allocator
04772 )
04773 : base(allocator)
04774 {
04775 if(list.size() != 0) {
04776 size_t shape[1] = {list.size()};
04777 this->data_ = this->dataAllocator_.allocate(list.size());
04778 base::base::assign(&shape[0], &shape[1], this->data_);
04779 int j=0;
04780 for(const T *p = list.begin(); p != list.end(); ++p, ++j) {
04781 this->data_[j] = *p;
04782 }
04783 }
04784 testInvariant();
04785 }
04786 #endif
04787
04794 template<class T, class A>
04795 inline Vector<T, A>&
04796 Vector<T, A>::operator=
04797 (
04798 const T& value
04799 )
04800 {
04801 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
04802 for(size_t j=0; j<this->size(); ++j) {
04803 this->data_[j] = value;
04804 }
04805 return *this;
04806 }
04807
04814 template<class T, class A>
04815 inline Vector<T, A>&
04816 Vector<T, A>::operator=
04817 (
04818 const Vector<T, A>& in
04819 )
04820 {
04821 in.testInvariant();
04822 base::operator=(in);
04823 testInvariant();
04824 return *this;
04825 }
04826
04833 template<class T, class A>
04834 template<class TLocal, bool isConstLocal, class ALocal>
04835 inline Vector<T, A>&
04836 Vector<T, A>::operator=
04837 (
04838 const View<TLocal, isConstLocal, ALocal>& in
04839 )
04840 {
04841 in.testInvariant();
04842 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
04843 in.data_ == 0 ||
04844 (in.dimension() == 0 && in.size() == 1) ||
04845 in.dimension() == 1);
04846 if(in.geometry_.dimension() == 0 && in.geometry_.size() == 1) {
04847
04848 if(this->size() != 1) {
04849 this->dataAllocator_.deallocate(this->data_, this->size());
04850 this->data_ = this->dataAllocator_.allocate(1);
04851 }
04852 this->data_[0] = static_cast<T>(in(0));
04853 this->geometry_.resize(1);
04854 this->geometry_.shape(0) = 1;
04855 this->geometry_.shapeStrides(0) = 1;
04856 this->geometry_.strides(0) = 1;
04857 this->geometry_.size() = 1;
04858 this->geometry_.isSimple() = true;
04859 this->geometry_.coordinateOrder() = in.coordinateOrder();
04860 }
04861 else {
04862 base::operator=(in);
04863 }
04864 testInvariant();
04865 return *this;
04866 }
04867
04872 template<class T, class A>
04873 template<class E, class Te>
04874 inline Vector<T, A>&
04875 Vector<T, A>::operator=
04876 (
04877 const ViewExpression<E, Te>& expression
04878 )
04879 {
04880 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 1);
04881 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
04882 base::operator=(expression);
04883 return *this;
04884 }
04885
04895 template<class T, class A>
04896 inline void
04897 Vector<T, A>::reshape
04898 (
04899 const size_t size
04900 )
04901 {
04902 marray_detail::Assert(size == this->size());
04903 }
04904
04910 template<class T, class A>
04911 inline void
04912 Vector<T, A>::resize
04913 (
04914 const size_t size,
04915 const T& value
04916 )
04917 {
04918 if(size == 0) {
04919 base::assign();
04920 }
04921 else {
04922 size_t shape[1] = {size};
04923 base::resize(&shape[0], &shape[1], value);
04924 }
04925 testInvariant();
04926 }
04927
04933 template<class T, class A>
04934 inline void
04935 Vector<T, A>::resize
04936 (
04937 const InitializationSkipping& is,
04938 const size_t size
04939 )
04940 {
04941 if(size == 0) {
04942 base::assign();
04943 }
04944 else {
04945 size_t shape[1] = {size};
04946 base::resize(is, &shape[0], &shape[1]);
04947 }
04948 testInvariant();
04949 }
04950
04953 template<class T, class A>
04954 inline T&
04955 Vector<T, A>::operator[]
04956 (
04957 const size_t index
04958 )
04959 {
04960 testInvariant();
04961 return this->operator()(index);
04962 }
04963
04966 template<class T, class A>
04967 inline const T&
04968 Vector<T, A>::operator[]
04969 (
04970 const size_t index
04971 ) const
04972 {
04973 testInvariant();
04974 return this->operator()(index);
04975 }
04976
04979 template<class T, class A>
04980 inline void
04981 Vector<T, A>::testInvariant() const
04982 {
04983 View<T, false, A>::testInvariant();
04984 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ == 0 ||
04985 (this->geometry_.isSimple() && this->geometry_.dimension() == 1));
04986 }
04987
04988
04989
04994 template<class T, class A>
04995 inline
04996 Matrix<T, A>::Matrix
04997 (
04998 const allocator_type& allocator
04999 )
05000 : base(allocator)
05001 {
05002 testInvariant();
05003 }
05004
05009 template<class T, class A>
05010 template<class TLocal, bool isConstLocal, class ALocal>
05011 inline
05012 Matrix<T, A>::Matrix
05013 (
05014 const View<TLocal, isConstLocal, ALocal>& in
05015 )
05016 {
05017 in.testInvariant();
05018 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
05019 in.data_ == 0 ||
05020 (in.dimension() == 0 && in.size() == 1) ||
05021 in.dimension() == 2);
05022 this->geometry_.size() = in.size();
05023 this->geometry_.coordinateOrder() = in.coordinateOrder();
05024 if(in.data_ != 0) {
05025 this->geometry_.resize(2);
05026 if(in.dimension() == 0) {
05027 this->geometry_.shape(0) = 1;
05028 this->geometry_.shape(1) = 1;
05029 this->geometry_.shapeStrides(0) = 1;
05030 this->geometry_.shapeStrides(1) = 1;
05031 this->geometry_.strides(0) = 1;
05032 this->geometry_.strides(1) = 1;
05033 this->data_ = this->dataAllocator_.allocate(1);
05034 this->data_[0] = static_cast<T>(in(0));
05035 }
05036 else {
05037 this->geometry_.shape(0) = in.shape(0);
05038 this->geometry_.shape(1) = in.shape(1);
05039 this->geometry_.shapeStrides(0) = in.geometry_.shapeStrides(0);
05040 this->geometry_.shapeStrides(1) = in.geometry_.shapeStrides(1);
05041 this->geometry_.strides(0) = in.geometry_.shapeStrides(0);
05042 this->geometry_.strides(1) = in.geometry_.shapeStrides(1);
05043 this->data_ = this->dataAllocator_.allocate(this->size());
05044 if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
05045 memcpy(this->data_, in.data_, (this->size())*sizeof(T));
05046 }
05047 else {
05048 for(size_t j=0; j<in.size(); ++j) {
05049 this->data_[j] = static_cast<T>(in(j));
05050 }
05051 }
05052 }
05053 }
05054 testInvariant();
05055 }
05056
05066 template<class T, class A>
05067 inline
05068 Matrix<T, A>::Matrix
05069 (
05070 const size_t n1,
05071 const size_t n2,
05072 const T& value,
05073 const CoordinateOrder& coordinateOrder,
05074 const allocator_type& allocator
05075 )
05076 : base(allocator)
05077 {
05078 if(n1 > 0 && n2 > 0) {
05079 size_t shape[2] = {n1, n2};
05080 T* data = this->dataAllocator_.allocate(n1 * n2);
05081 base::base::assign(&shape[0], &shape[2], data,
05082 coordinateOrder, coordinateOrder);
05083 for(size_t j=0; j<this->size(); ++j) {
05084 this->data_[j] = value;
05085 }
05086 }
05087 testInvariant();
05088 }
05089
05090
05100 template<class T, class A>
05101 inline
05102 Matrix<T, A>::Matrix
05103 (
05104 const InitializationSkipping& is,
05105 const size_t n1,
05106 const size_t n2,
05107 const CoordinateOrder& coordinateOrder,
05108 const allocator_type& allocator
05109 )
05110 : base(allocator)
05111 {
05112 if(n1 > 0 && n2 > 0) {
05113 size_t shape[2] = {n1, n2};
05114 this->data_ = this->dataAllocator_.allocate(n1 * n2);
05115 base::base::assign(&shape[0], &shape[2], this->data_,
05116 coordinateOrder, coordinateOrder);
05117 }
05118 testInvariant();
05119 }
05120
05126 template<class T, class A>
05127 template<class E, class Te>
05128 inline
05129 Matrix<T, A>::Matrix
05130 (
05131 const ViewExpression<E, Te>& expression,
05132 const allocator_type& allocator
05133 )
05134 : base(expression, allocator)
05135 {
05136 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 2);
05137 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
05138 testInvariant();
05139 }
05140
05147 template<class T, class A>
05148 inline Matrix<T, A>&
05149 Matrix<T, A>::operator=
05150 (
05151 const T& value
05152 )
05153 {
05154 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
05155 for(size_t j=0; j<this->size(); ++j) {
05156 this->data_[j] = value;
05157 }
05158 return *this;
05159 }
05160
05165 template<class T, class A>
05166 inline Matrix<T, A>&
05167 Matrix<T, A>::operator=
05168 (
05169 const Matrix<T, A>& in
05170 )
05171 {
05172 in.testInvariant();
05173 base::operator=(in);
05174 testInvariant();
05175 return *this;
05176 }
05177
05182 template<class T, class A>
05183 template<class TLocal, bool isConstLocal, class ALocal>
05184 inline Matrix<T, A>&
05185 Matrix<T, A>::operator=
05186 (
05187 const View<TLocal, isConstLocal, ALocal>& in
05188 )
05189 {
05190 marray_detail::Assert(MARRAY_NO_ARG_TEST ||
05191 in.data_ != 0 ||
05192 (in.dimension() == 0 && in.size() == 1) ||
05193 in.dimension() == 2);
05194 if(in.dimension() == 0 && in.size() == 1) {
05195
05196 if(this->size() != 1) {
05197 this->dataAllocator_.deallocate(this->data_, this->size());
05198 this->data_ = this->dataAllocator_.allocate(1);
05199 }
05200 this->data_[0] = static_cast<T>(in(0));
05201 this->geometry_.resize(2);
05202 this->geometry_.shape(0) = 1;
05203 this->geometry_.shape(1) = 1;
05204 this->geometry_.shapeStrides(0) = 1;
05205 this->geometry_.shapeStrides(1) = 1;
05206 this->geometry_.strides(0) = 1;
05207 this->geometry_.strides(1) = 1;
05208 this->geometry_.size() = 1;
05209 this->geometry_.isSimple() = true;
05210 this->geometry_.coordinateOrder() = in.coordinateOrder();
05211 }
05212 else {
05213 base::operator=(in);
05214 }
05215 testInvariant();
05216 return *this;
05217 }
05218
05223 template<class T, class A>
05224 template<class E, class Te>
05225 inline Matrix<T, A>&
05226 Matrix<T, A>::operator=
05227 (
05228 const ViewExpression<E, Te>& expression
05229 )
05230 {
05231 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 2);
05232 marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
05233 base::operator=(expression);
05234 return *this;
05235 }
05236
05243 template<class T, class A>
05244 inline void
05245 Matrix<T, A>::resize
05246 (
05247 const size_t n1,
05248 const size_t n2,
05249 const T& value
05250 )
05251 {
05252 if(n1 == 0 || n2 == 0) {
05253 base::assign();
05254 }
05255 else {
05256 size_t shape[2] = {n1, n2};
05257 base::resize(&shape[0], &shape[2], value);
05258 }
05259 testInvariant();
05260 }
05261
05268 template<class T, class A>
05269 inline void
05270 Matrix<T, A>::resize
05271 (
05272 const InitializationSkipping& is,
05273 const size_t n1,
05274 const size_t n2
05275 )
05276 {
05277 if(n1 == 0 || n2 == 0) {
05278 base::assign();
05279 }
05280 else {
05281 size_t shape[2] = {n1, n2};
05282 base::resize(is, &shape[0], &shape[2]);
05283 }
05284 testInvariant();
05285 }
05286
05294 template<class T, class A>
05295 inline void
05296 Matrix<T, A>::reshape
05297 (
05298 const size_t n1,
05299 const size_t n2
05300 )
05301 {
05302 marray_detail::Assert(MARRAY_NO_ARG_TEST || (n2 > 0 && n1 > 0));
05303 size_t shape[2] = {n1, n2};
05304 base::reshape(&shape[0], &shape[2]);
05305 testInvariant();
05306 }
05307
05310 template<class T, class A>
05311 inline void
05312 Matrix<T, A>::testInvariant() const
05313 {
05314 View<T, false, A>::testInvariant();
05315 marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ == 0 ||
05316 (this->geometry_.isSimple() && this->geometry_.dimension() == 2));
05317 }
05318
05319
05320
05321 template<class E, class T>
05322 class ViewExpression {
05323 public:
05324 typedef E expression_type;
05325 typedef T value_type;
05326
05327 const size_t dimension() const
05328 { return static_cast<const E&>(*this).dimension(); }
05329 const size_t size() const
05330 { return static_cast<const E&>(*this).size(); }
05331 const size_t shape(const size_t j) const
05332 { return static_cast<const E&>(*this).shape(j); }
05333 const size_t* shapeBegin() const
05334 { return static_cast<const E&>(*this).shapeBegin(); }
05335 const size_t* shapeEnd() const
05336 { return static_cast<const E&>(*this).shapeEnd(); }
05337 template<class Tv, bool isConst, class A>
05338 bool overlaps(const View<Tv, isConst, A>& v) const
05339 { return static_cast<const E&>(*this).overlaps(v); }
05340 const CoordinateOrder& coordinateOrder() const
05341 { return static_cast<const E&>(*this).coordinateOrder(); }
05342 const bool isSimple() const
05343 { return static_cast<const E&>(*this).isSimple(); }
05344 template<class Accessor>
05345 const T& operator()(Accessor it) const
05346 { return static_cast<const E&>(*this)(it); }
05347 const T& operator()(const size_t c0, const size_t c1) const
05348 { return static_cast<const E&>(*this)(c0, c1); }
05349 const T& operator()(const size_t c0, const size_t c1, const size_t c2) const
05350 { return static_cast<const E&>(*this)(c0, c1, c2); }
05351 const T& operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
05352 { return static_cast<const E&>(*this)(c0, c1, c2, c3); }
05353 const T& operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
05354 { return static_cast<const E&>(*this)(c0, c1, c2, c3, c4); }
05355 const T& operator[](const size_t offset) const
05356 { return static_cast<const E&>(*this)[offset]; }
05357 operator E&()
05358 { return static_cast<E&>(*this); }
05359 operator E const&() const
05360 { return static_cast<const E&>(*this); }
05361
05362
05363 class ExpressionIterator {
05364 public:
05365 ExpressionIterator(const ViewExpression<E, T>& expression)
05366 : expression_(expression),
05367 data_(&expression_(0)),
05368 offset_(0)
05369 {}
05370 void incrementCoordinate(const size_t coordinateIndex)
05371 { offset_ += expression_.strides(coordinateIndex); }
05372 void resetCoordinate(const size_t coordinateIndex)
05373 { offset_ -= expression_.strides(coordinateIndex)
05374
05375 * (expression_.shape(coordinateIndex) - 1); }
05376 const T& operator*() const
05377 {
05378
05379
05380
05381 return data_[offset_]; }
05382 private:
05383 const E& expression_;
05384 const T* data_;
05385 size_t offset_;
05386 };
05387
05388 };
05389
05390
05391 template<class E, class T, class UnaryFunctor>
05392 class UnaryViewExpression
05393 : public ViewExpression<UnaryViewExpression<E, T, UnaryFunctor>, T>
05394 {
05395 public:
05396 typedef E expression_type;
05397 typedef T value_type;
05398
05399 UnaryViewExpression(const ViewExpression<E, T>& e)
05400 : e_(e),
05401 unaryFunctor_(UnaryFunctor())
05402 {}
05403 const size_t dimension() const
05404 { return e_.dimension(); }
05405 const size_t size() const
05406 { return e_.size(); }
05407 const size_t shape(const size_t j) const
05408 { return e_.shape(j); }
05409 const size_t* shapeBegin() const
05410 { return e_.shapeBegin(); }
05411 const size_t* shapeEnd() const
05412 { return e_.shapeEnd(); }
05413 template<class Tv, bool isConst, class A>
05414 bool overlaps(const View<Tv, isConst, A>& v) const
05415 { return e_.overlaps(v); }
05416 const CoordinateOrder& coordinateOrder() const
05417 { return e_.coordinateOrder(); }
05418 const bool isSimple() const
05419 { return e_.isSimple(); }
05420 template<class Accessor>
05421 const T operator()(Accessor it) const
05422 { return unaryFunctor_(e_(it)); }
05423 const T operator()(const size_t c0, const size_t c1) const
05424 { return unaryFunctor_(e_(c0, c1)); }
05425 const T operator()(const size_t c0, const size_t c1,const size_t c2) const
05426 { return unaryFunctor_(e_(c0, c1, c2)); }
05427 const T operator()(const size_t c0, const size_t c1,const size_t c2, const size_t c3) const
05428 { return unaryFunctor_(e_(c0, c1, c2, c3)); }
05429 const T operator()(const size_t c0, const size_t c1,const size_t c2, const size_t c3, const size_t c4) const
05430 { return unaryFunctor_(e_(c0, c1, c2, c3, c4)); }
05431 const T operator[](const size_t offset) const
05432 { return unaryFunctor_(e_[offset]); }
05433
05434 class ExpressionIterator {
05435 public:
05436 ExpressionIterator(const UnaryViewExpression<E, T, UnaryFunctor>& expression)
05437 : unaryFunctor_(expression.unaryFunctor_),
05438 iterator_(expression.e_)
05439 {}
05440 void incrementCoordinate(const size_t coordinateIndex)
05441 { iterator_.incrementCoordinate(coordinateIndex); }
05442 void resetCoordinate(const size_t coordinateIndex)
05443 { iterator_.resetCoordinate(coordinateIndex); }
05444 const T operator*() const
05445 { return unaryFunctor_(*iterator_); }
05446 private:
05447 UnaryFunctor unaryFunctor_;
05448 typename E::ExpressionIterator iterator_;
05449 };
05450
05451 private:
05452 const E& e_;
05453 UnaryFunctor unaryFunctor_;
05454 };
05455
05456 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
05457 class BinaryViewExpression
05458 : public ViewExpression<BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>,
05459 typename marray_detail::PromoteType<T1, T2>::type>
05460 {
05461 public:
05462 typedef E1 expression_type_1;
05463 typedef E2 expression_type_2;
05464 typedef T1 value_type_1;
05465 typedef T2 value_type_2;
05466 typedef typename marray_detail::PromoteType<T1, T2>::type value_type;
05467 typedef BinaryFunctor functor_type;
05468 typedef ViewExpression<BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>,
05469 value_type> base;
05470
05471 BinaryViewExpression(const ViewExpression<E1, T1>& e1,
05472 const ViewExpression<E2, T2>& e2)
05473 : e1_(e1), e2_(e2),
05474 binaryFunctor_(BinaryFunctor())
05475 {
05476 if(!MARRAY_NO_DEBUG) {
05477 marray_detail::Assert(e1_.size() != 0 && e2_.size() != 0);
05478 marray_detail::Assert(e1_.dimension() == e2_.dimension());
05479 for(size_t j=0; j<e1_.dimension(); ++j) {
05480 marray_detail::Assert(e1_.shape(j) == e2_.shape(j));
05481 }
05482 }
05483 }
05484 const size_t dimension() const
05485 { return e1_.dimension() < e2_.dimension() ? e2_.dimension() : e1_.dimension(); }
05486 const size_t size() const
05487 { return e1_.size() < e2_.size() ? e2_.size() : e1_.size(); }
05488 const size_t shape(const size_t j) const
05489 { return e1_.dimension() < e2_.dimension() ? e2_.shape(j) : e1_.shape(j); }
05490 const size_t* shapeBegin() const
05491 { return e1_.dimension() < e2_.dimension() ? e2_.shapeBegin() : e1_.shapeBegin(); }
05492 const size_t* shapeEnd() const
05493 { return e1_.dimension() < e2_.dimension() ? e2_.shapeEnd() : e1_.shapeEnd(); }
05494 template<class Tv, bool isConst, class A>
05495 bool overlaps(const View<Tv, isConst, A>& v) const
05496 { return e1_.overlaps(v) || e2_.overlaps(v); }
05497 const CoordinateOrder& coordinateOrder() const
05498 { return e1_.coordinateOrder(); }
05499 const bool isSimple() const
05500 { return e1_.isSimple() && e2_.isSimple()
05501 && e1_.coordinateOrder() == e2_.coordinateOrder(); }
05502 template<class Accessor>
05503 const value_type operator()(Accessor it) const
05504 { return binaryFunctor_(e1_(it), e2_(it)); }
05505 const value_type operator()(const size_t c0, const size_t c1) const
05506 { return binaryFunctor_(e1_(c0, c1), e2_(c0, c1)); }
05507 const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
05508 { return binaryFunctor_(e1_(c0, c1, c2), e2_(c0, c1, c2)); }
05509 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
05510 { return binaryFunctor_(e1_(c0, c1, c2, c3), e2_(c0, c1, c2, c3)); }
05511 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
05512 { return binaryFunctor_(e1_(c0, c1, c2, c3, c4), e2_(c0, c1, c2, c3, c4)); }
05513 const value_type operator[](const size_t offset) const
05514 { return binaryFunctor_(e1_[offset], e2_[offset]); }
05515
05516 class ExpressionIterator {
05517 public:
05518 ExpressionIterator(const BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>& expression)
05519 : binaryFunctor_(expression.binaryFunctor_),
05520 iterator1_(expression.e1_),
05521 iterator2_(expression.e2_)
05522 {}
05523 void incrementCoordinate(const size_t coordinateIndex)
05524 { iterator1_.incrementCoordinate(coordinateIndex);
05525 iterator2_.incrementCoordinate(coordinateIndex); }
05526 void resetCoordinate(const size_t coordinateIndex)
05527 { iterator1_.resetCoordinate(coordinateIndex);
05528 iterator2_.resetCoordinate(coordinateIndex); }
05529 const value_type operator*() const
05530 { return binaryFunctor_(*iterator1_, *iterator2_); }
05531 private:
05532 BinaryFunctor binaryFunctor_;
05533 typename E1::ExpressionIterator iterator1_;
05534 typename E2::ExpressionIterator iterator2_;
05535 };
05536
05537 private:
05538 const expression_type_1& e1_;
05539 const expression_type_2& e2_;
05540 BinaryFunctor binaryFunctor_;
05541 };
05542
05543 template<class E, class T, class S, class BinaryFunctor>
05544 class BinaryViewExpressionScalarFirst
05545 : public ViewExpression<BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>,
05546 typename marray_detail::PromoteType<T, S>::type> {
05547 public:
05548 typedef E expression_type;
05549 typedef T value_type_1;
05550 typedef S scalar_type;
05551 typedef typename marray_detail::PromoteType<T, S>::type value_type;
05552 typedef BinaryFunctor functor_type;
05553 typedef ViewExpression<BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>,
05554 value_type> base;
05555
05556 BinaryViewExpressionScalarFirst(const ViewExpression<E, T>& e,
05557 const scalar_type& scalar)
05558 : e_(e),
05559 scalar_(scalar), binaryFunctor_(BinaryFunctor())
05560 { }
05561 const size_t dimension() const
05562 { return e_.dimension(); }
05563 const size_t size() const
05564 { return e_.size(); }
05565 const size_t shape(const size_t j) const
05566 { return e_.shape(j); }
05567 const size_t* shapeBegin() const
05568 { return e_.shapeBegin(); }
05569 const size_t* shapeEnd() const
05570 { return e_.shapeEnd(); }
05571 template<class Tv, bool isConst, class A>
05572 bool overlaps(const View<Tv, isConst, A>& v) const
05573 { return e_.overlaps(v); }
05574 const CoordinateOrder& coordinateOrder() const
05575 { return e_.coordinateOrder(); }
05576 const bool isSimple() const
05577 { return e_.isSimple(); }
05578 template<class Accessor>
05579 const value_type operator()(Accessor it) const
05580 { return binaryFunctor_(scalar_, e_(it)); }
05581 const value_type operator()(const size_t c0, const size_t c1) const
05582 { return binaryFunctor_(scalar_, e_(c0, c1)); }
05583 const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
05584 { return binaryFunctor_(scalar_, e_(c0, c1, c2)); }
05585 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
05586 { return binaryFunctor_(scalar_, e_(c0, c1, c2, c3)); }
05587 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
05588 { return binaryFunctor_(scalar_, e_(c0, c1, c2, c3, c4)); }
05589 const value_type operator[](const size_t offset) const
05590 { return binaryFunctor_(scalar_, e_[offset]); }
05591
05592 class ExpressionIterator {
05593 public:
05594 ExpressionIterator(const BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>& expression)
05595 : binaryFunctor_(expression.binaryFunctor_),
05596 scalar_(expression.scalar_),
05597 iterator_(expression.e_)
05598 {}
05599 void incrementCoordinate(const size_t coordinateIndex)
05600 { iterator_.incrementCoordinate(coordinateIndex); }
05601 void resetCoordinate(const size_t coordinateIndex)
05602 { iterator_.resetCoordinate(coordinateIndex); }
05603 const T operator*() const
05604 { return binaryFunctor_(scalar_, *iterator_); }
05605 private:
05606 BinaryFunctor binaryFunctor_;
05607 const typename BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>::scalar_type& scalar_;
05608 typename E::ExpressionIterator iterator_;
05609 };
05610
05611 private:
05612 const expression_type& e_;
05613 const scalar_type scalar_;
05614 BinaryFunctor binaryFunctor_;
05615 };
05616
05617 template<class E, class T, class S, class BinaryFunctor>
05618 class BinaryViewExpressionScalarSecond
05619 : public ViewExpression<BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>,
05620 typename marray_detail::PromoteType<T, S>::type> {
05621 public:
05622 typedef T value_type_1;
05623 typedef E expression_type;
05624 typedef S scalar_type;
05625 typedef typename marray_detail::PromoteType<T, S>::type value_type;
05626 typedef BinaryFunctor functor_type;
05627 typedef ViewExpression<BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>,
05628 value_type> base;
05629
05630 BinaryViewExpressionScalarSecond(const ViewExpression<E, T>& e,
05631 const scalar_type& scalar)
05632 : e_(e),
05633 scalar_(scalar), binaryFunctor_(BinaryFunctor())
05634 { }
05635 const size_t dimension() const
05636 { return e_.dimension(); }
05637 const size_t size() const
05638 { return e_.size(); }
05639 const size_t shape(const size_t j) const
05640 { return e_.shape(j); }
05641 const size_t* shapeBegin() const
05642 { return e_.shapeBegin(); }
05643 const size_t* shapeEnd() const
05644 { return e_.shapeEnd(); }
05645 template<class Tv, bool isConst, class A>
05646 bool overlaps(const View<Tv, isConst, A>& v) const
05647 { return e_.overlaps(v); }
05648 const CoordinateOrder& coordinateOrder() const
05649 { return e_.coordinateOrder(); }
05650 const bool isSimple() const
05651 { return e_.isSimple(); }
05652 template<class Accessor>
05653 const value_type operator()(Accessor it) const
05654 { return binaryFunctor_(e_(it), scalar_); }
05655 const value_type operator()(const size_t c0, const size_t c1) const
05656 { return binaryFunctor_(e_(c0, c1), scalar_); }
05657 const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
05658 { return binaryFunctor_(e_(c0, c1, c2), scalar_); }
05659 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
05660 { return binaryFunctor_(e_(c0, c1, c2, c3), scalar_); }
05661 const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
05662 { return binaryFunctor_(e_(c0, c1, c2, c3, c4), scalar_); }
05663 const value_type operator[](const size_t offset) const
05664 { return binaryFunctor_(e_[offset], scalar_); }
05665
05666 class ExpressionIterator {
05667 public:
05668 ExpressionIterator(const BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>& expression)
05669 : binaryFunctor_(expression.binaryFunctor_),
05670 scalar_(expression.scalar_),
05671 iterator_(expression.e_)
05672 {}
05673 void incrementCoordinate(const size_t coordinateIndex)
05674 { iterator_.incrementCoordinate(coordinateIndex); }
05675 void resetCoordinate(const size_t coordinateIndex)
05676 { iterator_.resetCoordinate(coordinateIndex); }
05677 const T operator*() const
05678 { return binaryFunctor_(*iterator_, scalar_); }
05679 private:
05680 BinaryFunctor binaryFunctor_;
05681 const typename BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>::scalar_type& scalar_;
05682 typename E::ExpressionIterator iterator_;
05683 };
05684
05685 private:
05686 const expression_type& e_;
05687 const scalar_type scalar_;
05688 BinaryFunctor binaryFunctor_;
05689 };
05690
05691
05692
05693
05694
05695 namespace marray_detail {
05696
05697 template<class A>
05698 class Geometry
05699 {
05700 public:
05701 typedef typename A::template rebind<size_t>::other allocator_type;
05702
05703 Geometry(const allocator_type& = allocator_type());
05704 Geometry(const size_t, const CoordinateOrder& = defaultOrder,
05705 const size_t = 0, const bool = true,
05706 const allocator_type& = allocator_type());
05707 template<class ShapeIterator>
05708 Geometry(ShapeIterator, ShapeIterator,
05709 const CoordinateOrder& = defaultOrder,
05710 const CoordinateOrder& = defaultOrder,
05711 const allocator_type& = allocator_type());
05712 template<class ShapeIterator, class StrideIterator>
05713 Geometry(ShapeIterator, ShapeIterator, StrideIterator,
05714 const CoordinateOrder& = defaultOrder,
05715 const allocator_type& = allocator_type());
05716 Geometry(const Geometry<A>&);
05717 ~Geometry();
05718
05719 Geometry<A>& operator=(const Geometry<A>&);
05720
05721 void resize(const size_t dimension);
05722 const size_t dimension() const;
05723 const size_t shape(const size_t) const;
05724 size_t& shape(const size_t);
05725 const size_t shapeStrides(const size_t) const;
05726 size_t& shapeStrides(const size_t);
05727 const size_t strides(const size_t) const;
05728 size_t& strides(const size_t);
05729 const size_t* shapeBegin() const;
05730 size_t* shapeBegin();
05731 const size_t* shapeEnd() const;
05732 size_t* shapeEnd();
05733 const size_t* shapeStridesBegin() const;
05734 size_t* shapeStridesBegin();
05735 const size_t* shapeStridesEnd() const;
05736 size_t* shapeStridesEnd();
05737 const size_t* stridesBegin() const;
05738 size_t* stridesBegin();
05739 const size_t* stridesEnd() const;
05740 size_t* stridesEnd();
05741 const size_t size() const;
05742 size_t& size();
05743 const CoordinateOrder& coordinateOrder() const;
05744 CoordinateOrder& coordinateOrder();
05745 const bool isSimple() const;
05746 void updateSimplicity();
05747 bool& isSimple();
05748
05749 private:
05750 allocator_type allocator_;
05751 size_t* shape_;
05752 size_t* shapeStrides_;
05753
05754
05755 size_t* strides_;
05756 size_t dimension_;
05757 size_t size_;
05758
05759 CoordinateOrder coordinateOrder_;
05760 bool isSimple_;
05761
05762
05763
05764 };
05765
05766 template<class A>
05767 inline
05768 Geometry<A>::Geometry
05769 (
05770 const typename Geometry<A>::allocator_type& allocator
05771 )
05772 : allocator_(allocator),
05773 shape_(0),
05774 shapeStrides_(0),
05775 strides_(0),
05776 dimension_(0),
05777 size_(0),
05778 coordinateOrder_(defaultOrder),
05779 isSimple_(true)
05780 {
05781 }
05782
05783 template<class A>
05784 inline
05785 Geometry<A>::Geometry
05786 (
05787 const Geometry<A>& g
05788 )
05789 : allocator_(g.allocator_),
05790 shape_(g.dimension_==0 ? 0 : allocator_.allocate(g.dimension_*3)),
05791 shapeStrides_(shape_ + g.dimension_),
05792 strides_(shapeStrides_ + g.dimension_),
05793 dimension_(g.dimension_),
05794 size_(g.size_),
05795 coordinateOrder_(g.coordinateOrder_),
05796 isSimple_(g.isSimple_)
05797 {
05798
05799
05800
05801
05802
05803
05804
05805 memcpy(shape_, g.shape_, (dimension_*3)*sizeof(size_t));
05806 }
05807
05808 template<class A>
05809 inline
05810 Geometry<A>::Geometry
05811 (
05812 const size_t dimension,
05813 const CoordinateOrder& order,
05814 const size_t size,
05815 const bool isSimple,
05816 const typename Geometry<A>::allocator_type& allocator
05817 )
05818 : allocator_(allocator),
05819 shape_(allocator_.allocate(dimension*3)),
05820 shapeStrides_(shape_+dimension),
05821 strides_(shapeStrides_+dimension),
05822 dimension_(dimension),
05823 size_(size),
05824 coordinateOrder_(order),
05825 isSimple_(isSimple)
05826 {
05827 }
05828
05829 template<class A>
05830 template<class ShapeIterator>
05831 inline
05832 Geometry<A>::Geometry
05833 (
05834 ShapeIterator begin,
05835 ShapeIterator end,
05836 const CoordinateOrder& externalCoordinateOrder,
05837 const CoordinateOrder& internalCoordinateOrder,
05838 const typename Geometry<A>::allocator_type& allocator
05839 )
05840 : allocator_(allocator),
05841 shape_(allocator_.allocate(std::distance(begin, end) * 3)),
05842 shapeStrides_(shape_ + std::distance(begin, end)),
05843 strides_(shapeStrides_ + std::distance(begin, end)),
05844 dimension_(std::distance(begin, end)),
05845 size_(1),
05846 coordinateOrder_(internalCoordinateOrder),
05847 isSimple_(true)
05848 {
05849 if(dimension_ != 0) {
05850 isSimple_ = (externalCoordinateOrder == internalCoordinateOrder);
05851 for(size_t j=0; j<dimension(); ++j, ++begin) {
05852 const size_t s = static_cast<size_t>(*begin);
05853 shape(j) = s;
05854 size() *= s;
05855 }
05856 stridesFromShape(shapeBegin(), shapeEnd(), stridesBegin(),
05857 externalCoordinateOrder);
05858 stridesFromShape(shapeBegin(), shapeEnd(), shapeStridesBegin(),
05859 internalCoordinateOrder);
05860 }
05861 }
05862
05863 template<class A>
05864 template<class ShapeIterator, class StrideIterator>
05865 inline
05866 Geometry<A>::Geometry
05867 (
05868 ShapeIterator begin,
05869 ShapeIterator end,
05870 StrideIterator it,
05871 const CoordinateOrder& internalCoordinateOrder,
05872 const typename Geometry<A>::allocator_type& allocator
05873 )
05874 : allocator_(allocator),
05875 shape_(allocator_.allocate(std::distance(begin, end) * 3)),
05876 shapeStrides_(shape_ + std::distance(begin, end)),
05877 strides_(shapeStrides_ + std::distance(begin, end)),
05878 dimension_(std::distance(begin, end)),
05879 size_(1),
05880 coordinateOrder_(internalCoordinateOrder),
05881 isSimple_(true)
05882 {
05883 if(dimension() != 0) {
05884 for(size_t j=0; j<dimension(); ++j, ++begin, ++it) {
05885 const size_t s = static_cast<size_t>(*begin);
05886 shape(j) = s;
05887 size() *= s;
05888 strides(j) = *it;
05889 }
05890 stridesFromShape(shapeBegin(), shapeEnd(), shapeStridesBegin(),
05891 internalCoordinateOrder);
05892 updateSimplicity();
05893 }
05894 }
05895
05896 template<class A>
05897 inline
05898 Geometry<A>::~Geometry()
05899 {
05900 allocator_.deallocate(shape_, dimension_*3);
05901 }
05902
05903 template<class A>
05904 inline Geometry<A>&
05905 Geometry<A>::operator=
05906 (
05907 const Geometry<A>& g
05908 )
05909 {
05910 if(&g != this) {
05911 if(g.dimension_ != dimension_) {
05912 allocator_.deallocate(shape_, dimension_*3);
05913 dimension_ = g.dimension_;
05914 shape_ = allocator_.allocate(dimension_*3);
05915 shapeStrides_ = shape_+dimension_;
05916 strides_ = shapeStrides_+dimension_;
05917 dimension_ = g.dimension_;
05918 }
05919
05920
05921
05922
05923
05924
05925
05926 memcpy(shape_, g.shape_, (dimension_*3)*sizeof(size_t));
05927 size_ = g.size_;
05928 coordinateOrder_ = g.coordinateOrder_;
05929 isSimple_ = g.isSimple_;
05930 }
05931 return *this;
05932 }
05933
05934 template<class A>
05935 inline void
05936 Geometry<A>::resize
05937 (
05938 const size_t dimension
05939 )
05940 {
05941 if(dimension != dimension_) {
05942 size_t* newShape = allocator_.allocate(dimension*3);
05943 size_t* newShapeStrides = newShape + dimension;
05944 size_t* newStrides = newShapeStrides + dimension;
05945 for(size_t j=0; j<( (dimension < dimension_) ? dimension : dimension_); ++j) {
05946
05947 newShape[j] = shape(j);
05948 newShapeStrides[j] = shapeStrides(j);
05949 newStrides[j] = strides(j);
05950 }
05951 allocator_.deallocate(shape_, dimension_*3);
05952 shape_ = newShape;
05953 shapeStrides_ = newShapeStrides;
05954 strides_ = newStrides;
05955 dimension_ = dimension;
05956 }
05957 }
05958
05959 template<class A>
05960 inline const size_t
05961 Geometry<A>::dimension() const
05962 {
05963 return dimension_;
05964 }
05965
05966 template<class A>
05967 inline const size_t
05968 Geometry<A>::shape(const size_t j) const
05969 {
05970 Assert(MARRAY_NO_DEBUG || j<dimension_);
05971 return shape_[j];
05972 }
05973
05974 template<class A>
05975 inline size_t&
05976 Geometry<A>::shape(const size_t j)
05977 {
05978 Assert(MARRAY_NO_DEBUG || j<dimension_);
05979 return shape_[j];
05980 }
05981
05982 template<class A>
05983 inline const size_t
05984 Geometry<A>::shapeStrides
05985 (
05986 const size_t j
05987 ) const
05988 {
05989 Assert(MARRAY_NO_DEBUG || j<dimension_);
05990 return shapeStrides_[j];
05991 }
05992
05993 template<class A>
05994 inline size_t&
05995 Geometry<A>::shapeStrides
05996 (
05997 const size_t j
05998 )
05999 {
06000 Assert(MARRAY_NO_DEBUG || j<dimension_);
06001 return shapeStrides_[j];
06002 }
06003
06004 template<class A>
06005 inline const size_t
06006 Geometry<A>::strides
06007 (
06008 const size_t j
06009 ) const
06010 {
06011 Assert(MARRAY_NO_DEBUG || j<dimension_);
06012 return strides_[j];
06013 }
06014
06015 template<class A>
06016 inline size_t&
06017 Geometry<A>::strides
06018 (
06019 const size_t j
06020 )
06021 {
06022 Assert(MARRAY_NO_DEBUG || j<dimension_);
06023 return strides_[j];
06024 }
06025
06026 template<class A>
06027 inline const size_t*
06028 Geometry<A>::shapeBegin() const
06029 {
06030 return shape_;
06031 }
06032
06033 template<class A>
06034 inline size_t*
06035 Geometry<A>::shapeBegin()
06036 {
06037 return shape_;
06038 }
06039
06040 template<class A>
06041 inline const size_t*
06042 Geometry<A>::shapeEnd() const
06043 {
06044 return shape_ + dimension_;
06045 }
06046
06047 template<class A>
06048 inline size_t*
06049 Geometry<A>::shapeEnd()
06050 {
06051 return shape_ + dimension_;
06052 }
06053
06054 template<class A>
06055 inline const size_t*
06056 Geometry<A>::shapeStridesBegin() const
06057 {
06058 return shapeStrides_;
06059 }
06060
06061 template<class A>
06062 inline size_t*
06063 Geometry<A>::shapeStridesBegin()
06064 {
06065 return shapeStrides_;
06066 }
06067
06068 template<class A>
06069 inline const size_t*
06070 Geometry<A>::shapeStridesEnd() const
06071 {
06072 return shapeStrides_ + dimension_;
06073 }
06074
06075 template<class A>
06076 inline size_t*
06077 Geometry<A>::shapeStridesEnd()
06078 {
06079 return shapeStrides_ + dimension_;
06080 }
06081
06082 template<class A>
06083 inline const size_t*
06084 Geometry<A>::stridesBegin() const
06085 {
06086 return strides_;
06087 }
06088
06089 template<class A>
06090 inline size_t*
06091 Geometry<A>::stridesBegin()
06092 {
06093 return strides_;
06094 }
06095
06096 template<class A>
06097 inline const size_t*
06098 Geometry<A>::stridesEnd() const
06099 {
06100 return strides_ + dimension_;
06101 }
06102
06103 template<class A>
06104 inline size_t*
06105 Geometry<A>::stridesEnd()
06106 {
06107 return strides_ + dimension_;
06108 }
06109
06110 template<class A>
06111 inline const size_t
06112 Geometry<A>::size() const
06113 {
06114 return size_;
06115 }
06116
06117 template<class A>
06118 inline size_t&
06119 Geometry<A>::size()
06120 {
06121 return size_;
06122 }
06123
06124 template<class A>
06125 inline const CoordinateOrder&
06126 Geometry<A>::coordinateOrder() const
06127 {
06128 return coordinateOrder_;
06129 }
06130
06131 template<class A>
06132 inline CoordinateOrder&
06133 Geometry<A>::coordinateOrder()
06134 {
06135 return coordinateOrder_;
06136 }
06137
06138 template<class A>
06139 inline const bool
06140 Geometry<A>::isSimple() const
06141 {
06142 return isSimple_;
06143 }
06144
06145 template<class A>
06146 inline bool&
06147 Geometry<A>::isSimple()
06148 {
06149 return isSimple_;
06150 }
06151
06152 template<class A>
06153 inline void
06154 Geometry<A>::updateSimplicity()
06155 {
06156 for(size_t j=0; j<dimension(); ++j) {
06157 if(shapeStrides(j) != strides(j)) {
06158 isSimple_ = false;
06159 return;
06160 }
06161 }
06162 isSimple_ = true;
06163
06164 }
06165
06166 template<class ShapeIterator, class StridesIterator>
06167 inline void
06168 stridesFromShape
06169 (
06170 ShapeIterator begin,
06171 ShapeIterator end,
06172 StridesIterator strideBegin,
06173 const CoordinateOrder& coordinateOrder
06174 )
06175 {
06176 Assert(MARRAY_NO_ARG_TEST || std::distance(begin, end) != 0);
06177 size_t dimension = std::distance(begin, end);
06178 ShapeIterator shapeIt;
06179 StridesIterator strideIt;
06180 if(coordinateOrder == FirstMajorOrder) {
06181 shapeIt = begin + (dimension-1);
06182 strideIt = strideBegin + (dimension-1);
06183 *strideIt = 1;
06184 for(size_t j=1; j<dimension; ++j) {
06185 size_t tmp = *strideIt;
06186 --strideIt;
06187 (*strideIt) = tmp * (*shapeIt);
06188 --shapeIt;
06189 }
06190 }
06191 else {
06192 shapeIt = begin;
06193 strideIt = strideBegin;
06194 *strideIt = 1;
06195 for(size_t j=1; j<dimension; ++j) {
06196 size_t tmp = *strideIt;
06197 ++strideIt;
06198 (*strideIt) = tmp * (*shapeIt);
06199 ++shapeIt;
06200 }
06201 }
06202 }
06203
06204 template<unsigned short N, class Functor, class T, class A>
06205 struct OperateHelperUnary
06206 {
06207 static inline void operate
06208 (
06209 View<T, false, A>& v,
06210 Functor f,
06211 T* data
06212 )
06213 {
06214 for(size_t j=0; j<v.shape(N-1); ++j) {
06215 OperateHelperUnary<N-1, Functor, T, A>::operate(v, f, data);
06216 data += v.strides(N-1);
06217 }
06218 data -= v.shape(N-1) * v.strides(N-1);
06219 }
06220 };
06221
06222
06223 template<class Functor, class T, class A>
06224 struct OperateHelperUnary<0, Functor, T, A>
06225 {
06226 static inline void operate
06227 (
06228 View<T, false, A>& v,
06229 Functor f,
06230 T* data
06231 )
06232 {
06233 f(*data);
06234 }
06235 };
06236
06237 template<unsigned short N, class Functor, class T1, class T2, class A>
06238 struct OperateHelperBinaryScalar
06239 {
06240 static inline void operate
06241 (
06242 View<T1, false, A>& v,
06243 const T2& x,
06244 Functor f,
06245 T1* data
06246 )
06247 {
06248 for(size_t j=0; j<v.shape(N-1); ++j) {
06249 OperateHelperBinaryScalar<N-1, Functor, T1, T2, A>::operate(
06250 v, x, f, data);
06251 data += v.strides(N-1);
06252 }
06253 data -= v.shape(N-1) * v.strides(N-1);
06254 }
06255 };
06256
06257 template<class Functor, class T1, class T2, class A>
06258 struct OperateHelperBinaryScalar<0, Functor, T1, T2, A>
06259 {
06260 static inline void operate
06261 (
06262 View<T1, false, A>& v,
06263 const T2& x,
06264 Functor f,
06265 T1* data
06266 )
06267 {
06268 f(*data, x);
06269 }
06270 };
06271
06272 template<unsigned short N, class Functor, class T1, class T2,
06273 bool isConst, class A1, class A2>
06274 struct OperateHelperBinary
06275 {
06276 static inline void operate
06277 (
06278 View<T1, false, A1>& v,
06279 const View<T2, isConst, A2>& w,
06280 Functor f,
06281 T1* data1,
06282 const T2* data2
06283 )
06284 {
06285 for(size_t j=0; j<v.shape(N-1); ++j) {
06286 OperateHelperBinary<N-1, Functor, T1, T2, isConst, A1, A2>::operate(
06287 v, w, f, data1, data2);
06288 data1 += v.strides(N-1);
06289 data2 += w.strides(N-1);
06290 }
06291 data1 -= v.shape(N-1) * v.strides(N-1);
06292 data2 -= w.shape(N-1) * w.strides(N-1);
06293 }
06294 };
06295
06296 template<class Functor, class T1, class T2, bool isConst, class A1, class A2>
06297 struct OperateHelperBinary<0, Functor, T1, T2, isConst, A1, A2>
06298 {
06299 static inline void operate
06300 (
06301 View<T1, false, A1>& v,
06302 const View<T2, isConst, A2>& w,
06303 Functor f,
06304 T1* data1,
06305 const T2* data2
06306 )
06307 {
06308 f(*data1, *data2);
06309 }
06310 };
06311
06312 template<class TFrom, class TTo, class AFrom, class ATo>
06313 struct AssignmentOperatorHelper<false, TFrom, TTo, AFrom, ATo>
06314 {
06315
06316
06317
06318
06319
06320
06321
06322 static void execute
06323 (
06324 const View<TFrom, true, AFrom>& from,
06325 View<TTo, false, ATo>& to
06326 )
06327 {
06328 typedef typename View<TFrom, true, AFrom>::const_iterator FromIterator;
06329 typedef typename View<TTo, false, ATo>::iterator ToIterator;
06330 if(!MARRAY_NO_ARG_TEST) {
06331 Assert(from.data_ != 0 && from.dimension() == to.dimension());
06332 for(size_t j=0; j<from.dimension(); ++j) {
06333 Assert(from.shape(j) == to.shape(j));
06334 }
06335 }
06336 if(from.overlaps(to)) {
06337 Marray<TFrom, AFrom> m = from;
06338 execute(m, to);
06339 }
06340 else if(from.coordinateOrder() == to.coordinateOrder()
06341 && from.isSimple() && to.isSimple()
06342 && IsEqual<TFrom, TTo>::type) {
06343 memcpy(to.data_, from.data_, (from.size())*sizeof(TFrom));
06344 }
06345 else if(from.dimension() == 1)
06346 OperateHelperBinary<1, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06347 else if(from.dimension() == 2)
06348 OperateHelperBinary<2, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06349 else if(from.dimension() == 3)
06350 OperateHelperBinary<3, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06351 else if(from.dimension() == 4)
06352 OperateHelperBinary<4, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06353 else if(from.dimension() == 5)
06354 OperateHelperBinary<5, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06355 else if(from.dimension() == 6)
06356 OperateHelperBinary<6, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06357 else if(from.dimension() == 7)
06358 OperateHelperBinary<7, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06359 else if(from.dimension() == 8)
06360 OperateHelperBinary<8, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06361 else if(from.dimension() == 9)
06362 OperateHelperBinary<9, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06363 else if(from.dimension() == 10)
06364 OperateHelperBinary<10, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06365 else {
06366 FromIterator itFrom = from.begin();
06367 ToIterator itTo = to.begin();
06368 for(; itFrom.hasMore(); ++itFrom, ++itTo) {
06369 *itTo = static_cast<TTo>(*itFrom);
06370 }
06371 }
06372 }
06373
06378 static void execute
06379 (
06380 const View<TFrom, false, AFrom>& from,
06381 View<TTo, false, ATo>& to
06382 )
06383 {
06384 typedef typename View<TFrom, false, AFrom>::const_iterator FromIterator;
06385 typedef typename View<TTo, false, ATo>::iterator ToIterator;
06386 if(static_cast<const void*>(&from) != static_cast<const void*>(&to)) {
06387 if(to.data_ == 0) {
06388
06389 Assert(MARRAY_NO_ARG_TEST || sizeof(TTo) == sizeof(TFrom));
06390 to.data_ = static_cast<TTo*>(static_cast<void*>(from.data_));
06391 to.geometry_ = from.geometry_;
06392 }
06393 else {
06394 if(!MARRAY_NO_ARG_TEST) {
06395 Assert(from.data_ != 0 && from.dimension() == to.dimension());
06396 for(size_t j=0; j<from.dimension(); ++j) {
06397 Assert(from.shape(j) == to.shape(j));
06398 }
06399 }
06400 if(from.overlaps(to)) {
06401 Marray<TFrom, AFrom> m = from;
06402 execute(m, to);
06403 }
06404 else if(from.coordinateOrder() == to.coordinateOrder()
06405 && from.isSimple() && to.isSimple()
06406 && IsEqual<TFrom, TTo>::type) {
06407 memcpy(to.data_, from.data_, (from.size())*sizeof(TFrom));
06408 }
06409 else if(from.dimension() == 1)
06410 OperateHelperBinary<1, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06411 else if(from.dimension() == 2)
06412 OperateHelperBinary<2, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06413 else if(from.dimension() == 3)
06414 OperateHelperBinary<3, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06415 else if(from.dimension() == 4)
06416 OperateHelperBinary<4, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06417 else if(from.dimension() == 5)
06418 OperateHelperBinary<5, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06419 else if(from.dimension() == 6)
06420 OperateHelperBinary<6, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06421 else if(from.dimension() == 7)
06422 OperateHelperBinary<7, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06423 else if(from.dimension() == 8)
06424 OperateHelperBinary<8, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06425 else if(from.dimension() == 9)
06426 OperateHelperBinary<9, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06427 else if(from.dimension() == 10)
06428 OperateHelperBinary<10, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
06429 else {
06430 FromIterator itFrom = from.begin();
06431 ToIterator itTo = to.begin();
06432 for(; itFrom.hasMore(); ++itFrom, ++itTo) {
06433 *itTo = static_cast<TTo>(*itFrom);
06434 }
06435 }
06436 }
06437 }
06438 }
06439 };
06440
06441 template<class TFrom, class TTo, class AFrom, class ATo>
06442 struct AssignmentOperatorHelper<true, TFrom, TTo, AFrom, ATo>
06443 {
06445 template<bool isConstFrom>
06446 static void execute
06447 (
06448 const View<TFrom, isConstFrom, AFrom>& from,
06449 View<TTo, true, ATo>& to
06450 )
06451 {
06452 Assert(MARRAY_NO_ARG_TEST || sizeof(TFrom) == sizeof(TTo));
06453 to.data_ = static_cast<const TTo*>(
06454 static_cast<const void*>(from.data_));
06455 to.geometry_ = from.geometry_;
06456 }
06457 };
06458
06459 template<>
06460 struct AccessOperatorHelper<true>
06461 {
06462
06463 template<class T, class U, bool isConst, class A>
06464 static typename View<T, isConst, A>::reference
06465 execute(const View<T, isConst, A>& v, const U& index)
06466 {
06467 v.testInvariant();
06468 Assert(MARRAY_NO_DEBUG || v.data_ != 0);
06469 Assert(MARRAY_NO_DEBUG || v.dimension() != 0 || index == 0);
06470 size_t offset;
06471 v.indexToOffset(index, offset);
06472 return v.data_[offset];
06473 }
06474 };
06475
06476 template<>
06477 struct AccessOperatorHelper<false>
06478 {
06479
06480 template<class T, class U, bool isConst, class A>
06481 static typename View<T, isConst, A>::reference
06482 execute(const View<T, isConst, A>& v, U it)
06483 {
06484 v.testInvariant();
06485 Assert(MARRAY_NO_DEBUG || v.data_ != 0 );
06486 Assert(MARRAY_NO_DEBUG || v.dimension() != 0 || *it == 0);
06487 size_t offset;
06488 v.coordinatesToOffset(it, offset);
06489 return v.data_[offset];
06490 }
06491 };
06492
06493 template<class Functor, class T, class A>
06494 inline void
06495 operate
06496 (
06497 View<T, false, A>& v,
06498 Functor f
06499 )
06500 {
06501 if(v.isSimple()) {
06502 T* data = &v(0);
06503 for(size_t j=0; j<v.size(); ++j) {
06504 f(data[j]);
06505 }
06506 }
06507 else if(v.dimension() == 1)
06508 OperateHelperUnary<1, Functor, T, A>::operate(v, f, &v(0));
06509 else if(v.dimension() == 2)
06510 OperateHelperUnary<2, Functor, T, A>::operate(v, f, &v(0));
06511 else if(v.dimension() == 3)
06512 OperateHelperUnary<3, Functor, T, A>::operate(v, f, &v(0));
06513 else if(v.dimension() == 4)
06514 OperateHelperUnary<4, Functor, T, A>::operate(v, f, &v(0));
06515 else if(v.dimension() == 5)
06516 OperateHelperUnary<5, Functor, T, A>::operate(v, f, &v(0));
06517 else if(v.dimension() == 6)
06518 OperateHelperUnary<6, Functor, T, A>::operate(v, f, &v(0));
06519 else if(v.dimension() == 7)
06520 OperateHelperUnary<7, Functor, T, A>::operate(v, f, &v(0));
06521 else if(v.dimension() == 8)
06522 OperateHelperUnary<8, Functor, T, A>::operate(v, f, &v(0));
06523 else if(v.dimension() == 9)
06524 OperateHelperUnary<9, Functor, T, A>::operate(v, f, &v(0));
06525 else if(v.dimension() == 10)
06526 OperateHelperUnary<10, Functor, T, A>::operate(v, f, &v(0));
06527 else {
06528 for(typename View<T, false, A>::iterator it = v.begin(); it.hasMore(); ++it) {
06529 f(*it);
06530 }
06531 }
06532 }
06533
06534 template<class Functor, class T, class A>
06535 inline void
06536 operate
06537 (
06538 View<T, false, A>& v,
06539 const T& x,
06540 Functor f
06541 )
06542 {
06543 if(v.isSimple()) {
06544 T* data = &v(0);
06545 for(size_t j=0; j<v.size(); ++j) {
06546 f(data[j], x);
06547 }
06548 }
06549 else if(v.dimension() == 1)
06550 OperateHelperBinaryScalar<1, Functor, T, T, A>::operate(v, x, f, &v(0));
06551 else if(v.dimension() == 2)
06552 OperateHelperBinaryScalar<2, Functor, T, T, A>::operate(v, x, f, &v(0));
06553 else if(v.dimension() == 3)
06554 OperateHelperBinaryScalar<3, Functor, T, T, A>::operate(v, x, f, &v(0));
06555 else if(v.dimension() == 4)
06556 OperateHelperBinaryScalar<4, Functor, T, T, A>::operate(v, x, f, &v(0));
06557 else if(v.dimension() == 5)
06558 OperateHelperBinaryScalar<5, Functor, T, T, A>::operate(v, x, f, &v(0));
06559 else if(v.dimension() == 6)
06560 OperateHelperBinaryScalar<6, Functor, T, T, A>::operate(v, x, f, &v(0));
06561 else if(v.dimension() == 7)
06562 OperateHelperBinaryScalar<7, Functor, T, T, A>::operate(v, x, f, &v(0));
06563 else if(v.dimension() == 8)
06564 OperateHelperBinaryScalar<8, Functor, T, T, A>::operate(v, x, f, &v(0));
06565 else if(v.dimension() == 9)
06566 OperateHelperBinaryScalar<9, Functor, T, T, A>::operate(v, x, f, &v(0));
06567 else if(v.dimension() == 10)
06568 OperateHelperBinaryScalar<10, Functor, T, T, A>::operate(v, x, f, &v(0));
06569 else {
06570 for(typename View<T, false, A>::iterator it = v.begin(); it.hasMore(); ++it) {
06571 f(*it, x);
06572 }
06573 }
06574 }
06575
06576 template<class Functor, class T1, class T2, bool isConst, class A>
06577 inline void
06578 operate
06579 (
06580 View<T1, false, A>& v,
06581 const View<T2, isConst, A>& w,
06582 Functor f
06583 )
06584 {
06585 if(!MARRAY_NO_ARG_TEST) {
06586 Assert(v.size() != 0 && w.size() != 0);
06587 Assert(w.dimension() == 0 || v.dimension() == w.dimension());
06588 if(w.dimension() != 0) {
06589 for(size_t j=0; j<v.dimension(); ++j) {
06590 Assert(v.shape(j) == w.shape(j));
06591 }
06592 }
06593 }
06594 if(w.dimension() == 0) {
06595 T2 x = w(0);
06596 if(v.isSimple()) {
06597 T1* dataV = &v(0);
06598 for(size_t j=0; j<v.size(); ++j) {
06599 f(dataV[j], x);
06600 }
06601 }
06602 else if(v.dimension() == 1)
06603 OperateHelperBinaryScalar<1, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06604 else if(v.dimension() == 2)
06605 OperateHelperBinaryScalar<2, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06606 else if(v.dimension() == 3)
06607 OperateHelperBinaryScalar<3, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06608 else if(v.dimension() == 4)
06609 OperateHelperBinaryScalar<4, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06610 else if(v.dimension() == 5)
06611 OperateHelperBinaryScalar<5, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06612 else if(v.dimension() == 6)
06613 OperateHelperBinaryScalar<6, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06614 else if(v.dimension() == 7)
06615 OperateHelperBinaryScalar<7, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06616 else if(v.dimension() == 8)
06617 OperateHelperBinaryScalar<8, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06618 else if(v.dimension() == 9)
06619 OperateHelperBinaryScalar<9, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06620 else if(v.dimension() == 10)
06621 OperateHelperBinaryScalar<10, Functor, T1, T2, A>::operate(v, x, f, &v(0));
06622 else {
06623 for(typename View<T1, false>::iterator it = v.begin(); it.hasMore(); ++it) {
06624 f(*it, x);
06625 }
06626 }
06627 }
06628 else {
06629 if(v.overlaps(w)) {
06630 Marray<T2> m = w;
06631 operate(v, m, f);
06632 }
06633 else {
06634 if(v.coordinateOrder() == w.coordinateOrder()
06635 && v.isSimple() && w.isSimple()) {
06636 T1* dataV = &v(0);
06637 const T2* dataW = &w(0);
06638 for(size_t j=0; j<v.size(); ++j) {
06639 f(dataV[j], dataW[j]);
06640 }
06641 }
06642 else if(v.dimension() == 1)
06643 OperateHelperBinary<1, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06644 else if(v.dimension() == 2)
06645 OperateHelperBinary<2, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06646 else if(v.dimension() == 3)
06647 OperateHelperBinary<3, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06648 else if(v.dimension() == 4)
06649 OperateHelperBinary<4, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06650 else if(v.dimension() == 5)
06651 OperateHelperBinary<5, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06652 else if(v.dimension() == 6)
06653 OperateHelperBinary<6, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06654 else if(v.dimension() == 7)
06655 OperateHelperBinary<7, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06656 else if(v.dimension() == 8)
06657 OperateHelperBinary<8, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06658 else if(v.dimension() == 9)
06659 OperateHelperBinary<9, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06660 else if(v.dimension() == 10)
06661 OperateHelperBinary<10, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
06662 else {
06663 typename View<T1, false>::iterator itV = v.begin();
06664 typename View<T2, isConst>::const_iterator itW = w.begin();
06665 for(; itV.hasMore(); ++itV, ++itW) {
06666 Assert(MARRAY_NO_DEBUG || itW.hasMore());
06667 f(*itV, *itW);
06668 }
06669 Assert(MARRAY_NO_DEBUG || !itW.hasMore());
06670 }
06671 }
06672 }
06673 }
06674
06675 template<class Functor, class T1, class A, class E, class T2>
06676 inline void operate
06677 (
06678 View<T1, false, A>& v,
06679 const ViewExpression<E, T2>& expression,
06680 Functor f
06681 )
06682 {
06683 const E& e = expression;
06684 if(!MARRAY_NO_DEBUG) {
06685 Assert(v.size() != 0 && e.size() != 0);
06686 Assert(e.dimension() == v.dimension());
06687 if(v.dimension() == 0) {
06688 Assert(v.size() == 1 && e.size() == 1);
06689 }
06690 else {
06691 for(size_t j=0; j<v.dimension(); ++j) {
06692 Assert(v.shape(j) == e.shape(j));
06693 }
06694 }
06695 }
06696 if(e.overlaps(v)) {
06697 Marray<T1, A> m(e);
06698 operate(v, m, f);
06699 }
06700 else if(v.dimension() == 0) {
06701 f(v[0], e[0]);
06702 }
06703 else if(v.isSimple() && e.isSimple()
06704 && v.coordinateOrder() == e.coordinateOrder()) {
06705 for(size_t j=0; j<v.size(); ++j) {
06706 f(v[j], e[j]);
06707 }
06708 }
06709 else {
06710
06711 typename E::ExpressionIterator itE(e);
06712 size_t offsetV = 0;
06713 std::vector<size_t> coordinate(v.dimension());
06714 size_t maxDimension = v.dimension() - 1;
06715 for(;;) {
06716 f(v[offsetV], *itE);
06717 for(size_t j=0; j<v.dimension(); ++j) {
06718 if(coordinate[j]+1 == v.shape(j)) {
06719 if(j == maxDimension) {
06720 return;
06721 }
06722 else {
06723 offsetV -= coordinate[j] * v.strides(j);
06724 itE.resetCoordinate(j);
06725 coordinate[j] = 0;
06726 }
06727 }
06728 else {
06729 offsetV += v.strides(j);
06730 itE.incrementCoordinate(j);
06731 ++coordinate[j];
06732 break;
06733 }
06734 }
06735 }
06736 }
06737 }
06738
06739 }
06740
06741
06742 }
06743
06744 #endif // #ifndef MARRAY_HXX
06745