marray.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef MARRAY_HXX
00003 #define MARRAY_HXX
00004 
00005 #include <cassert>
00006 #include <stdexcept> // runtime_error
00007 #include <limits>
00008 #include <string>
00009 #include <sstream>
00010 #include <cstring> // memcpy
00011 #include <iterator> // reverse_iterator, distance
00012 #include <vector>
00013 #include <set>
00014 #include <iostream> // cout
00015 #include <memory> // allocator
00016 #include <numeric> // accumulate
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 // \cond suppress doxygen
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 // \endcond suppress doxygen
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 // assertion testing
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 // \cond suppress doxygen
00063 namespace marray_detail {
00064     // meta-programming
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     // assertion testing
00109     template<class A> inline void Assert(A assertion) {
00110         if(!assertion) throw std::runtime_error("Assertion failed.");
00111     }
00112 
00113     // geometry of views
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     // operations on entries of views
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     // helper classes
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     // unary in-place functors
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     // binary in-place functors
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     // unary functors
00167     template<class T>
00168         struct Negate { T operator()(const T& x) const { return -x; } };
00169 
00170     // binary functors
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 // \endcond suppress doxygen
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     // construction
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     // assignment
00242     View<T, isConst, A>& operator=(const T&);
00243     View<T, isConst, A>& operator=(const View<T, true, A>&); // over-write default
00244     View<T, isConst, A>& operator=(const View<T, false, A>&); // over-write default
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     // query
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     // element access
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     // sub-views
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     // iterator access
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     // coordinate transformation
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     // conversion between coordinates, index and offset
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     // output as string
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     // unsafe direct memory access
00426     const T& operator[](const size_t) const;
00427     T& operator[](const size_t);
00428 
00429     // data and memory address
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 // \cond suppress doxygen
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 // \endcond end suppress doxygen
00461 };
00462 
00468 template<class T, bool isConst, class A>
00469 class Iterator
00470 {
00471 public:
00472     // STL random access iterator typedefs
00473     typedef typename std::random_access_iterator_tag iterator_category;
00474     typedef T value_type;
00475     //gcc 4.6 bugfix
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     // non-standard typedefs
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     // construction
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         // conversion from mutable to const
00497 
00498     // STL random access iterator operations
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++(); // prefix
00505 
00506     Iterator<T, isConst, A>& operator--(); // prefix
00507     Iterator<T, isConst, A> operator++(int); // postfix
00508     Iterator<T, isConst, A> operator--(int); // postfix
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     // operations beyond the STL standard
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     // attributes
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>; // for comparison operators
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     // constructors and destructor
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     // assignment
00589     Marray<T, A>& operator=(const T&);
00590     Marray<T, A>& operator=(const Marray<T, A>&); // over-write default
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     // resize
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     // hiding inherited functions
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     // constructors and destructor
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     // assignment operator
00663     Vector<T, A>& operator=(const T&);
00664     Vector<T, A>& operator=(const Vector<T, A>&); // over-write default
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     // element access
00671     T& operator[](const size_t);
00672     const T& operator[](const size_t) const;
00673 
00674     // reshape, resize
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     // constructors and destructor
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     // assignment operator
00719     Matrix<T, A>& operator=(const T&);
00720     Matrix<T, A>& operator=(const Matrix<T, A>&); // over-write default
00721         // overwrite standard operator=
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     // resize and reshape
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 // implementation of View
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, // copy to work on
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 { // last major order
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 { // last major order
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 // private constructor
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     // the invariant is not tested as a pre-condition of this
01141     // function to allow for unsafe manipulations prior to its
01142     // call
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     // the invariant is not tested as a pre-condition of this
01175     // function to allow for unsafe manipulations prior to its
01176     // call
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     // update shape, shape strides, strides, and simplicity
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     // transpose shape
02574     c = geometry_.shape(j2);
02575     geometry_.shape(j2) = geometry_.shape(j1);
02576     geometry_.shape(j1) = c;
02577 
02578     // transpose strides
02579     d = geometry_.strides(j2);
02580     geometry_.strides(j2) = geometry_.strides(j1);
02581     geometry_.strides(j1) = d;
02582 
02583     // update shape strides
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         // transpose shape
02605         size_t tmp = geometry_.shape(j);
02606         geometry_.shape(j) = geometry_.shape(k);
02607         geometry_.shape(k) = tmp;
02608 
02609         // transpose strides
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     // no invariant test here because this function
02820     // is called during unsafe updates of a view
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) { // scalar
02874                 marray_detail::Assert(geometry_.size() == 1);
02875             }
02876         }
02877         else {
02878             marray_detail::Assert(data_ != 0);
02879 
02880             // test size_ to be consistent with shape_
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             // test shapeStrides_ to be consistent with shape_
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             // test the simplicity condition
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             // scalar
02970             out << "A = " << (*this)(0) << std::endl;
02971         }
02972         else if(dimension() == 1) {
02973             // vector
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             // matrix
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             // higher dimensional
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             // scalar
03046             out << "A = " << (*this)(0) << std::endl;
03047         }
03048         else {
03049             // non-scalar
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 // implementation of arithmetic operators of View
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 // prefix
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 // postfix
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 // prefix
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 // postfix
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 ) // unary
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 ) // unary
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 // implementation of Marray
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     // adapt geometry
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     // copy data
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) { // no self-assignment
03646         // copy data
03647         if(in.data_ == 0) { // un-initialized
03648             // free
03649             dataAllocator_.deallocate(this->data_, this->size());
03650             this->data_ = 0;
03651         }
03652         else {
03653             if(this->size() != in.size()) {
03654                 // re-alloc
03655                 dataAllocator_.deallocate(this->data_, this->size());
03656                 this->data_ = dataAllocator_.allocate(in.size());
03657             }
03658             // copy data
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) ) { // no self-assignment
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; // temporary copy
03700             (*this) = m;
03701         }
03702         else {
03703             // re-alloc memory if necessary
03704             if(this->size() != in.size()) {
03705                 dataAllocator_.deallocate(this->data_, this->size());
03706                 this->data_ = dataAllocator_.allocate(in.size());
03707             }
03708 
03709             // copy geometry
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             // copy data
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); // temporary copy
03786         (*this) = m; // recursive call
03787     }
03788     else {
03789         // re-allocate memory (if necessary)
03790         if(this->size() != expression.size()) {
03791             dataAllocator_.deallocate(this->data_, this->size());
03792             this->data_ = dataAllocator_.allocate(expression.size());
03793         }
03794 
03795         // copy geometry
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         // copy data
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     // compute size
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     // allocate new
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     // copy old data in region of overlap
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; // copy
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 // iterator implementation
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) { // un-initialized view
03988                 marray_detail::Assert(coordinates_.size() == 0
03989                     && index_ == 0
03990                     && pointer_ == 0);
03991             }
03992             else { // initialized view
03993                 marray_detail::Assert(index_ <= view_->size());
03994                 if(index_ == view_->size()) { // end iterator
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()) { // end iterator
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 { // FirstMajorOrder
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     // Note for developers: If isConst==false, the construction view_(&view)
04057     // fails due to incompatible types. This is intended because it should
04058     // not be possible to construct a mutable iterator on constant data.
04059 {
04060     if(view.size() == 0) { // un-initialized view
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()) { // end iterator
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 { // FirstMajorOrder
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     // Note for developers: If isConst==true, the construction
04110     // view_(reinterpret_cast<view_pointer>(&view)) works as well.
04111     // This is intended because it should be possible to construct
04112     // a constant iterator on mutable data.
04113 {
04114     if(view.size() == 0) { // un-initialized view
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()) { // end iterator
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 { // FirstMajorOrder
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     // Note for developers: If isConst==true, the construction
04164     // view_(reinterpret_cast<view_pointer>(&view)) works as well.
04165     // This is intended because it should be possible to construct
04166     // a constant iterator on mutable data.
04167 {
04168     if(view.size() == 0) { // un-initialized view
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()) { // end iterator
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 { // FirstMajorOrder
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()) { // view initialized and iterator not at the end
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             // set to end iterator
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 { // FirstMajorOrder
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()) { // view initialized and iterator not at the end
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 { // FirstMajorOrder
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                 // set to end iterator
04362                 pointer_ = &((*view_)(view_->size()-1)) + 1;
04363                 if(view_->coordinateOrder() == LastMajorOrder) {
04364                     ++coordinates_[0];
04365                 }
04366                 else { // FirstMajorOrder
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             // decrement from end iterator
04390             --pointer_;
04391             if(view_->coordinateOrder() == LastMajorOrder) {
04392                 --coordinates_[0];
04393             }
04394             else { // FirstMajorOrder
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 { // FirstMajorOrder
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 // Vector implementation
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 // un-initialized
04661         || (in.dimension() == 0 && in.size() == 1) // scalar
04662         || in.dimension() == 1 // vector
04663     );
04664     this->geometry_.size() = in.size();
04665     this->geometry_.coordinateOrder() = in.coordinateOrder();
04666     if(in.data_ != 0) { // in is initialized
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) { // in is a scalar
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 || // empty
04844         (in.dimension() == 0 && in.size() == 1) || // scalar
04845         in.dimension() == 1); // vector
04846     if(in.geometry_.dimension() == 0 && in.geometry_.size() == 1) { // in is a View to a scalar
04847         // copy data
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 // Matrix implementation
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 || // not initialized
05020         (in.dimension() == 0 && in.size() == 1) || // scalar
05021         in.dimension() == 2); // matrix
05022     this->geometry_.size() = in.size();
05023     this->geometry_.coordinateOrder() = in.coordinateOrder();
05024     if(in.data_ != 0) { // 'in' is uninitialized
05025         this->geometry_.resize(2);
05026         if(in.dimension() == 0) { // in is a scalar
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 || // empty
05192         (in.dimension() == 0 && in.size() == 1) || // scalar
05193         in.dimension() == 2);
05194     if(in.dimension() == 0 && in.size() == 1) { // in is a View to a scalar
05195         // copy data
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 // expression templates
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     // \cond suppress doxygen
05363     class ExpressionIterator {
05364     public:
05365         ExpressionIterator(const ViewExpression<E, T>& expression)
05366         : expression_(expression), // cast!
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             { // return expression_[offset_];
05378               // would require making this nested class a friend of View
05379               // which in turn would require a forward declaration of
05380               // this class. work around:
05381               return data_[offset_]; }
05382     private:
05383         const E& expression_;
05384         const T* data_;
05385         size_t offset_;
05386     };
05387     // \endcond suppress doxygen
05388 };
05389 
05390 // \cond suppress doxygen
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), // cast!
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), // cast!
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), // cast!
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), // cast!
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 // \endcond suppress doxygen
05691 
05692 // implementation of marray_detail
05693 
05694 // \cond suppress doxygen
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         // Intended redundancy: shapeStrides_ could be
05754         // computed from shape_ and coordinateOrder_
05755     size_t* strides_;
05756     size_t dimension_;
05757     size_t size_;
05758         // intended redundancy: size_ could be computed from shape_
05759     CoordinateOrder coordinateOrder_;
05760     bool isSimple_;
05761         // simple array: an array which is unstrided (i.e. the strides
05762         // equal the shape strides), cf. the function testInvariant of
05763         // View for the formal definition.
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     for(size_t j=0; j<dimension_; ++j) {
05800         shape_[j] = g.shape_[j];
05801         shapeStrides_[j] = g.shapeStrides_[j];
05802         strides_[j] = g.strides_[j];
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) { // if the array is not a scalar
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) { // no self-assignment
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         for(size_t j=0; j<dimension_; ++j) {
05921             shape_[j] = g.shape_[j];
05922             shapeStrides_[j] = g.shapeStrides_[j];
05923             strides_[j] = g.strides_[j];
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             // save existing entries
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     // a 0-dimensional geometry is simple
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     // from constant to mutable
06316     //
06317     // here, 'to' must be initialized (which is asserted) because
06318     // otherwise, the pointer to.data_ to mutable data would have
06319     // to be initialized with the pointer from.data_ to constant
06320     // data which we don't do.
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; // temporary copy
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)) { // no self-assignment
06387             if(to.data_ == 0) { // if the view 'to' is not initialized
06388                 // initialize the view 'to' with source data
06389                 Assert(MARRAY_NO_ARG_TEST || sizeof(TTo) == sizeof(TFrom));
06390                 to.data_ = static_cast<TTo*>(static_cast<void*>(from.data_)); // copy pointer
06391                 to.geometry_ = from.geometry_;
06392             }
06393             else { // if the view 'to' is initialized
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; // temporary copy
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_)); // copy pointer
06455         to.geometry_ = from.geometry_;
06456     }
06457 };
06458 
06459 template<>
06460 struct AccessOperatorHelper<true>
06461 {
06462     // access by scalar index
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     // access by iterator
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; // temporary copy
06631             operate(v, m, f); // recursive call
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; // cast
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); // temporary copy
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         // loop unrolling does not improve performance here
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 } // namespace marray_detail
06740 // \endcond suppress doxygen
06741 
06742 } // namespace marray
06743 
06744 #endif // #ifndef MARRAY_HXX
06745 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:04 2013 for OpenGM by  doxygen 1.6.3