OpenGM  2.3.x
Discrete Graphical Model Library
marray.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef MARRAY_HXX
3 #define MARRAY_HXX
4 
5 #include <cassert>
6 #include <cstddef>
7 #include <stdexcept> // runtime_error
8 #include <limits>
9 #include <string>
10 #include <sstream>
11 #include <cstring> // memcpy
12 #include <iterator> // reverse_iterator, distance
13 #include <vector>
14 #include <set>
15 #include <iostream> // cout
16 #include <memory> // allocator
17 #include <numeric> // accumulate
18 
20 namespace marray {
21 
25 
26 static const bool Const = true;
27 static const bool Mutable = false;
30 
31 template<class E, class T>
33 // \cond suppress doxygen
34 template<class E, class T, class UnaryFunctor>
35  class UnaryViewExpression;
36 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
37  class BinaryViewExpression;
38 template<class E, class T, class S, class BinaryFunctor>
39  class BinaryViewExpressionScalarFirst;
40 template<class E, class T, class S, class BinaryFunctor>
41  class BinaryViewExpressionScalarSecond;
42 // \endcond suppress doxygen
43 template<class T, bool isConst = false, class A = std::allocator<size_t> >
44  class View;
45 #ifdef HAVE_CPP0X_TEMPLATE_ALIASES
46  template<class T, class A> using ConstView = View<T, true, A>;
47 #endif
48 template<class T, bool isConst, class A = std::allocator<size_t> >
49  class Iterator;
50 template<class T, class A = std::allocator<size_t> > class Vector;
51 template<class T, class A = std::allocator<size_t> > class Matrix;
52 template<class T, class A = std::allocator<size_t> > class Marray;
53 
54 // assertion testing
55 #ifdef NDEBUG
56  const bool MARRAY_NO_DEBUG = true;
57  const bool MARRAY_NO_ARG_TEST = true;
58 #else
59  const bool MARRAY_NO_DEBUG = false;
60  const bool MARRAY_NO_ARG_TEST = false;
61 #endif
62 
63 // \cond suppress doxygen
64 namespace marray_detail {
65  // meta-programming
66  template <bool PREDICATE, class TRUECASE, class FALSECASE>
67  struct IfBool;
68  template <class TRUECASE, class FALSECASE>
69  struct IfBool<true, TRUECASE, FALSECASE>
70  { typedef TRUECASE type; };
71  template <class TRUECASE, class FALSECASE>
72  struct IfBool<false, TRUECASE, FALSECASE>
73  { typedef FALSECASE type; };
74 
75  template <class T1, class T2>
76  struct IsEqual
77  { static const bool type = false; };
78  template <class T>
79  struct IsEqual<T, T>
80  { static const bool type = true; };
81 
82  template<class T> struct TypeTraits
83  { static const unsigned char position = 255; };
84  template<> struct TypeTraits<char>
85  { static const unsigned char position = 0; };
86  template<> struct TypeTraits<unsigned char>
87  { static const unsigned char position = 1; };
88  template<> struct TypeTraits<short>
89  { static const unsigned char position = 2; };
90  template<> struct TypeTraits<unsigned short>
91  { static const unsigned char position = 3; };
92  template<> struct TypeTraits<int>
93  { static const unsigned char position = 4; };
94  template<> struct TypeTraits<unsigned int>
95  { static const unsigned char position = 5; };
96  template<> struct TypeTraits<long>
97  { static const unsigned char position = 6; };
98  template<> struct TypeTraits<unsigned long>
99  { static const unsigned char position = 7; };
100  template<> struct TypeTraits<float>
101  { static const unsigned char position = 8; };
102  template<> struct TypeTraits<double>
103  { static const unsigned char position = 9; };
104  template<> struct TypeTraits<long double>
105  { static const unsigned char position = 10; };
106  template<class A, class B> struct PromoteType
107  { typedef typename IfBool<TypeTraits<A>::position >= TypeTraits<B>::position, A, B>::type type; };
108 
109  // assertion testing
110  template<class A> inline void Assert(A assertion) {
111 #ifdef NDEBUG
112 #else
113  if(!assertion) throw std::runtime_error("Assertion failed.");
114 #endif
115  }
116 
117  // geometry of views
118  template<class A = std::allocator<size_t> > class Geometry;
119  template<class ShapeIterator, class StridesIterator>
120  inline void stridesFromShape(ShapeIterator, ShapeIterator,
121  StridesIterator, const CoordinateOrder& = defaultOrder);
122 
123  // operations on entries of views
124  template<class Functor, class T, class A>
125  inline void operate(View<T, false, A>&, Functor);
126  template<class Functor, class T, class A>
127  inline void operate(View<T, false, A>&, const T&, Functor);
128  template<class Functor, class T1, class T2, bool isConst, class A>
129  inline void operate(View<T1, false, A>&, const View<T2, isConst, A>&, Functor);
130  template<class Functor, class T1, class A, class E, class T2>
131  inline void operate(View<T1, false, A>& v, const ViewExpression<E, T2>& expression, Functor f);
132 
133  // helper classes
134  template<unsigned short N, class Functor, class T, class A>
135  struct OperateHelperUnary;
136  template<unsigned short N, class Functor, class T1, class T2, class A>
137  struct OperateHelperBinaryScalar;
138  template<unsigned short N, class Functor, class T1, class T2,
139  bool isConst, class A1, class A2>
140  struct OperateHelperBinary;
141  template<bool isConstTo, class TFrom, class TTo, class AFrom, class ATo>
142  struct AssignmentOperatorHelper;
143  template<bool isIntegral>
144  struct AccessOperatorHelper;
145 
146  // unary in-place functors
147  template<class T>
148  struct Negative { void operator()(T& x) { x = -x; } };
149  template<class T>
150  struct PrefixIncrement { void operator()(T& x) { ++x; } };
151  template<class T>
152  struct PostfixIncrement { void operator()(T& x) { x++; } };
153  template<class T>
154  struct PrefixDecrement { void operator()(T& x) { --x; } };
155  template<class T>
156  struct PostfixDecrement { void operator()(T& x) { x--; } };
157 
158  // binary in-place functors
159  template<class T1, class T2>
160  struct Assign { void operator()(T1& x, const T2& y) { x = y; } };
161  template<class T1, class T2>
162  struct PlusEqual { void operator()(T1& x, const T2& y) { x += y; } };
163  template<class T1, class T2>
164  struct MinusEqual { void operator()(T1& x, const T2& y) { x -= y; } };
165  template<class T1, class T2>
166  struct TimesEqual { void operator()(T1& x, const T2& y) { x *= y; } };
167  template<class T1, class T2>
168  struct DividedByEqual { void operator()(T1& x, const T2& y) { x /= y; } };
169 
170  // unary functors
171  template<class T>
172  struct Negate { T operator()(const T& x) const { return -x; } };
173 
174  // binary functors
175  template<class T1, class T2, class U>
176  struct Plus { U operator()(const T1& x, const T2& y) const { return x + y; } };
177  template<class T1, class T2, class U>
178  struct Minus { U operator()(const T1& x, const T2& y) const { return x - y; } };
179  template<class T1, class T2, class U>
180  struct Times { U operator()(const T1& x, const T2& y) const { return x * y; } };
181  template<class T1, class T2, class U>
182  struct DividedBy { U operator()(const T1& x, const T2& y) const { return x / y; } };
183 }
184 // \endcond suppress doxygen
185 
204 template<class T, bool isConst, class A>
205 class View
206 : public ViewExpression<View<T, isConst, A>, T>
207 {
208 public:
209  typedef T value_type;
210  typedef T ValueType;
211  typedef typename marray_detail::IfBool<isConst, const T*, T*>::type pointer;
212  typedef const T* const_pointer;
213  typedef typename marray_detail::IfBool<isConst, const T&, T&>::type reference;
214  typedef const T& const_reference;
217  typedef std::reverse_iterator<iterator> reverse_iterator;
218  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
220  typedef typename A::template rebind<value_type>::other allocator_type;
221 
222  // construction
223  View(const allocator_type& = allocator_type());
224  View(pointer, const allocator_type& = allocator_type());
225  View(const View<T, false, A>&);
226  template<class ShapeIterator>
227  View(ShapeIterator, ShapeIterator, pointer,
228  const CoordinateOrder& = defaultOrder,
229  const CoordinateOrder& = defaultOrder,
230  const allocator_type& = allocator_type());
231  template<class ShapeIterator, class StrideIterator>
232  View(ShapeIterator, ShapeIterator, StrideIterator,
233  pointer, const CoordinateOrder&,
234  const allocator_type& = allocator_type());
235  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
236  View(std::initializer_list<size_t>, pointer,
237  const CoordinateOrder& = defaultOrder,
238  const CoordinateOrder& = defaultOrder,
239  const allocator_type& = allocator_type());
240  View(std::initializer_list<size_t>, std::initializer_list<size_t>,
241  pointer, const CoordinateOrder&,
242  const allocator_type& = allocator_type());
243  #endif
244 
245  // assignment
246  View<T, isConst, A>& operator=(const T&);
247  View<T, isConst, A>& operator=(const View<T, true, A>&); // over-write default
248  View<T, isConst, A>& operator=(const View<T, false, A>&); // over-write default
249  template<class TLocal, bool isConstLocal, class ALocal>
251  template<class E, class Te>
254 
255  void assign(const allocator_type& = allocator_type());
256  template<class ShapeIterator>
257  void assign(ShapeIterator, ShapeIterator, pointer,
258  const CoordinateOrder& = defaultOrder,
259  const CoordinateOrder& = defaultOrder,
260  const allocator_type& = allocator_type());
261  template<class ShapeIterator, class StrideIterator>
262  void assign(ShapeIterator, ShapeIterator, StrideIterator,
263  pointer, const CoordinateOrder&,
264  const allocator_type& = allocator_type());
265  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
266  void assign(std::initializer_list<size_t>, pointer,
267  const CoordinateOrder& = defaultOrder,
268  const CoordinateOrder& = defaultOrder,
269  const allocator_type& = allocator_type());
270  void assign(std::initializer_list<size_t>,
271  std::initializer_list<size_t>, pointer,
272  const CoordinateOrder&,
273  const allocator_type& = allocator_type());
274  #endif
275 
276  // query
277  const size_t dimension() const;
278  const size_t size() const;
279  const size_t shape(const size_t) const;
280  const size_t* shapeBegin() const;
281  const size_t* shapeEnd() const;
282  const size_t strides(const size_t) const;
283  const size_t* stridesBegin() const;
284  const size_t* stridesEnd() const;
285  const CoordinateOrder& coordinateOrder() const;
286  const bool isSimple() const;
287  template<class TLocal, bool isConstLocal, class ALocal>
288  bool overlaps(const View<TLocal, isConstLocal, ALocal>&) const;
289 
290  // element access
291  template<class U> reference operator()(U);
292  template<class U> reference operator()(U) const;
293  #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
294  reference operator()(const size_t, const size_t);
295  reference operator()(const size_t, const size_t) const;
296  reference operator()(const size_t, const size_t, const size_t);
297  reference operator()(const size_t, const size_t, const size_t) const;
298  reference operator()(const size_t, const size_t, const size_t,
299  const size_t);
300  reference operator()(const size_t, const size_t, const size_t,
301  const size_t) const;
302  reference operator()(const size_t, const size_t, const size_t,
303  const size_t, const size_t);
304  reference operator()(const size_t, const size_t, const size_t,
305  const size_t, const size_t) const;
306  reference operator()(const size_t, const size_t, const size_t,
307  const size_t, const size_t, const size_t, const size_t,
308  const size_t, const size_t, const size_t);
309  reference operator()(const size_t, const size_t, const size_t,
310  const size_t, const size_t, const size_t, const size_t,
311  const size_t, const size_t, const size_t) const;
312  #else
313  reference operator()(const size_t);
314  reference operator()(const size_t) const;
315  template<typename... Args>
316  reference operator()(const size_t, const Args...);
317  template<typename... Args>
318  reference operator()(const size_t, const Args...) const;
319  private:
320  size_t elementAccessHelper(const size_t, const size_t);
321  size_t elementAccessHelper(const size_t, const size_t) const;
322  template<typename... Args>
323  size_t elementAccessHelper(const size_t, const size_t,
324  const Args...);
325  template<typename... Args>
326  size_t elementAccessHelper(const size_t, const size_t,
327  const Args...) const;
328  public:
329  #endif
330 
331  // sub-views
332  template<class BaseIterator, class ShapeIterator>
333  void view(BaseIterator, ShapeIterator, View<T, isConst, A>&) const;
334  template<class BaseIterator, class ShapeIterator>
335  void view(BaseIterator, ShapeIterator, const CoordinateOrder&,
336  View<T, isConst, A>&) const;
337  template<class BaseIterator, class ShapeIterator>
338  View<T, isConst, A> view(BaseIterator, ShapeIterator) const;
339  template<class BaseIterator, class ShapeIterator>
340  View<T, isConst, A> view(BaseIterator, ShapeIterator,
341  const CoordinateOrder&) const;
342  template<class BaseIterator, class ShapeIterator>
343  void constView(BaseIterator, ShapeIterator, View<T, true, A>&) const;
344  template<class BaseIterator, class ShapeIterator>
345  void constView(BaseIterator, ShapeIterator, const CoordinateOrder&,
346  View<T, true, A>&) const;
347  template<class BaseIterator, class ShapeIterator>
348  View<T, true, A> constView(BaseIterator, ShapeIterator) const;
349  template<class BaseIterator, class ShapeIterator>
350  View<T, true, A> constView(BaseIterator, ShapeIterator,
351  const CoordinateOrder&) const;
352  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
353  void view(std::initializer_list<size_t>,
354  std::initializer_list<size_t>, View<T, isConst, A>&) const;
355  void view(std::initializer_list<size_t>,
356  std::initializer_list<size_t>, const CoordinateOrder&,
357  View<T, isConst, A>&) const;
358  void constView(std::initializer_list<size_t>,
359  std::initializer_list<size_t>, View<T, true, A>&) const;
360  void constView(std::initializer_list<size_t>,
361  std::initializer_list<size_t>, const CoordinateOrder&,
362  View<T, true, A>&) const;
363  #endif
364 
365  // iterator access
366  iterator begin();
367  iterator end();
368  const_iterator begin() const;
369  const_iterator end() const;
370  reverse_iterator rbegin();
371  reverse_iterator rend();
372  const_reverse_iterator rbegin() const;
373  const_reverse_iterator rend() const;
374 
375  // coordinate transformation
376  template<class ShapeIterator>
377  void reshape(ShapeIterator, ShapeIterator);
378  template<class CoordinateIterator>
379  void permute(CoordinateIterator);
380  void transpose(const size_t, const size_t);
381  void transpose();
382  void shift(const int);
383  void squeeze();
384 
385  template<class ShapeIterator>
386  View<T, isConst, A> reshapedView(ShapeIterator, ShapeIterator) const;
387  template<class CoordinateIterator>
388  View<T, isConst, A> permutedView(CoordinateIterator) const;
389  View<T, isConst, A> transposedView(const size_t, const size_t) const;
391  View<T, isConst, A> shiftedView(const int) const;
392  View<T, isConst, A> boundView(const size_t, const size_t = 0) const;
394 
395  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
396  void reshape(std::initializer_list<size_t>);
397  void permute(std::initializer_list<size_t>);
398 
399  View<T, isConst, A> reshapedView(std::initializer_list<size_t>) const;
400  View<T, isConst, A> permutedView(std::initializer_list<size_t>) const;
401  #endif
402 
403  // conversion between coordinates, index and offset
404  template<class CoordinateIterator>
405  void coordinatesToIndex(CoordinateIterator, size_t&) const;
406  template<class CoordinateIterator>
407  void coordinatesToOffset(CoordinateIterator, size_t&) const;
408  template<class CoordinateIterator>
409  void indexToCoordinates(size_t, CoordinateIterator) const;
410  void indexToOffset(size_t, size_t&) const;
411  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
412  void coordinatesToIndex(std::initializer_list<size_t>,
413  size_t&) const;
414  void coordinatesToOffset(std::initializer_list<size_t>,
415  size_t&) const;
416  #endif
417 
418  // output as string
419  std::string asString(const StringStyle& = MatrixStyle) const;
420 
421 private:
422  typedef typename marray_detail::Geometry<A> geometry_type;
423 
424  View(pointer, const geometry_type&);
425 
426  void updateSimplicity();
427  void testInvariant() const;
428 
429  // unsafe direct memory access
430  const T& operator[](const size_t) const;
431  T& operator[](const size_t);
432 
433  // data and memory address
434  pointer data_;
435  geometry_type geometry_;
436 
437 template<class TLocal, bool isConstLocal, class ALocal>
438  friend class View;
439 template<class TLocal, class ALocal>
440  friend class Marray;
441 template<class TLocal, class ALocal>
442  friend class Vector;
443 template<class TLocal, class ALocal>
444  friend class Matrix;
445 // \cond suppress doxygen
446 template<bool isConstTo, class TFrom, class TTo, class AFrom, class ATo>
447  friend struct marray_detail::AssignmentOperatorHelper;
448 friend struct marray_detail::AccessOperatorHelper<true>;
449 friend struct marray_detail::AccessOperatorHelper<false>;
450 
451 template<class E, class U>
452  friend class ViewExpression;
453 template<class E, class U, class UnaryFunctor>
454  friend class UnaryViewExpression;
455 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
456  friend class BinaryViewExpression;
457 template<class E, class U, class S, class BinaryFunctor>
458  friend class BinaryViewExpressionScalarFirst;
459 template<class E, class U, class S, class BinaryFunctor>
460  friend class BinaryViewExpressionScalarSecond;
461 
462 template<class Functor, class T1, class Alocal, class E, class T2>
463  friend void marray_detail::operate(View<T1, false, Alocal>& v, const ViewExpression<E, T2>& expression, Functor f);
464 // \endcond end suppress doxygen
465 };
466 
472 template<class T, bool isConst, class A>
473 class Iterator
474 {
475 public:
476  // STL random access iterator typedefs
477  typedef typename std::random_access_iterator_tag iterator_category;
478  typedef T value_type;
479  typedef std::ptrdiff_t difference_type;
480  typedef typename marray_detail::IfBool<isConst, const T*, T*>::type pointer;
481  typedef typename marray_detail::IfBool<isConst, const T&, T&>::type reference;
482 
483  // non-standard typedefs
484  typedef typename marray_detail::IfBool<isConst, const View<T, true, A>*,
486  typedef typename marray_detail::IfBool<isConst, const View<T, true, A>&,
488 
489  // construction
490  Iterator();
491  Iterator(const View<T, false, A>&, const size_t = 0);
492  Iterator(View<T, false, A>&, const size_t = 0);
493  Iterator(const View<T, true, A>&, const size_t = 0);
495  // conversion from mutable to const
496 
497  // STL random access iterator operations
498  reference operator*() const;
499  pointer operator->() const;
500  reference operator[](const size_t) const;
501  Iterator<T, isConst, A>& operator+=(const difference_type&);
502  Iterator<T, isConst, A>& operator-=(const difference_type&);
503  Iterator<T, isConst, A>& operator++(); // prefix
504 
505  Iterator<T, isConst, A>& operator--(); // prefix
506  Iterator<T, isConst, A> operator++(int); // postfix
507  Iterator<T, isConst, A> operator--(int); // postfix
508  Iterator<T, isConst, A> operator+(const difference_type&) const;
509  Iterator<T, isConst, A> operator-(const difference_type&) const;
510  template<bool isConstLocal>
511  difference_type operator-(const Iterator<T, isConstLocal, A>&) const;
512  template<bool isConstLocal>
513  bool operator==(const Iterator<T, isConstLocal, A>&) const;
514  template<bool isConstLocal>
515  bool operator!=(const Iterator<T, isConstLocal, A>&) const;
516  template<bool isConstLocal>
517  bool operator<(const Iterator<T, isConstLocal, A>&) const;
518  template<bool isConstLocal>
519  bool operator>(const Iterator<T, isConstLocal, A>&) const;
520  template<bool isConstLocal>
521  bool operator<=(const Iterator<T, isConstLocal, A>&) const;
522  template<bool isConstLocal>
523  bool operator>=(const Iterator<T, isConstLocal, A>&) const;
524 
525  // operations beyond the STL standard
526  bool hasMore() const;
527  size_t index() const;
528  template<class CoordinateIterator>
529  void coordinate(CoordinateIterator) const;
530 
531 private:
532  void testInvariant() const;
533 
534  // attributes
535  view_pointer view_;
536  pointer pointer_;
537  size_t index_;
538  std::vector<size_t> coordinates_;
539 
540 friend class Marray<T, A>;
541 friend class Iterator<T, !isConst, A>; // for comparison operators
542 };
543 
545 template<class T, class A>
546 class Marray
547 : public View<T, false, A>
548 {
549 public:
551  typedef typename base::value_type value_type;
552  typedef typename base::pointer pointer;
554  typedef typename base::reference reference;
556  typedef typename base::iterator iterator;
560  typedef typename A::template rebind<value_type>::other allocator_type;
561 
562  // constructors and destructor
563  Marray(const allocator_type& = allocator_type());
564  Marray(const T&, const CoordinateOrder& = defaultOrder,
565  const allocator_type& = allocator_type());
566  template<class ShapeIterator>
567  Marray(ShapeIterator, ShapeIterator, const T& = T(),
568  const CoordinateOrder& = defaultOrder,
569  const allocator_type& = allocator_type());
570  template<class ShapeIterator>
571  Marray(const InitializationSkipping&, ShapeIterator, ShapeIterator,
572  const CoordinateOrder& = defaultOrder,
573  const allocator_type& = allocator_type());
574  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
575  Marray(std::initializer_list<size_t>, const T& = T(),
576  const CoordinateOrder& = defaultOrder,
577  const allocator_type& = allocator_type());
578  #endif
579  Marray(const Marray<T, A>&);
580  template<class E, class Te>
582  const allocator_type& = allocator_type());
583  template<class TLocal, bool isConstLocal, class ALocal>
585  ~Marray();
586 
587  // assignment
588  Marray<T, A>& operator=(const T&);
589  Marray<T, A>& operator=(const Marray<T, A>&); // over-write default
590  template<class TLocal, bool isConstLocal, class ALocal>
592  template<class E, class Te>
594  void assign(const allocator_type& = allocator_type());
595 
596  // resize
597  template<class ShapeIterator>
598  void resize(ShapeIterator, ShapeIterator, const T& = T());
599  template<class ShapeIterator>
600  void resize(const InitializationSkipping&, ShapeIterator, ShapeIterator);
601  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
602  void resize(std::initializer_list<size_t>, const T& = T());
603  void resize(const InitializationSkipping&, std::initializer_list<size_t>);
604  #endif
605 
606 private:
607  typedef typename base::geometry_type geometry_type;
608 
609  // hiding inherited functions
610  template<class CoordinateIterator>
611  void permute(CoordinateIterator) {}
612  void transpose(const size_t, const size_t) {}
613  void transpose() {}
614  void shift(const int) {}
615  void squeeze() {}
616 
617  void testInvariant() const;
618  template<bool SKIP_INITIALIZATION, class ShapeIterator>
619  void resizeHelper(ShapeIterator, ShapeIterator, const T& = T());
620 
621  allocator_type dataAllocator_;
622 
623 friend class Vector<T, A>;
624 friend class Matrix<T, A>;
625 };
626 
628 template<class T, class A>
629 class Vector
630 : public Marray<T, A>
631 {
632 public:
634  typedef typename base::value_type value_type;
635  typedef typename base::pointer pointer;
637  typedef typename base::reference reference;
639  typedef typename base::iterator iterator;
644 
645  // constructors and destructor
646  Vector(const allocator_type& = allocator_type());
647  template<class TLocal, bool isConstLocal, class ALocal>
649  Vector(const size_t, const T& = T(),
650  const allocator_type& = allocator_type());
651  Vector(const InitializationSkipping&, const size_t,
652  const allocator_type& = allocator_type());
653  template<class E, class Te>
655  const allocator_type& = allocator_type());
656  #ifdef HAVE_CPP0X_INITIALIZER_LISTS
657  Vector(std::initializer_list<T> list,
658  const allocator_type& = allocator_type());
659  #endif
660 
661  // assignment operator
662  Vector<T, A>& operator=(const T&);
663  Vector<T, A>& operator=(const Vector<T, A>&); // over-write default
664  template<class TLocal, bool isConstLocal, class ALocal>
666  template<class E, class Te>
668 
669  // element access
670  T& operator[](const size_t);
671  const T& operator[](const size_t) const;
672 
673  // reshape, resize
674  void reshape(const size_t);
675  void resize(const size_t, const T& = T());
676  void resize(const InitializationSkipping&, const size_t);
677 
678 private:
679  void testInvariant() const;
680 };
681 
683 template<class T, class A>
684 class Matrix
685 : public Marray<T, A>
686 {
687 public:
689 
690  typedef typename base::value_type value_type;
691  typedef typename base::pointer pointer;
692 
694  typedef typename base::reference reference;
696  typedef typename base::iterator iterator;
701 
702  // constructors and destructor
703  Matrix(const allocator_type& = allocator_type());
704  template<class TLocal, bool isConstLocal, class ALocal>
706  Matrix(const size_t, const size_t, const T& = T(),
707  const CoordinateOrder& = defaultOrder,
708  const allocator_type& = allocator_type());
710  const size_t, const size_t,
711  const CoordinateOrder& = defaultOrder,
712  const allocator_type& = allocator_type());
713  template<class E, class Te>
715  const allocator_type& = allocator_type());
716 
717  // assignment operator
718  Matrix<T, A>& operator=(const T&);
719  Matrix<T, A>& operator=(const Matrix<T, A>&); // over-write default
720  // overwrite standard operator=
721  template<class TLocal, bool isConstLocal, class ALocal>
723  template<class E, class Te>
725 
726  // resize and reshape
727  void reshape(const size_t, const size_t);
728  void resize(const size_t, const size_t, const T& = T());
729  void resize(const InitializationSkipping&, const size_t, const size_t);
730 
731 private:
732  void testInvariant() const;
733 };
734 
735 // implementation of View
736 
737 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
738 template<class T, bool isConst, class A>
745 inline void
747 (
748  std::initializer_list<size_t> coordinate,
749  size_t& out
750 ) const
751 {
752  coordinatesToIndex(coordinate.begin(), out);
753 }
754 #endif
755 
762 template<class T, bool isConst, class A>
763 template<class CoordinateIterator>
764 inline void
766 (
767  CoordinateIterator it,
768  size_t& out
769 ) const
770 {
771  testInvariant();
772  out = 0;
773  for(size_t j=0; j<this->dimension(); ++j, ++it) {
774  marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<size_t>(*it) < shape(j));
775  out += static_cast<size_t>(*it) * geometry_.shapeStrides(j);
776  }
777 }
778 
779 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
780 template<class T, bool isConst, class A>
787 inline void
789 (
790  std::initializer_list<size_t> coordinate,
791  size_t& out
792 ) const
793 {
794  coordinatesToOffset(coordinate.begin(), out);
795 }
796 #endif
797 
804 template<class T, bool isConst, class A>
805 template<class CoordinateIterator>
806 inline void
808 (
809  CoordinateIterator it,
810  size_t& out
811 ) const
812 {
813  testInvariant();
814  out = 0;
815  for(size_t j=0; j<this->dimension(); ++j, ++it) {
816  marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<size_t>(*it) < shape(j));
817  out += static_cast<size_t>(*it) * strides(j);
818  }
819 }
820 
828 template<class T, bool isConst, class A>
829 template<class CoordinateIterator>
830 inline void
832 (
833  size_t index, // copy to work on
834  CoordinateIterator outit
835 ) const
836 {
837  testInvariant();
838  marray_detail::Assert(MARRAY_NO_DEBUG || this->dimension() > 0);
839  marray_detail::Assert(MARRAY_NO_ARG_TEST || index < this->size());
840  if(coordinateOrder() == FirstMajorOrder) {
841  for(size_t j=0; j<this->dimension(); ++j, ++outit) {
842  *outit = size_t(index / geometry_.shapeStrides(j));
843  index = index % geometry_.shapeStrides(j);
844  }
845  }
846  else { // last major order
847  size_t j = this->dimension()-1;
848  outit += j;
849  for(;;) {
850  *outit = size_t(index / geometry_.shapeStrides(j));
851  index = index % geometry_.shapeStrides(j);
852  if(j == 0) {
853  break;
854  }
855  else {
856  --outit;
857  --j;
858  }
859  }
860  }
861 }
862 
869 template<class T, bool isConst, class A>
870 inline void
872 (
873  size_t index,
874  size_t& out
875 ) const
876 {
877  testInvariant();
878  marray_detail::Assert(MARRAY_NO_ARG_TEST || index < this->size());
879  if(isSimple()) {
880  out = index;
881  }
882  else {
883  out = 0;
884  if(coordinateOrder() == FirstMajorOrder) {
885  for(size_t j=0; j<this->dimension(); ++j) {
886  out += geometry_.strides(j) * (index / geometry_.shapeStrides(j));
887  index = index % geometry_.shapeStrides(j);
888  }
889  }
890  else { // last major order
891  if(this->dimension() == 0) {
892  marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
893  return;
894  }
895  else {
896  size_t j = this->dimension()-1;
897  for(;;) {
898  out += geometry_.strides(j) * (index / geometry_.shapeStrides(j));
899  index = index % geometry_.shapeStrides(j);
900  if(j == 0) {
901  break;
902  }
903  else {
904  --j;
905  }
906  }
907  }
908  }
909  }
910 }
911 
919 template<class T, bool isConst, class A>
920 inline
922 (
923  const allocator_type& allocator
924 )
925 : data_(0),
926  geometry_(geometry_type(allocator))
927 {
928  testInvariant();
929 }
930 
931 // private constructor
932 template<class T, bool isConst, class A>
933 inline
935 (
936  pointer data,
937  const geometry_type& geometry
938 )
939 : data_(data),
940  geometry_(geometry)
941 {
942  testInvariant();
943 }
944 
950 template<class T, bool isConst, class A>
951 inline
953 (
954  pointer data,
955  const allocator_type& allocator
956 )
957 : data_(data),
958  geometry_(geometry_type(0, defaultOrder, 1, true, allocator))
959 {
960  testInvariant();
961 }
962 
967 template<class T, bool isConst, class A>
968 inline
970 (
971  const View<T, false, A>& in
972 )
973 : data_(in.data_),
974  geometry_(in.geometry_)
975 {
976  testInvariant();
977 }
978 
991 
992 template<class T, bool isConst, class A>
993 template<class ShapeIterator>
994 inline
996 (
997  ShapeIterator begin,
998  ShapeIterator end,
999  pointer data,
1000  const CoordinateOrder& externalCoordinateOrder,
1001  const CoordinateOrder& internalCoordinateOrder,
1002  const allocator_type& allocator
1003 )
1004 : data_(data),
1005  geometry_(begin, end, externalCoordinateOrder,
1006  internalCoordinateOrder, allocator)
1007 {
1008  testInvariant();
1009 }
1010 
1023 template<class T, bool isConst, class A>
1024 template<class ShapeIterator, class StrideIterator>
1025 inline
1028  ShapeIterator begin,
1029  ShapeIterator end,
1030  StrideIterator it,
1031  pointer data,
1032  const CoordinateOrder& internalCoordinateOrder,
1033  const allocator_type& allocator
1034 )
1035 : data_(data),
1036  geometry_(begin, end, it, internalCoordinateOrder, allocator)
1037 {
1038  testInvariant();
1039 }
1040 
1041 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
1042 template<class T, bool isConst, class A>
1053 inline
1055 (
1056  std::initializer_list<size_t> shape,
1057  pointer data,
1058  const CoordinateOrder& externalCoordinateOrder,
1059  const CoordinateOrder& internalCoordinateOrder,
1060  const allocator_type& allocator
1061 )
1062 : data_(data),
1063  geometry_(shape.begin(), shape.end(), externalCoordinateOrder,
1064  internalCoordinateOrder, allocator)
1065 {
1066  testInvariant();
1067 }
1068 
1077 template<class T, bool isConst, class A>
1078 inline
1080 (
1081  std::initializer_list<size_t> shape,
1082  std::initializer_list<size_t> strides,
1083  pointer data,
1084  const CoordinateOrder& internalCoordinateOrder,
1085  const allocator_type& allocator
1086 )
1087 : data_(data),
1088  geometry_(shape.begin(), shape.end(), strides.begin(),
1089  internalCoordinateOrder, allocator)
1090 {
1091  testInvariant();
1092 }
1093 #endif
1094 
1102 template<class T, bool isConst, class A>
1103 inline void
1106  const allocator_type& allocator
1107 )
1108 {
1109  geometry_ = geometry_type(allocator);
1110  data_ = 0;
1111  testInvariant();
1112 }
1113 
1126 template<class T, bool isConst, class A>
1127 template<class ShapeIterator>
1128 inline void
1131  ShapeIterator begin,
1132  ShapeIterator end,
1133  pointer data,
1134  const CoordinateOrder& externalCoordinateOrder,
1135  const CoordinateOrder& internalCoordinateOrder,
1136  const allocator_type& allocator
1137 )
1138 {
1139  // the invariant is not tested as a pre-condition of this
1140  // function to allow for unsafe manipulations prior to its
1141  // call
1142  geometry_ = typename marray_detail::Geometry<A>(begin, end,
1143  externalCoordinateOrder, internalCoordinateOrder, allocator);
1144  data_ = data;
1145  testInvariant();
1146 }
1147 
1160 template<class T, bool isConst, class A>
1161 template<class ShapeIterator, class StrideIterator>
1162 inline void
1165  ShapeIterator begin,
1166  ShapeIterator end,
1167  StrideIterator it,
1168  pointer data,
1169  const CoordinateOrder& internalCoordinateOrder,
1170  const allocator_type& allocator
1171 )
1172 {
1173  // the invariant is not tested as a pre-condition of this
1174  // function to allow for unsafe manipulations prior to its
1175  // call
1176  geometry_ = typename marray_detail::Geometry<A>(begin, end,
1177  it, internalCoordinateOrder, allocator);
1178  data_ = data;
1179  testInvariant();
1180 }
1181 
1182 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
1183 template<class T, bool isConst, class A>
1194 inline void
1196 (
1197  std::initializer_list<size_t> shape,
1198  pointer data,
1199  const CoordinateOrder& externalCoordinateOrder,
1200  const CoordinateOrder& internalCoordinateOrder,
1201  const allocator_type& allocator
1202 )
1203 {
1204  assign(shape.begin(), shape.end(), data, externalCoordinateOrder,
1205  internalCoordinateOrder, allocator);
1206 }
1207 
1218 template<class T, bool isConst, class A>
1219 inline void
1221 (
1222  std::initializer_list<size_t> shape,
1223  std::initializer_list<size_t> strides,
1224  pointer data,
1225  const CoordinateOrder& internalCoordinateOrder,
1226  const allocator_type& allocator
1227 )
1228 {
1229  assign(shape.begin(), shape.end(), strides.begin(), data,
1230  internalCoordinateOrder, allocator);
1231 }
1232 #endif
1233 
1241 template<class T, bool isConst, class A>
1242 template<class U>
1243 inline typename View<T, isConst, A>::reference
1244 View<T, isConst, A>::operator()
1246  U u
1247 )
1248 {
1249  return marray_detail::AccessOperatorHelper<std::numeric_limits<U>::is_integer>::execute(*this, u);
1250 }
1251 
1259 template<class T, bool isConst, class A>
1260 template<class U>
1261 inline typename View<T, isConst, A>::reference
1264  U u
1265 ) const
1266 {
1267  return marray_detail::AccessOperatorHelper<std::numeric_limits<U>::is_integer>::execute(*this, u);
1268 }
1269 
1270 #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
1271 
1280 template<class T, bool isConst, class A>
1281 inline typename View<T, isConst, A>::reference
1284  const size_t c0,
1285  const size_t c1
1286 )
1287 {
1288  testInvariant();
1289  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 2));
1290  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)));
1291  return data_[c0*strides(0) + c1*strides(1)];
1292 }
1293 
1302 template<class T, bool isConst, class A>
1303 inline typename View<T, isConst, A>::reference
1306  const size_t c0,
1307  const size_t c1
1308 ) const
1309 {
1310  testInvariant();
1311  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 2));
1312  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)));
1313  return data_[c0*strides(0) + c1*strides(1)];
1314 }
1315 
1325 template<class T, bool isConst, class A>
1326 inline typename View<T, isConst, A>::reference
1329  const size_t c0,
1330  const size_t c1,
1331  const size_t c2
1332 )
1333 {
1334  testInvariant();
1335  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 3));
1336  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1337  && c2 < shape(2)));
1338  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)];
1339 }
1340 
1350 template<class T, bool isConst, class A>
1351 inline typename View<T, isConst, A>::reference
1354  const size_t c0,
1355  const size_t c1,
1356  const size_t c2
1357 ) const
1358 {
1359  testInvariant();
1360  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 3));
1361  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1362  && c2 < shape(2)));
1363  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)];
1364 }
1365 
1376 template<class T, bool isConst, class A>
1377 inline typename View<T, isConst, A>::reference
1380  const size_t c0,
1381  const size_t c1,
1382  const size_t c2,
1383  const size_t c3
1384 )
1385 {
1386  testInvariant();
1387  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 4));
1388  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1389  && c2 < shape(2) && c3 < shape(3)));
1390  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1391  + c3*strides(3)];
1392 }
1393 
1404 template<class T, bool isConst, class A>
1405 inline typename View<T, isConst, A>::reference
1408  const size_t c0,
1409  const size_t c1,
1410  const size_t c2,
1411  const size_t c3
1412 ) const
1413 {
1414  testInvariant();
1415  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 4));
1416  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1417  && c2 < shape(2) && c3 < shape(3)));
1418  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1419  + c3*strides(3)];
1420 }
1421 
1433 template<class T, bool isConst, class A>
1434 inline typename View<T, isConst, A>::reference
1437  const size_t c0,
1438  const size_t c1,
1439  const size_t c2,
1440  const size_t c3,
1441  const size_t c4
1442 )
1443 {
1444  testInvariant();
1445  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 5));
1446  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1447  && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)));
1448  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1449  + c3*strides(3) + c4*strides(4)];
1450 }
1451 
1463 template<class T, bool isConst, class A>
1464 inline typename View<T, isConst, A>::reference
1467  const size_t c0,
1468  const size_t c1,
1469  const size_t c2,
1470  const size_t c3,
1471  const size_t c4
1472 ) const
1473 {
1474  testInvariant();
1475  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 5));
1476  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1477  && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)));
1478  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1479  + c3*strides(3) + c4*strides(4)];
1480 }
1481 
1485 
1499 template<class T, bool isConst, class A>
1500 inline typename View<T, isConst, A>::reference
1503  const size_t c0,
1504  const size_t c1,
1505  const size_t c2,
1506  const size_t c3,
1507  const size_t c4,
1508  const size_t c5,
1509  const size_t c6,
1510  const size_t c7,
1511  const size_t c8,
1512  const size_t c9
1513 )
1514 {
1515  testInvariant();
1516  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 10));
1517  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1518  && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)
1519  && c5 < shape(5) && c6 < shape(6) && c7 < shape(7)
1520  && c8 < shape(8) && c9 < shape(9)));
1521  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1522  + c3*strides(3) + c4*strides(4) + c5*strides(5) + c6*strides(6)
1523  + c7*strides(7) + c8*strides(8) + c9*strides(9)];
1524 }
1525 
1542 template<class T, bool isConst, class A>
1543 inline typename View<T, isConst, A>::reference
1546  const size_t c0,
1547  const size_t c1,
1548  const size_t c2,
1549  const size_t c3,
1550  const size_t c4,
1551  const size_t c5,
1552  const size_t c6,
1553  const size_t c7,
1554  const size_t c8,
1555  const size_t c9
1556 ) const
1557 {
1558  testInvariant();
1559  marray_detail::Assert(MARRAY_NO_DEBUG || (data_ != 0 && dimension() == 10));
1560  marray_detail::Assert(MARRAY_NO_ARG_TEST || (c0 < shape(0) && c1 < shape(1)
1561  && c2 < shape(2) && c3 < shape(3) && c4 < shape(4)
1562  && c5 < shape(5) && c6 < shape(6) && c7 < shape(7)
1563  && c8 < shape(8) && c9 < shape(9)));
1564  return data_[c0*strides(0) + c1*strides(1) + c2*strides(2)
1565  + c3*strides(3) + c4*strides(4) + c5*strides(5) + c6*strides(6)
1566  + c7*strides(7) + c8*strides(8) + c9*strides(9)];
1567 }
1568 
1569 #else
1570 
1571 template<class T, bool isConst, class A>
1572 inline size_t
1574 (
1575  const size_t Dim,
1576  const size_t value
1577 )
1578 {
1579  marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1) ) );
1580  return strides(Dim-1) * value;
1581 }
1582 
1583 template<class T, bool isConst, class A>
1584 inline size_t
1585 View<T, isConst, A>::elementAccessHelper
1586 (
1587  const size_t Dim,
1588  const size_t value
1589 ) const
1590 {
1591  marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1) ) );
1592  return strides(Dim-1) * value;
1593 }
1594 
1595 template<class T, bool isConst, class A>
1596 template<typename... Args>
1597 inline size_t
1598 View<T, isConst, A>::elementAccessHelper
1599 (
1600  const size_t Dim,
1601  const size_t value,
1602  const Args... args
1603 )
1604 {
1605  marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1-sizeof...(args)) ) );
1606  return value * strides(Dim-1-sizeof...(args)) + elementAccessHelper(Dim, args...);
1607 }
1608 
1609 template<class T, bool isConst, class A>
1610 template<typename... Args>
1611 inline size_t
1612 View<T, isConst, A>::elementAccessHelper
1613 (
1614  const size_t Dim,
1615  const size_t value,
1616  const Args... args
1617 ) const
1618 {
1619  marray_detail::Assert(MARRAY_NO_ARG_TEST || (value < shape(Dim-1-sizeof...(args)) ) );
1620  return value * strides(Dim-1-sizeof...(args)) + elementAccessHelper(Dim, args...);
1621 }
1622 
1623 template<class T, bool isConst, class A>
1624 inline typename View<T, isConst, A>::reference
1625 View<T, isConst, A>::operator()
1626 (
1627  const size_t value
1628 )
1629 {
1630  testInvariant();
1631  if(dimension() == 0) {
1632  marray_detail::Assert(MARRAY_NO_ARG_TEST || value == 0);
1633  return data_[0];
1634  }
1635  else {
1636  size_t offset;
1637  indexToOffset(value, offset);
1638  return data_[offset];
1639  }
1640 }
1641 
1642 template<class T, bool isConst, class A>
1643 inline typename View<T, isConst, A>::reference
1644 View<T, isConst, A>::operator()
1645 (
1646  const size_t value
1647 ) const
1648 {
1649  testInvariant();
1650  if(dimension() == 0) {
1651  marray_detail::Assert(MARRAY_NO_ARG_TEST || value == 0);
1652  return data_[0];
1653  }
1654  else {
1655  size_t offset;
1656  indexToOffset(value, offset);
1657  return data_[offset];
1658  }
1659 }
1660 
1661 template<class T, bool isConst, class A>
1662 template<typename... Args>
1663 inline typename View<T, isConst, A>::reference
1664 View<T, isConst, A>::operator()
1665 (
1666  const size_t value,
1667  const Args... args
1668 )
1669 {
1670  testInvariant();
1671  marray_detail::Assert( MARRAY_NO_DEBUG || ( data_ != 0 && sizeof...(args)+1 == dimension() ) );
1672  return data_[strides(0)*value + elementAccessHelper(sizeof...(args)+1, args...) ];
1673 }
1674 
1675 template<class T, bool isConst, class A>
1676 template<typename... Args>
1677 inline typename View<T, isConst, A>::reference
1678 View<T, isConst, A>::operator()
1679 (
1680  const size_t value,
1681  const Args... args
1682 ) const
1683 {
1684  testInvariant();
1685  marray_detail::Assert( MARRAY_NO_DEBUG || ( data_ != 0 && sizeof...(args)+1 == dimension() ) );
1686  return data_[ strides(0) * static_cast<size_t>(value)
1687  + static_cast<size_t>(elementAccessHelper(sizeof...(args)+1, args...)) ];
1688 }
1689 
1690 #endif // #ifndef HAVE_CPP0X_VARIADIC_TEMPLATES
1691 
1696 template<class T, bool isConst, class A>
1697 inline const size_t
1699 {
1700  return geometry_.size();
1701 }
1702 
1709 template<class T, bool isConst, class A>
1710 inline const size_t
1712 {
1713  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
1714  return geometry_.dimension();
1715 }
1716 
1722 template<class T, bool isConst, class A>
1723 inline const size_t
1726  const size_t dimension
1727 ) const
1728 {
1729  testInvariant();
1730  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1731  marray_detail::Assert(MARRAY_NO_ARG_TEST || dimension < this->dimension());
1732  return geometry_.shape(dimension);
1733 }
1734 
1740 template<class T, bool isConst, class A>
1741 inline const size_t*
1743 {
1744  testInvariant();
1745  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1746  return geometry_.shapeBegin();
1747 }
1748 
1754 template<class T, bool isConst, class A>
1755 inline const size_t*
1757 {
1758  testInvariant();
1759  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1760  return geometry_.shapeEnd();
1761 }
1762 
1768 template<class T, bool isConst, class A>
1769 inline const size_t
1772  const size_t dimension
1773 ) const
1774 {
1775  testInvariant();
1776  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1777  marray_detail::Assert(MARRAY_NO_ARG_TEST || dimension < this->dimension());
1778  return geometry_.strides(dimension);
1779 }
1780 
1786 template<class T, bool isConst, class A>
1787 inline const size_t*
1789 {
1790  testInvariant();
1791  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1792  return geometry_.stridesBegin();
1793 }
1794 
1800 template<class T, bool isConst, class A>
1801 inline const size_t*
1803 {
1804  testInvariant();
1805  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1806  return geometry_.stridesEnd();
1807 }
1808 
1813 template<class T, bool isConst, class A>
1814 inline const CoordinateOrder&
1816 {
1817  testInvariant();
1818  return geometry_.coordinateOrder();
1819 }
1820 
1825 template<class T, bool isConst, class A>
1826 inline const bool
1828 {
1829  testInvariant();
1830  return geometry_.isSimple();
1831 }
1832 
1872 template<class T, bool isConst, class A>
1873 inline View<T, isConst, A>&
1876  const View<T, true, A>& in
1877 )
1878 {
1879  testInvariant();
1880  marray_detail::AssignmentOperatorHelper<isConst, T, T, A, A>::execute(in, *this);
1881  testInvariant();
1882  return *this;
1883 }
1884 
1887 template<class T, bool isConst, class A>
1888 inline View<T, isConst, A>&
1889 View<T, isConst, A>::operator=
1891  const View<T, false, A>& in
1892 )
1893 {
1894  testInvariant();
1895  marray_detail::AssignmentOperatorHelper<isConst, T, T, A, A>::execute(in, *this);
1896  testInvariant();
1897  return *this;
1898 }
1899 
1902 template<class T, bool isConst, class A>
1903 template<class TLocal, bool isConstLocal, class ALocal>
1904 inline View<T, isConst, A>&
1905 View<T, isConst, A>::operator=
1908 )
1909 {
1910  testInvariant();
1911  marray_detail::AssignmentOperatorHelper<isConst, TLocal, T, ALocal, A>::execute(in, *this);
1912  testInvariant();
1913  return *this;
1914 }
1915 
1922 template<class T, bool isConst, class A>
1923 inline View<T, isConst, A>&
1924 View<T, isConst, A>::operator=
1926  const T& value
1927 )
1928 {
1929  marray_detail::Assert(MARRAY_NO_DEBUG || data_ != 0);
1930  if(isSimple()) {
1931  for(size_t j=0; j<geometry_.size(); ++j) {
1932  data_[j] = value;
1933  }
1934  }
1935  else if(dimension() == 1)
1936  marray_detail::OperateHelperBinaryScalar<1, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1937  else if(dimension() == 2)
1938  marray_detail::OperateHelperBinaryScalar<2, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1939  else if(dimension() == 3)
1940  marray_detail::OperateHelperBinaryScalar<3, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1941  else if(dimension() == 4)
1942  marray_detail::OperateHelperBinaryScalar<4, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1943  else if(dimension() == 5)
1944  marray_detail::OperateHelperBinaryScalar<5, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1945  else if(dimension() == 6)
1946  marray_detail::OperateHelperBinaryScalar<6, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1947  else if(dimension() == 7)
1948  marray_detail::OperateHelperBinaryScalar<7, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1949  else if(dimension() == 8)
1950  marray_detail::OperateHelperBinaryScalar<8, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1951  else if(dimension() == 9)
1952  marray_detail::OperateHelperBinaryScalar<9, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1953  else if(dimension() == 10)
1954  marray_detail::OperateHelperBinaryScalar<10, marray_detail::Assign<T, T>, T, T, A>::operate(*this, value, marray_detail::Assign<T, T>(), data_);
1955  else {
1956  for(iterator it = begin(); it.hasMore(); ++it) {
1957  *it = value;
1958  }
1959  }
1960  return *this;
1961 }
1962 
1963 template<class T, bool isConst, class A>
1964 template<class E, class Te>
1965 inline View<T, isConst, A>&
1966 View<T, isConst, A>::operator=
1968  const ViewExpression<E, Te>& expression
1969 )
1970 {
1971  marray_detail::operate(*this, expression, marray_detail::Assign<T, Te>());
1972  return *this;
1973 }
1974 
1983 template<class T, bool isConst, class A>
1984 template<class BaseIterator, class ShapeIterator>
1985 inline void
1988  BaseIterator bit,
1989  ShapeIterator sit,
1990  View<T, isConst, A>& out
1991 ) const
1992 {
1993  view(bit, sit, coordinateOrder(), out);
1994 }
1995 
2006 template<class T, bool isConst, class A>
2007 template<class BaseIterator, class ShapeIterator>
2008 inline void
2011  BaseIterator bit,
2012  ShapeIterator sit,
2013  const CoordinateOrder& internalCoordinateOrder,
2014  View<T, isConst, A>& out
2015 ) const
2016 {
2017  testInvariant();
2018  size_t offset = 0;
2019  coordinatesToOffset(bit, offset);
2020  out.assign(sit, sit+dimension(), geometry_.stridesBegin(),
2021  data_+offset, internalCoordinateOrder);
2022 }
2023 
2032 template<class T, bool isConst, class A>
2033 template<class BaseIterator, class ShapeIterator>
2034 inline View<T, isConst, A>
2037  BaseIterator bit,
2038  ShapeIterator sit
2039 ) const
2040 {
2042  this->view(bit, sit, v);
2043  return v;
2044 }
2045 
2056 template<class T, bool isConst, class A>
2057 template<class BaseIterator, class ShapeIterator>
2058 inline View<T, isConst, A>
2061  BaseIterator bit,
2062  ShapeIterator sit,
2063  const CoordinateOrder& internalCoordinateOrder
2064 ) const
2065 {
2067  this->view(bit, sit, internalCoordinateOrder, v);
2068  return v;
2069 }
2070 
2080 template<class T, bool isConst, class A>
2081 template<class BaseIterator, class ShapeIterator>
2082 inline void
2085  BaseIterator bit,
2086  ShapeIterator sit,
2087  View<T, true, A>& out
2088 ) const
2089 {
2090  constView(bit, sit, coordinateOrder(), out);
2091 }
2092 
2103 template<class T, bool isConst, class A>
2104 template<class BaseIterator, class ShapeIterator>
2105 inline void
2108  BaseIterator bit,
2109  ShapeIterator sit,
2110  const CoordinateOrder& internalCoordinateOrder,
2111  View<T, true, A>& out
2112 ) const
2113 {
2114  testInvariant();
2115  size_t offset = 0;
2116  coordinatesToOffset(bit, offset);
2117  out.assign(sit, sit+dimension(),
2118  geometry_.stridesBegin(),
2119  static_cast<const T*>(data_) + offset,
2120  internalCoordinateOrder);
2121 }
2122 
2132 template<class T, bool isConst, class A>
2133 template<class BaseIterator, class ShapeIterator>
2134 inline View<T, true, A>
2137  BaseIterator bit,
2138  ShapeIterator sit
2139 ) const
2140 {
2141  View<T, true, A> v;
2142  this->constView(bit, sit, v);
2143  return v;
2144 }
2145 
2156 template<class T, bool isConst, class A>
2157 template<class BaseIterator, class ShapeIterator>
2158 inline View<T, true, A>
2161  BaseIterator bit,
2162  ShapeIterator sit,
2163  const CoordinateOrder& internalCoordinateOrder
2164 ) const
2165 {
2166  View<T, true, A> v;
2167  this->constView(bit, sit, internalCoordinateOrder, v);
2168  return v;
2169 }
2170 
2171 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
2172 template<class T, bool isConst, class A>
2182 inline void
2184 (
2185  std::initializer_list<size_t> b,
2186  std::initializer_list<size_t> s,
2187  const CoordinateOrder& internalCoordinateOrder,
2188  View<T, isConst, A>& out
2189 ) const
2190 {
2191  view(b.begin(), s.begin(), internalCoordinateOrder, out);
2192 }
2193 
2202 template<class T, bool isConst, class A>
2203 inline void
2205 (
2206  std::initializer_list<size_t> b,
2207  std::initializer_list<size_t> s,
2208  View<T, isConst, A>& out
2209 ) const
2210 {
2211  view(b.begin(), s.begin(), coordinateOrder(), out);
2212 }
2213 
2223 template<class T, bool isConst, class A>
2224 inline void
2226 (
2227  std::initializer_list<size_t> b,
2228  std::initializer_list<size_t> s,
2229  const CoordinateOrder& internalCoordinateOrder,
2230  View<T, true, A>& out
2231 ) const
2232 {
2233  constView(b.begin(), s.begin(), internalCoordinateOrder, out);
2234 }
2235 
2245 template<class T, bool isConst, class A>
2246 inline void
2248 (
2249  std::initializer_list<size_t> b,
2250  std::initializer_list<size_t> s,
2251  View<T, true, A>& out
2252 ) const
2253 {
2254  constView(b.begin(), s.begin(), coordinateOrder(), out);
2255 }
2256 #endif
2257 
2271 template<class T, bool isConst, class A>
2272 template<class ShapeIterator>
2273 inline void
2276  ShapeIterator begin,
2277  ShapeIterator end
2278 )
2279 {
2280  testInvariant();
2281  marray_detail::Assert(MARRAY_NO_DEBUG || isSimple());
2282  if(!MARRAY_NO_ARG_TEST) {
2283  size_t size = std::accumulate(begin, end, 1, std::multiplies<size_t>());
2284  marray_detail::Assert(size == this->size());
2285  }
2286  assign(begin, end, data_, coordinateOrder(), coordinateOrder());
2287  testInvariant();
2288 }
2289 
2303 template<class T, bool isConst, class A>
2304 template<class ShapeIterator>
2305 inline View<T, isConst, A>
2308  ShapeIterator begin,
2309  ShapeIterator end
2310 ) const
2311 {
2312  View<T, isConst, A> out = *this;
2313  out.reshape(begin, end);
2314  return out;
2315 }
2316 
2317 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
2318 template<class T, bool isConst, class A>
2330 inline void
2332 (
2333  std::initializer_list<size_t> shape
2334 )
2335 {
2336  reshape(shape.begin(), shape.end());
2337 }
2338 
2350 template<class T, bool isConst, class A>
2351 inline View<T, isConst, A>
2353 (
2354  std::initializer_list<size_t> shape
2355 ) const
2356 {
2357  return reshapedView(shape.begin(), shape.end());
2358 }
2359 #endif
2360 
2371 template<class T, bool isConst, class A>
2372 View<T, isConst, A>
2375  const size_t dimension,
2376  const size_t value
2377 ) const
2378 {
2379  testInvariant();
2380  marray_detail::Assert(MARRAY_NO_ARG_TEST || (dimension < this->dimension()
2381  && value < shape(dimension)));
2382  if(this->dimension() == 1) {
2383  View v(&((*this)(value)));
2384  v.geometry_.coordinateOrder() = coordinateOrder();
2385  return v;
2386  }
2387  else {
2388  View v;
2389  v.geometry_.resize(this->dimension()-1);
2390  v.geometry_.coordinateOrder() = coordinateOrder();
2391  v.geometry_.size() = size() / shape(dimension);
2392  for(size_t j=0, k=0; j<this->dimension(); ++j) {
2393  if(j != dimension) {
2394  v.geometry_.shape(k) = shape(j);
2395  v.geometry_.strides(k) = strides(j);
2396  ++k;
2397  }
2398  }
2399  marray_detail::stridesFromShape(v.geometry_.shapeBegin(), v.geometry_.shapeEnd(),
2400  v.geometry_.shapeStridesBegin(), v.geometry_.coordinateOrder());
2401  v.data_ = data_ + strides(dimension) * value;
2402  v.updateSimplicity();
2403  v.testInvariant();
2404  return v;
2405  }
2406 }
2407 
2412 template<class T, bool isConst, class A>
2413 void
2415 {
2416  testInvariant();
2417  if(dimension() != 0) {
2418  size_t newDimension = dimension();
2419  for(size_t j=0; j<dimension(); ++j) {
2420  if(shape(j) == 1) {
2421  --newDimension;
2422  }
2423  }
2424  if(newDimension != dimension()) {
2425  if(newDimension == 0) {
2426  geometry_.resize(0);
2427  geometry_.size() = 1;
2428  }
2429  else {
2430  for(size_t j=0, k=0; j<geometry_.dimension(); ++j) {
2431  if(geometry_.shape(j) != 1) {
2432  geometry_.shape(k) = geometry_.shape(j);
2433  geometry_.strides(k) = geometry_.strides(j);
2434  ++k;
2435  }
2436  }
2437  geometry_.resize(newDimension);
2438  marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
2439  geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
2440  updateSimplicity();
2441  }
2442  }
2443  }
2444  testInvariant();
2445 }
2446 
2452 template<class T, bool isConst, class A>
2453 inline View<T, isConst, A>
2455 {
2456  View<T, isConst, A> v = *this;
2457  v.squeeze();
2458  return v;
2459 }
2460 
2461 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
2462 template<class T, bool isConst, class A>
2471 void
2473 (
2474  std::initializer_list<size_t> permutation
2475 )
2476 {
2477  permute(permutation.begin());
2478 }
2479 #endif
2480 
2489 template<class T, bool isConst, class A>
2490 template<class CoordinateIterator>
2491 void
2494  CoordinateIterator begin
2495 )
2496 {
2497  testInvariant();
2498  if(!MARRAY_NO_ARG_TEST) {
2499  marray_detail::Assert(dimension() != 0);
2500  std::set<size_t> s1, s2;
2501  CoordinateIterator it = begin;
2502  for(size_t j=0; j<dimension(); ++j) {
2503  s1.insert(j);
2504  s2.insert(*it);
2505  ++it;
2506  }
2507  marray_detail::Assert(s1 == s2);
2508  }
2509  // update shape, shape strides, strides, and simplicity
2510  std::vector<size_t> newShape = std::vector<size_t>(dimension());
2511  std::vector<size_t> newStrides = std::vector<size_t>(dimension());
2512  for(size_t j=0; j<dimension(); ++j) {
2513  newShape[j] = geometry_.shape(static_cast<size_t>(*begin));
2514  newStrides[j] = geometry_.strides(static_cast<size_t>(*begin));
2515  ++begin;
2516  }
2517  for(size_t j=0; j<dimension(); ++j) {
2518  geometry_.shape(j) = newShape[j];
2519  geometry_.strides(j) = newStrides[j];
2520  }
2521  marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
2522  geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
2523  updateSimplicity();
2524  testInvariant();
2525 }
2526 
2536 template<class T, bool isConst, class A>
2537 template<class CoordinateIterator>
2538 inline View<T, isConst, A>
2541  CoordinateIterator begin
2542 ) const
2543 {
2544  View<T, isConst, A> out = *this;
2545  out.permute(begin);
2546  return out;
2547 }
2548 
2555 template<class T, bool isConst, class A>
2556 void
2559  const size_t c1,
2560  const size_t c2
2561 )
2562 {
2563  testInvariant();
2564  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
2565  (dimension() != 0 && c1 < dimension() && c2 < dimension()));
2566 
2567  size_t j1 = c1;
2568  size_t j2 = c2;
2569  size_t c;
2570  size_t d;
2571 
2572  // transpose shape
2573  c = geometry_.shape(j2);
2574  geometry_.shape(j2) = geometry_.shape(j1);
2575  geometry_.shape(j1) = c;
2576 
2577  // transpose strides
2578  d = geometry_.strides(j2);
2579  geometry_.strides(j2) = geometry_.strides(j1);
2580  geometry_.strides(j1) = d;
2581 
2582  // update shape strides
2583  marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
2584  geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
2585 
2586  updateSimplicity();
2587  testInvariant();
2588 }
2589 
2595 template<class T, bool isConst, class A>
2596 void
2598 {
2599  testInvariant();
2600  for(size_t j=0; j<dimension()/2; ++j) {
2601  size_t k = dimension()-j-1;
2602 
2603  // transpose shape
2604  size_t tmp = geometry_.shape(j);
2605  geometry_.shape(j) = geometry_.shape(k);
2606  geometry_.shape(k) = tmp;
2607 
2608  // transpose strides
2609  tmp = geometry_.strides(j);
2610  geometry_.strides(j) = geometry_.strides(k);
2611  geometry_.strides(k) = tmp;
2612  }
2613  marray_detail::stridesFromShape(geometry_.shapeBegin(), geometry_.shapeEnd(),
2614  geometry_.shapeStridesBegin(), geometry_.coordinateOrder());
2615  updateSimplicity();
2616  testInvariant();
2617 
2618 }
2619 
2628 template<class T, bool isConst, class A>
2629 inline View<T, isConst, A>
2632  const size_t c1,
2633  const size_t c2
2634 ) const
2635 {
2636  View<T, isConst, A> out = *this;
2637  out.transpose(c1, c2);
2638  return out;
2639 }
2640 
2647 template<class T, bool isConst, class A>
2648 inline View<T, isConst, A>
2650 {
2651  View<T, isConst, A> out = *this;
2652  out.transpose();
2653  return out;
2654 }
2655 
2662 template<class T, bool isConst, class A>
2663 inline void
2666  const int n
2667 )
2668 {
2669  testInvariant();
2670  marray_detail::Assert(MARRAY_NO_DEBUG || dimension() != 0);
2671  if(n <= -static_cast<int>(dimension()) || n >= static_cast<int>(dimension())) {
2672  shift(n % static_cast<int>(dimension()));
2673  }
2674  else {
2675  if(n > 0) {
2676  shift(n - static_cast<int>(dimension()));
2677  }
2678  else {
2679  std::vector<size_t> p(dimension());
2680  for(size_t j=0; j<dimension(); ++j) {
2681  p[j] = static_cast<size_t>((static_cast<int>(j) - n)) % dimension();
2682  }
2683  permute(p.begin());
2684  }
2685  }
2686  testInvariant();
2687 }
2688 
2694 template<class T, bool isConst, class A>
2695 inline View<T, isConst, A>
2698  const int n
2699 ) const
2700 {
2701  View<T, isConst, A> out = *this;
2702  out.shift(n);
2703  return out;
2704 }
2705 
2711 
2712 template<class T, bool isConst, class A>
2713 inline typename View<T, isConst, A>::iterator
2715 {
2716  testInvariant();
2717  return Iterator<T, isConst, A>(*this, 0);
2718 }
2719 
2725 template<class T, bool isConst, class A>
2726 inline typename View<T, isConst, A>::iterator
2728 {
2729  testInvariant();
2730  return Iterator<T, isConst, A>(*this, geometry_.size());
2731 }
2732 
2738 template<class T, bool isConst, class A>
2741 {
2742  testInvariant();
2743  return Iterator<T, true>(*this, 0);
2744 }
2745 
2751 template<class T, bool isConst, class A>
2753 
2755 {
2756  testInvariant();
2757  return Iterator<T, true>(*this, geometry_.size());
2758 }
2759 
2765 template<class T, bool isConst, class A>
2768 {
2769  return reverse_iterator(end());
2770 }
2771 
2777 template<class T, bool isConst, class A>
2780 {
2781  return reverse_iterator(begin());
2782 }
2783 
2789 template<class T, bool isConst, class A>
2792 {
2793  return const_reverse_iterator(end());
2794 }
2795 
2801 template<class T, bool isConst, class A>
2804 {
2805  return const_reverse_iterator(begin());
2806 }
2807 
2814 template<class T, bool isConst, class A>
2815 inline void
2817 {
2818  // no invariant test here because this function
2819  // is called during unsafe updates of a view
2820  geometry_.updateSimplicity();
2821 }
2822 
2831 template<class T, bool isConst, class A>
2832 inline const T&
2833 View<T, isConst, A>::operator[]
2834 (
2835  const size_t offset
2836 )
2837 const
2838 {
2839  return data_[offset];
2840 }
2841 
2850 template<class T, bool isConst, class A>
2851 inline T&
2852 View<T, isConst, A>::operator[]
2853 (
2854  const size_t offset
2855 )
2856 {
2857  return data_[offset];
2858 }
2859 
2865 template<class T, bool isConst, class A>
2866 inline void
2867 View<T, isConst, A>::testInvariant() const
2868 {
2869  if(!MARRAY_NO_DEBUG) {
2870  if(geometry_.dimension() == 0) {
2871  marray_detail::Assert(geometry_.isSimple() == true);
2872  if(data_ != 0) { // scalar
2873  marray_detail::Assert(geometry_.size() == 1);
2874  }
2875  }
2876  else {
2877  marray_detail::Assert(data_ != 0);
2878 
2879  // test size_ to be consistent with shape_
2880  size_t testSize = 1;
2881  for(size_t j=0; j<geometry_.dimension(); ++j) {
2882  testSize *= geometry_.shape(j);
2883  }
2884  marray_detail::Assert(geometry_.size() == testSize);
2885 
2886  // test shapeStrides_ to be consistent with shape_
2887  if(geometry_.coordinateOrder() == FirstMajorOrder) {
2888  size_t tmp = 1;
2889  for(size_t j=0; j<geometry_.dimension(); ++j) {
2890  marray_detail::Assert(geometry_.shapeStrides(geometry_.dimension()-j-1) == tmp);
2891  tmp *= geometry_.shape(geometry_.dimension()-j-1);
2892  }
2893  }
2894  else {
2895  size_t tmp = 1;
2896  for(size_t j=0; j<geometry_.dimension(); ++j) {
2897  marray_detail::Assert(geometry_.shapeStrides(j) == tmp);
2898  tmp *= geometry_.shape(j);
2899  }
2900  }
2901 
2902  // test the simplicity condition
2903  if(geometry_.isSimple()) {
2904  for(size_t j=0; j<geometry_.dimension(); ++j) {
2905  marray_detail::Assert(geometry_.strides(j) == geometry_.shapeStrides(j));
2906  }
2907  }
2908  }
2909  }
2910 }
2911 
2927 template<class T, bool isConst, class A>
2928 template<class TLocal, bool isConstLocal, class ALocal>
2932 ) const
2933 {
2934  testInvariant();
2935  if(!MARRAY_NO_ARG_TEST) {
2936  v.testInvariant();
2937  }
2938  if(data_ == 0 || v.data_ == 0) {
2939  return false;
2940  }
2941  else {
2942  const void* dataPointer_ = data_;
2943  const void* vDataPointer_ = v.data_;
2944  const void* maxPointer = & (*this)(this->size()-1);
2945  const void* maxPointerV = & v(v.size()-1);
2946  if( (dataPointer_ <= vDataPointer_ && vDataPointer_ <= maxPointer)
2947  || (vDataPointer_ <= dataPointer_ && dataPointer_ <= maxPointerV) )
2948  {
2949  return true;
2950  }
2951  }
2952  return false;
2953 }
2954 
2957 template<class T, bool isConst, class A>
2958 std::string
2961  const StringStyle& style
2962 ) const
2963 {
2964  testInvariant();
2965  std::ostringstream out(std::ostringstream::out);
2966  if(style == MatrixStyle) {
2967  if(dimension() == 0) {
2968  // scalar
2969  out << "A = " << (*this)(0) << std::endl;
2970  }
2971  else if(dimension() == 1) {
2972  // vector
2973  out << "A = (";
2974  for(size_t j=0; j<this->size(); ++j) {
2975  out << (*this)(j) << ", ";
2976  }
2977  out << "\b\b)" << std::endl;
2978  }
2979  else if(dimension() == 2) {
2980  // matrix
2981  if(coordinateOrder() == FirstMajorOrder) {
2982  out << "A(r,c) =" << std::endl;
2983  for(size_t y=0; y<this->shape(0); ++y) {
2984  for(size_t x=0; x<this->shape(1); ++x) {
2985  out << (*this)(y, x) << ' ';
2986  }
2987  out << std::endl;
2988  }
2989  }
2990  else {
2991  out << "A(c,r) =" << std::endl;
2992  for(size_t y=0; y<this->shape(1); ++y) {
2993  for(size_t x=0; x<this->shape(0); ++x) {
2994  out << (*this)(x, y) << ' ';
2995  }
2996  out << std::endl;
2997  }
2998  }
2999  }
3000  else {
3001  // higher dimensional
3002  std::vector<size_t> c1(dimension());
3003  std::vector<size_t> c2(dimension());
3004  unsigned short q = 2;
3005  if(coordinateOrder() == FirstMajorOrder) {
3006  q = dimension()-3;
3007  }
3008  for(const_iterator it = this->begin(); it.hasMore(); ++it) {
3009  it.coordinate(c2.begin());
3010  if(it.index() == 0 || c2[q] != c1[q]) {
3011  if(it.index() != 0) {
3012  out << std::endl << std::endl;
3013  }
3014  if(coordinateOrder() == FirstMajorOrder) {
3015  out << "A(";
3016  for(size_t j=0; j<dimension()-2; ++j) {
3017  out << c2[j] << ",";
3018  }
3019  }
3020  else {
3021  out << "A(c,r,";
3022  for(size_t j=2; j<dimension(); ++j) {
3023  out << c2[j] << ",";
3024  }
3025  }
3026  out << '\b';
3027  if(coordinateOrder() == FirstMajorOrder) {
3028  out << ",r,c";
3029  }
3030  out << ") =" << std::endl;
3031  }
3032  else if(c2[1] != c1[1]) {
3033  out << std::endl;
3034  }
3035  out << *it << " ";
3036  c1 = c2;
3037  }
3038  out << std::endl;
3039  }
3040  out << std::endl;
3041  }
3042  else if(style == TableStyle) {
3043  if(dimension() == 0) {
3044  // scalar
3045  out << "A = " << (*this)(0) << std::endl;
3046  }
3047  else {
3048  // non-scalar
3049  std::vector<size_t> c(dimension());
3050  for(const_iterator it = this->begin(); it.hasMore(); ++it) {
3051  out << "A(";
3052  it.coordinate(c.begin());
3053  for(size_t j=0; j<c.size(); ++j) {
3054  out << c[j] << ',';
3055  }
3056  out << "\b) = " << *it << std::endl;
3057  }
3058  }
3059  out << std::endl;
3060  }
3061  return out.str();
3062 }
3063 
3064 // implementation of arithmetic operators of View
3065 
3066 template<class T1, class T2, bool isConst, class A>
3067 inline View<T1, false, A>&
3068 operator+=
3070  View<T1, false, A>& v,
3071  const View<T2, isConst, A>& w
3072 )
3073 {
3074  marray_detail::operate(v, w, marray_detail::PlusEqual<T1, T2>());
3075  return v;
3076 }
3077 
3078 // prefix
3079 template<class T, class A>
3080 inline View<T, false, A>&
3081 operator++
3084 )
3085 {
3086  marray_detail::operate(v, marray_detail::PrefixIncrement<T>());
3087  return v;
3088 }
3089 
3090 // postfix
3091 template<class T, class A>
3092 inline Marray<T, A>
3093 operator++
3095  Marray<T, A>& in,
3096  int dummy
3097 )
3098 {
3099  Marray<T, A> out = in;
3100  marray_detail::operate(in, marray_detail::PostfixIncrement<T>());
3101  return out;
3102 }
3103 
3104 template<class T1, class T2, bool isConst, class A>
3105 inline View<T1, false, A>&
3106 operator-=
3108  View<T1, false, A>& v,
3109  const View<T2, isConst, A>& w
3110 )
3111 {
3112  marray_detail::operate(v, w, marray_detail::MinusEqual<T1, T2>());
3113  return v;
3114 }
3115 
3116 // prefix
3117 template<class T, class A>
3118 inline View<T, false, A>&
3119 operator--
3122 )
3123 {
3124  marray_detail::operate(v, marray_detail::PrefixDecrement<T>());
3125  return v;
3126 }
3127 
3128 // postfix
3129 template<class T, class A>
3130 inline Marray<T, A>
3131 operator--
3133  Marray<T, A>& in,
3134  int dummy
3135 )
3136 {
3137  Marray<T, A> out = in;
3138  marray_detail::operate(in, marray_detail::PostfixDecrement<T>());
3139  return out;
3140 }
3141 
3142 template<class T1, class T2, bool isConst, class A>
3143 inline View<T1, false, A>&
3144 operator*=
3146  View<T1, false, A>& v,
3147  const View<T2, isConst, A>& w
3148 )
3149 {
3150  marray_detail::operate(v, w, marray_detail::TimesEqual<T1, T2>());
3151  return v;
3152 }
3153 
3154 template<class T1, class T2, bool isConst, class A>
3155 inline View<T1, false, A>&
3156 operator/=
3158  View<T1, false, A>& v,
3159  const View<T2, isConst, A>& w
3160 )
3161 {
3162  marray_detail::operate(v, w, marray_detail::DividedByEqual<T1, T2>());
3163  return v;
3164 }
3165 
3166 template<class E1, class T1, class E2, class T2>
3167 inline const BinaryViewExpression<E1, T1, E2, T2, marray_detail::Plus<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
3168 operator+
3170  const ViewExpression<E1, T1>& expression1,
3171  const ViewExpression<E2, T2>& expression2
3172 )
3173 {
3174  typedef typename marray_detail::PromoteType<T1, T2>::type promoted_type;
3175  typedef marray_detail::Plus<T1, T2, promoted_type> Functor;
3176  typedef BinaryViewExpression<E1, T1, E2, T2, Functor> return_type;
3177  return return_type(expression1, expression2);
3178 }
3179 
3180 template<class E, class T>
3181 inline const ViewExpression<E,T>&
3182 operator+
3184  const ViewExpression<E,T>& expression
3185 ) // unary
3186 {
3187  return expression;
3188 }
3189 
3190 #define MARRAY_UNARY_OPERATOR(datatype, operation, functorname) \
3191 template<class T, class A> \
3192 inline View<T, false, A>& \
3193 operator operation \
3194 ( \
3195  View<T, false, A>& v, \
3196  const datatype& x \
3197 ) \
3198 { \
3199  marray_detail::operate(v, static_cast<T>(x), marray_detail:: functorname <T, T>()); \
3200  return v; \
3201 } \
3202 
3203 #define MARRAY_UNARY_OPERATOR_ALL_TYPES(op, functorname) \
3204  MARRAY_UNARY_OPERATOR(char, op, functorname) \
3205  MARRAY_UNARY_OPERATOR(unsigned char, op, functorname) \
3206  MARRAY_UNARY_OPERATOR(short, op, functorname) \
3207  MARRAY_UNARY_OPERATOR(unsigned short, op, functorname) \
3208  MARRAY_UNARY_OPERATOR(int, op, functorname) \
3209  MARRAY_UNARY_OPERATOR(unsigned int, op, functorname) \
3210  MARRAY_UNARY_OPERATOR(long, op, functorname) \
3211  MARRAY_UNARY_OPERATOR(unsigned long, op, functorname) \
3212  MARRAY_UNARY_OPERATOR(float, op, functorname) \
3213  MARRAY_UNARY_OPERATOR(double, op, functorname) \
3214  MARRAY_UNARY_OPERATOR(long double, op, functorname) \
3215 
3220 
3221 template<class E1, class T1, class E2, class T2>
3222 inline const BinaryViewExpression<E1, T1, E2, T2,
3223  marray_detail::Minus<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
3224 operator-
3226  const ViewExpression<E1, T1>& expression1,
3227  const ViewExpression<E2, T2>& expression2
3228 )
3229 {
3230  return BinaryViewExpression<E1, T1, E2, T2,
3231  marray_detail::Minus<T1, T2,
3232  typename marray_detail::PromoteType<T1, T2>::type> >(
3233  expression1, expression2);
3234 }
3235 
3236 template<class E, class T>
3237 inline const UnaryViewExpression<E,T,marray_detail::Negate<T> >
3238 operator-
3240  const ViewExpression<E,T>& expression
3241 ) // unary
3242 {
3243  return UnaryViewExpression<E,T,marray_detail::Negate<T> >(
3244  expression);
3245 }
3246 
3247 template<class E1, class T1, class E2, class T2>
3248 inline const BinaryViewExpression<E1, T1, E2, T2,
3249  marray_detail::Times<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
3250 operator*
3252  const ViewExpression<E1, T1>& expression1,
3253  const ViewExpression<E2, T2>& expression2
3254 )
3255 {
3256  return BinaryViewExpression<E1, T1, E2, T2,
3257  marray_detail::Times<T1, T2,
3258  typename marray_detail::PromoteType<T1, T2>::type > >(
3259  expression1, expression2);
3260 }
3261 
3262 template<class E1, class T1, class E2, class T2>
3263 inline const BinaryViewExpression<E1, T1, E2, T2,
3264  marray_detail::DividedBy<T1, T2, typename marray_detail::PromoteType<T1, T2>::type> >
3265 operator/
3267  const ViewExpression<E1, T1>& expression1,
3268  const ViewExpression<E2, T2>& expression2
3269 )
3270 {
3271  return BinaryViewExpression<E1, T1, E2, T2,
3272  marray_detail::DividedBy<T1, T2,
3273  typename marray_detail::PromoteType<T1, T2>::type > >(
3274  expression1, expression2);
3275 }
3276 
3277 #define MARRAY_BINARY_OPERATOR(datatype, operation, functorname) \
3278 template<class E, class T> \
3279 inline const BinaryViewExpressionScalarSecond< \
3280  E, T, datatype, marray_detail:: functorname < \
3281  T, datatype, typename marray_detail::PromoteType<T, datatype>::type \
3282  > \
3283 > \
3284 operator operation \
3285 ( \
3286  const ViewExpression<E, T>& expression, \
3287  const datatype& scalar \
3288 ) \
3289 { \
3290  typedef typename marray_detail::PromoteType<T, datatype>::type \
3291  promoted_type; \
3292  typedef marray_detail:: functorname <T, datatype, promoted_type> Functor; \
3293  typedef BinaryViewExpressionScalarSecond<E, T, datatype, Functor> \
3294  expression_type; \
3295  return expression_type(expression, scalar); \
3296 } \
3297 \
3298 template<class E, class T> \
3299 inline const BinaryViewExpressionScalarFirst \
3300 < \
3301  E, T, datatype, marray_detail:: functorname < \
3302  datatype, T, typename marray_detail::PromoteType<datatype, T>::type \
3303  > \
3304 > \
3305 operator operation \
3306 ( \
3307  const datatype& scalar, \
3308  const ViewExpression<E, T>& expression \
3309 ) \
3310 { \
3311  typedef typename marray_detail::PromoteType<T, datatype>::type \
3312  promoted_type; \
3313  typedef marray_detail:: functorname <datatype, T, promoted_type> Functor; \
3314  typedef BinaryViewExpressionScalarFirst<E, T, datatype, Functor> \
3315  expression_type; \
3316  return expression_type(expression, scalar); \
3317 }
3318 
3319 #define MARRAY_BINARY_OPERATOR_ALL_TYPES(op, functorname) \
3320  MARRAY_BINARY_OPERATOR(char, op, functorname) \
3321  MARRAY_BINARY_OPERATOR(unsigned char, op, functorname) \
3322  MARRAY_BINARY_OPERATOR(short, op, functorname) \
3323  MARRAY_BINARY_OPERATOR(unsigned short, op, functorname) \
3324  MARRAY_BINARY_OPERATOR(int, op, functorname) \
3325  MARRAY_BINARY_OPERATOR(unsigned int, op, functorname) \
3326  MARRAY_BINARY_OPERATOR(long, op, functorname) \
3327  MARRAY_BINARY_OPERATOR(unsigned long, op, functorname) \
3328  MARRAY_BINARY_OPERATOR(float, op, functorname) \
3329  MARRAY_BINARY_OPERATOR(double, op, functorname) \
3330  MARRAY_BINARY_OPERATOR(long double, op, functorname) \
3331 
3336 
3337 // implementation of Marray
3338 
3347 template<class T, class A>
3348 inline void
3349 Marray<T, A>::assign
3351  const allocator_type& allocator
3352 )
3353 {
3354  if(this->data_ != 0) {
3355  dataAllocator_.deallocate(this->data_, this->size());
3356  this->data_ = 0;
3357  }
3358  dataAllocator_ = allocator;
3359  base::assign();
3360 }
3361 
3366 template<class T, class A>
3367 inline
3370  const allocator_type& allocator
3371 )
3372 : base(allocator),
3373  dataAllocator_(allocator)
3374 {
3375  testInvariant();
3376 }
3377 
3387 template<class T, class A>
3388 inline
3391  const T& value,
3392  const CoordinateOrder& coordinateOrder,
3393  const allocator_type& allocator
3394 )
3395 : dataAllocator_(allocator)
3396 {
3397  this->data_ = dataAllocator_.allocate(1);
3398  this->data_[0] = value;
3399  this->geometry_ = geometry_type(0, coordinateOrder, 1, true, allocator);
3400  testInvariant();
3401 }
3402 
3407 template<class T, class A>
3408 inline
3411  const Marray<T, A>& in
3412 )
3413 : dataAllocator_(in.dataAllocator_)
3414 {
3415  if(!MARRAY_NO_ARG_TEST) {
3416  in.testInvariant();
3417  }
3418  if(in.data_ == 0) {
3419  this->data_ = 0;
3420  }
3421  else {
3422  this->data_ = dataAllocator_.allocate(in.size());
3423  memcpy(this->data_, in.data_, (in.size())*sizeof(T));
3424  }
3425  this->geometry_ = in.geometry_;
3426  testInvariant();
3427 }
3428 
3433 template<class T, class A>
3434 template<class TLocal, bool isConstLocal, class ALocal>
3435 inline
3439 )
3440 : dataAllocator_()
3441 {
3442  if(!MARRAY_NO_ARG_TEST) {
3443  in.testInvariant();
3444  }
3445 
3446  // adapt geometry
3447  this->geometry_ = in.geometry_;
3448  for(size_t j=0; j<in.dimension(); ++j) {
3449  this->geometry_.strides(j) = in.geometry_.shapeStrides(j); // !
3450  }
3451  this->geometry_.isSimple() = true;
3452 
3453  // copy data
3454  if(in.size() == 0) {
3455  this->data_ = 0;
3456  }
3457  else {
3458  this->data_ = dataAllocator_.allocate(in.size());
3459  }
3460  if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
3461  memcpy(this->data_, in.data_, (in.size())*sizeof(T));
3462  }
3463  else {
3464  typename View<TLocal, isConstLocal, ALocal>::const_iterator it = in.begin();
3465  for(size_t j=0; j<this->size(); ++j, ++it) {
3466  this->data_[j] = static_cast<T>(*it);
3467  }
3468  }
3469 
3470  testInvariant();
3471 }
3472 
3478 template<class T, class A>
3479 template<class E, class Te>
3480 inline
3483  const ViewExpression<E, Te>& expression,
3484  const allocator_type& allocator
3485 )
3486 : dataAllocator_(allocator)
3487 {
3488  this->data_ = dataAllocator_.allocate(expression.size());
3489  if(expression.dimension() == 0) {
3490  this->geometry_ = geometry_type(0,
3491  static_cast<const E&>(expression).coordinateOrder(),
3492  1, true, dataAllocator_);
3493  }
3494  else {
3495  this->geometry_ = geometry_type(
3496  static_cast<const E&>(expression).shapeBegin(),
3497  static_cast<const E&>(expression).shapeEnd(),
3498  static_cast<const E&>(expression).coordinateOrder(),
3499  static_cast<const E&>(expression).coordinateOrder(),
3500  dataAllocator_);
3501 
3502  }
3503  const E& e = static_cast<const E&>(expression);
3504  if(e.dimension() == 0) {
3505  marray_detail::Assert(MARRAY_NO_ARG_TEST || e.size() < 2);
3506  this->data_[0] = static_cast<T>(e(0));
3507  }
3508  else {
3509  marray_detail::Assert(MARRAY_NO_ARG_TEST || e.size() != 0);
3510  marray_detail::operate(*this, e, marray_detail::Assign<T, Te>());
3511  }
3512  testInvariant();
3513 }
3514 
3525 template<class T, class A>
3526 template<class ShapeIterator>
3527 inline
3530  ShapeIterator begin,
3531  ShapeIterator end,
3532  const T& value,
3533  const CoordinateOrder& coordinateOrder,
3534  const allocator_type& allocator
3535 )
3536 : dataAllocator_(allocator)
3537 {
3538  size_t size = std::accumulate(begin, end, static_cast<size_t>(1), std::multiplies<size_t>());
3539  marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
3540  base::assign(begin, end, dataAllocator_.allocate(size), coordinateOrder,
3541  coordinateOrder, allocator);
3542  for(size_t j=0; j<size; ++j) {
3543  this->data_[j] = value;
3544  }
3545  testInvariant();
3546 }
3547 
3558 template<class T, class A>
3559 template<class ShapeIterator>
3560 inline
3563  const InitializationSkipping& is,
3564  ShapeIterator begin,
3565  ShapeIterator end,
3566  const CoordinateOrder& coordinateOrder,
3567  const allocator_type& allocator
3568 )
3569 : dataAllocator_(allocator)
3570 {
3571  size_t size = std::accumulate(begin, end, 1, std::multiplies<size_t>());
3572  marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
3573  base::assign(begin, end, dataAllocator_.allocate(size), coordinateOrder,
3574  coordinateOrder, allocator);
3575  testInvariant();
3576 }
3577 
3578 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
3579 template<class T, class A>
3588 inline
3590 (
3591  std::initializer_list<size_t> shape,
3592  const T& value,
3593  const CoordinateOrder& coordinateOrder,
3594  const allocator_type& allocator
3595 
3596 )
3597 : dataAllocator_(allocator)
3598 {
3599  size_t size = std::accumulate(shape.begin(), shape.end(),
3600  1, std::multiplies<size_t>());
3601  marray_detail::Assert(MARRAY_NO_ARG_TEST || size != 0);
3602  base::assign(shape.begin(), shape.end(), dataAllocator_.allocate(size),
3603  coordinateOrder, coordinateOrder, allocator);
3604  for(size_t j=0; j<size; ++j) {
3605  this->data_[j] = value;
3606  }
3607  testInvariant();
3608 }
3609 #endif
3610 
3613 template<class T, class A>
3614 inline
3616 {
3617  dataAllocator_.deallocate(this->data_, this->size());
3618 }
3619 
3632 template<class T, class A>
3633 
3634 Marray<T, A>&
3637  const Marray<T, A>& in
3638 )
3639 {
3640  testInvariant();
3641  if(!MARRAY_NO_ARG_TEST) {
3642  in.testInvariant();
3643  }
3644  if(this != &in) { // no self-assignment
3645  // copy data
3646  if(in.data_ == 0) { // un-initialized
3647  // free
3648  dataAllocator_.deallocate(this->data_, this->size());
3649  this->data_ = 0;
3650  }
3651  else {
3652  if(this->size() != in.size()) {
3653  // re-alloc
3654  dataAllocator_.deallocate(this->data_, this->size());
3655  this->data_ = dataAllocator_.allocate(in.size());
3656  }
3657  // copy data
3658  memcpy(this->data_, in.data_, in.size() * sizeof(T));
3659  }
3660  this->geometry_ = in.geometry_;
3661  }
3662  testInvariant();
3663  return *this;
3664 }
3665 
3680 template<class T, class A>
3681 template<class TLocal, bool isConstLocal, class ALocal>
3682 Marray<T, A>&
3683 Marray<T, A>::operator=
3686 )
3687 {
3688  if(!MARRAY_NO_ARG_TEST) {
3689  in.testInvariant();
3690  }
3691  if( (void*)(this) != (void*)(&in) ) { // no self-assignment
3692  if(in.data_ == 0) {
3693  dataAllocator_.deallocate(this->data_, this->size());
3694  this->data_ = 0;
3695  this->geometry_ = in.geometry_;
3696  }
3697  else if(this->overlaps(in)) {
3698  Marray<T, A> m = in; // temporary copy
3699  (*this) = m;
3700  }
3701  else {
3702  // re-alloc memory if necessary
3703  if(this->size() != in.size()) {
3704  dataAllocator_.deallocate(this->data_, this->size());
3705  this->data_ = dataAllocator_.allocate(in.size());
3706  }
3707 
3708  // copy geometry
3709  this->geometry_.resize(in.dimension());
3710  for(size_t j=0; j<in.dimension(); ++j) {
3711  this->geometry_.shape(j) = in.geometry_.shape(j);
3712  this->geometry_.shapeStrides(j) = in.geometry_.shapeStrides(j);
3713  this->geometry_.strides(j) = in.geometry_.shapeStrides(j); // !
3714  }
3715  this->geometry_.size() = in.size();
3716  this->geometry_.isSimple() = true;
3717  this->geometry_.coordinateOrder() = in.coordinateOrder();
3718 
3719  // copy data
3720  if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
3721  memcpy(this->data_, in.data_, (in.size())*sizeof(T));
3722  }
3723  else if(in.dimension() == 1)
3724  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));
3725  else if(in.dimension() == 2)
3726  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));
3727  else if(in.dimension() == 3)
3728  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));
3729  else if(in.dimension() == 4)
3730  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));
3731  else if(in.dimension() == 5)
3732  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));
3733  else if(in.dimension() == 6)
3734  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));
3735  else if(in.dimension() == 7)
3736  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));
3737  else if(in.dimension() == 8)
3738  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));
3739  else if(in.dimension() == 9)
3740  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));
3741  else if(in.dimension() == 10)
3742  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));
3743  else {
3744  typename View<TLocal, isConstLocal, ALocal>::const_iterator it = in.begin();
3745  for(size_t j=0; j<this->size(); ++j, ++it) {
3746  this->data_[j] = static_cast<T>(*it);
3747  }
3748  }
3749  }
3750  }
3751  testInvariant();
3752  return *this;
3753 }
3754 
3761 template<class T, class A>
3762 inline Marray<T, A>&
3763 Marray<T, A>::operator=
3765  const T& value
3766 )
3767 {
3768  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
3769  for(size_t j=0; j<this->size(); ++j) {
3770  this->data_[j] = value;
3771  }
3772  return *this;
3773 }
3774 
3775 template<class T, class A>
3776 template<class E, class Te>
3777 inline Marray<T, A>&
3778 Marray<T, A>::operator=
3780  const ViewExpression<E, Te>& expression
3781 )
3782 {
3783  if(expression.overlaps(*this)) {
3784  Marray<T, A> m(expression); // temporary copy
3785  (*this) = m; // recursive call
3786  }
3787  else {
3788  // re-allocate memory (if necessary)
3789  if(this->size() != expression.size()) {
3790  dataAllocator_.deallocate(this->data_, this->size());
3791  this->data_ = dataAllocator_.allocate(expression.size());
3792  }
3793 
3794  // copy geometry
3795  this->geometry_.resize(expression.dimension());
3796  for(size_t j=0; j<expression.dimension(); ++j) {
3797  this->geometry_.shape(j) = expression.shape(j);
3798  }
3799  this->geometry_.size() = expression.size();
3800  this->geometry_.isSimple() = true;
3801  this->geometry_.coordinateOrder() = expression.coordinateOrder();
3802  if(this->geometry_.dimension() != 0) {
3803  marray_detail::stridesFromShape(this->geometry_.shapeBegin(), this->geometry_.shapeEnd(),
3804  this->geometry_.shapeStridesBegin(), this->geometry_.coordinateOrder());
3805  marray_detail::stridesFromShape(this->geometry_.shapeBegin(), this->geometry_.shapeEnd(),
3806  this->geometry_.stridesBegin(), this->geometry_.coordinateOrder());
3807  }
3808 
3809  // copy data
3810  marray_detail::operate(*this, expression, marray_detail::Assign<T, Te>());
3811  }
3812  return *this;
3813 }
3814 
3815 template<class T, class A>
3816 template<bool SKIP_INITIALIZATION, class ShapeIterator>
3817 inline void
3819 (
3820  ShapeIterator begin,
3821  ShapeIterator end,
3822  const T& value
3823 )
3824 {
3825  testInvariant();
3826  // compute size
3827  std::vector<size_t> newShape;
3828  size_t newSize = 1;
3829  for(ShapeIterator it = begin; it != end; ++it) {
3830  size_t x = static_cast<size_t>(*it);
3831  marray_detail::Assert(MARRAY_NO_ARG_TEST || x > 0);
3832  newShape.push_back(x);
3833  newSize *= x;
3834  }
3835  // allocate new
3836  value_type* newData = dataAllocator_.allocate(newSize);
3837  if(!SKIP_INITIALIZATION) {
3838  for(size_t j=0; j<newSize; ++j) {
3839  newData[j] = value;
3840  }
3841  }
3842  // copy old data in region of overlap
3843  if(this->data_ != 0) {
3844  if(newSize == 1 || this->dimension() == 0) {
3845  newData[0] = this->data_[0];
3846  }
3847  else {
3848  std::vector<size_t> base1(this->dimension());
3849  std::vector<size_t> base2(newShape.size());
3850  std::vector<size_t> shape1(this->dimension(), 1);
3851  std::vector<size_t> shape2(newShape.size(), 1);
3852  for(size_t j=0; j<std::min(this->dimension(), newShape.size()); ++j) {
3853  shape1[j] = std::min(this->shape(j), newShape[j]);
3854  shape2[j] = shape1[j];
3855  }
3856  View<T, true, A> view1;
3857  this->constView(base1.begin(), shape1.begin(), view1);
3858  View<T, false, A> viewT(newShape.begin(), newShape.end(),
3859  newData, this->coordinateOrder(),
3860  this->coordinateOrder());
3861  View<T, false, A> view2;
3862  viewT.view(base2.begin(), shape2.begin(), view2);
3863  view1.squeeze();
3864  view2.squeeze();
3865  view2 = view1; // copy
3866  }
3867  dataAllocator_.deallocate(this->data_, this->size());
3868  this->data_ = 0;
3869  }
3870  base::assign(begin, end, newData, this->geometry_.coordinateOrder(),
3871  this->geometry_.coordinateOrder());
3872  testInvariant();
3873 }
3874 
3882 template<class T, class A>
3883 template<class ShapeIterator>
3884 void
3887  ShapeIterator begin,
3888  ShapeIterator end,
3889  const T& value
3890 )
3891 {
3892  if(std::distance(begin,end)==0) {
3893  if(this->size()>0) {
3894  *this=Marray<T,A>((*this).operator()(0));
3895  }
3896  else{
3897  *this=Marray<T,A>(T());
3898  }
3899 
3900  }
3901  else
3902  {
3903  resizeHelper<false>(begin, end, value);
3904  }
3905 }
3906 
3914 template<class T, class A>
3915 template<class ShapeIterator>
3916 void
3919  const InitializationSkipping& is,
3920  ShapeIterator begin,
3921  ShapeIterator end
3922 )
3923 {
3924  resizeHelper<true>(begin, end);
3925 }
3926 
3927 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
3928 template<class T, class A>
3934 inline void
3936 (
3937  std::initializer_list<size_t> shape,
3938  const T& value
3939 )
3940 {
3941  resizeHelper<false>(shape.begin(), shape.end(), value);
3942 }
3943 
3949 template<class T, class A>
3950 inline void
3952 (
3953  const InitializationSkipping& si,
3954  std::initializer_list<size_t> shape
3955 )
3956 {
3957  resizeHelper<true>(shape.begin(), shape.end());
3958 }
3959 #endif
3960 
3963 template<class T, class A>
3964 inline void
3965 Marray<T, A>::testInvariant() const
3966 {
3967  View<T, false, A>::testInvariant();
3968  marray_detail::Assert(MARRAY_NO_DEBUG || this->geometry_.isSimple());
3969 }
3970 
3971 // iterator implementation
3972 
3975 template<class T, bool isConst, class A>
3976 inline void
3977 Iterator<T, isConst, A>::testInvariant() const
3978 {
3979  if(!MARRAY_NO_DEBUG) {
3980  if(view_ == 0) {
3981  marray_detail::Assert(coordinates_.size() == 0
3982  && index_ == 0
3983  && pointer_ == 0);
3984  }
3985  else {
3986  if(view_->size() == 0) { // un-initialized view
3987  marray_detail::Assert(coordinates_.size() == 0
3988  && index_ == 0
3989  && pointer_ == 0);
3990  }
3991  else { // initialized view
3992  marray_detail::Assert(index_ <= view_->size());
3993  if(index_ == view_->size()) { // end iterator
3994  marray_detail::Assert(pointer_ == &((*view_)(view_->size()-1)) + 1);
3995  }
3996  else {
3997  marray_detail::Assert(pointer_ == &((*view_)(index_)));
3998  }
3999  if(!view_->isSimple()) {
4000  marray_detail::Assert(coordinates_.size() == view_->dimension());
4001  if(index_ == view_->size()) { // end iterator
4002  if(view_->coordinateOrder() == LastMajorOrder) {
4003  marray_detail::Assert(coordinates_[0] == view_->shape(0));
4004  for(size_t j=1; j<coordinates_.size(); ++j) {
4005  marray_detail::Assert(coordinates_[j] == view_->shape(j)-1);
4006  }
4007  }
4008  else { // FirstMajorOrder
4009  size_t d = view_->dimension() - 1;
4010  marray_detail::Assert(coordinates_[d] == view_->shape(d));
4011  for(size_t j=0; j<d; ++j) {
4012  marray_detail::Assert(coordinates_[j] == view_->shape(j)-1);
4013  }
4014  }
4015  }
4016  else {
4017  std::vector<size_t> testCoord(coordinates_.size());
4018  view_->indexToCoordinates(index_, testCoord.begin());
4019  for(size_t j=0; j<coordinates_.size(); ++j) {
4020  marray_detail::Assert(coordinates_[j] == testCoord[j]);
4021  }
4022  }
4023  }
4024  }
4025  }
4026  }
4027 }
4028 
4030 template<class T, bool isConst, class A>
4032 : view_(0),
4033  pointer_(0),
4034  index_(0),
4035  coordinates_(std::vector<size_t>())
4036 {
4037  testInvariant();
4038 }
4039 
4045 template<class T, bool isConst, class A>
4048  const View<T, true, A>& view,
4049  const size_t index
4050 )
4051 : view_(&view),
4052  pointer_(0),
4053  index_(index),
4054  coordinates_(std::vector<size_t>(view.dimension()))
4055  // Note for developers: If isConst==false, the construction view_(&view)
4056  // fails due to incompatible types. This is intended because it should
4057  // not be possible to construct a mutable iterator on constant data.
4058 {
4059  if(view.size() == 0) { // un-initialized view
4060  marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
4061  }
4062  else {
4063  if(view.isSimple()) {
4064  marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
4065  pointer_ = &view(0) + index;
4066  }
4067  else {
4068  if(index >= view.size()) { // end iterator
4069  if(view_->coordinateOrder() == LastMajorOrder) {
4070  coordinates_[0] = view.shape(0);
4071  for(size_t j=1; j<view.dimension(); ++j) {
4072  coordinates_[j] = view.shape(j)-1;
4073  }
4074  }
4075  else { // FirstMajorOrder
4076  size_t d = view_->dimension() - 1;
4077  coordinates_[d] = view.shape(d);
4078  for(size_t j=0; j<d; ++j) {
4079  coordinates_[j] = view.shape(j)-1;
4080  }
4081  }
4082  pointer_ = &view(view.size()-1) + 1;
4083  }
4084  else {
4085  view.indexToCoordinates(index, coordinates_.begin());
4086  pointer_ = &view(index);
4087  }
4088  }
4089  }
4090  testInvariant();
4091 }
4092 
4098 template<class T, bool isConst, class A>
4101  const View<T, false, A>& view,
4102  const size_t index
4103 )
4104 : view_(reinterpret_cast<view_pointer>(&view)),
4105  pointer_(0),
4106  index_(index),
4107  coordinates_(std::vector<size_t>(view.dimension()))
4108  // Note for developers: If isConst==true, the construction
4109  // view_(reinterpret_cast<view_pointer>(&view)) works as well.
4110  // This is intended because it should be possible to construct
4111  // a constant iterator on mutable data.
4112 {
4113  if(view.size() == 0) { // un-initialized view
4114  marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
4115  }
4116  else {
4117  if(view.isSimple()) {
4118  marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
4119  pointer_ = &view(0) + index;
4120  }
4121  else {
4122  if(index >= view.size()) { // end iterator
4123  if(view_->coordinateOrder() == LastMajorOrder) {
4124  coordinates_[0] = view.shape(0);
4125  for(size_t j=1; j<view.dimension(); ++j) {
4126  coordinates_[j] = view.shape(j)-1;
4127  }
4128  }
4129  else { // FirstMajorOrder
4130  size_t d = view_->dimension() - 1;
4131  coordinates_[d] = view.shape(d);
4132  for(size_t j=0; j<d; ++j) {
4133  coordinates_[j] = view.shape(j)-1;
4134  }
4135  }
4136  pointer_ = &view(view.size()-1) + 1;
4137  }
4138  else {
4139  view.indexToCoordinates(index, coordinates_.begin());
4140  pointer_ = &view(index);
4141  }
4142  }
4143  }
4144  testInvariant();
4145 }
4146 
4152 template<class T, bool isConst, class A>
4155  View<T, false, A>& view,
4156  const size_t index
4157 )
4158 : view_(reinterpret_cast<view_pointer>(&view)),
4159  pointer_(0),
4160  index_(index),
4161  coordinates_(std::vector<size_t>(view.dimension()))
4162  // Note for developers: If isConst==true, the construction
4163  // view_(reinterpret_cast<view_pointer>(&view)) works as well.
4164  // This is intended because it should be possible to construct
4165  // a constant iterator on mutable data.
4166 {
4167  if(view.size() == 0) { // un-initialized view
4168  marray_detail::Assert(MARRAY_NO_ARG_TEST || index == 0);
4169  }
4170  else {
4171  if(view.isSimple()) {
4172  marray_detail::Assert(MARRAY_NO_ARG_TEST || index <= view.size());
4173  pointer_ = &view(0) + index;
4174  }
4175  else {
4176  if(index >= view.size()) { // end iterator
4177  if(view_->coordinateOrder() == LastMajorOrder) {
4178  coordinates_[0] = view.shape(0);
4179  for(size_t j=1; j<view.dimension(); ++j) {
4180  coordinates_[j] = view.shape(j)-1;
4181  }
4182  }
4183  else { // FirstMajorOrder
4184  size_t d = view_->dimension() - 1;
4185  coordinates_[d] = view.shape(d);
4186  for(size_t j=0; j<d; ++j) {
4187  coordinates_[j] = view.shape(j)-1;
4188  }
4189  }
4190  pointer_ = &view(view.size()-1) + 1;
4191  }
4192  else {
4193  view.indexToCoordinates(index, coordinates_.begin());
4194  pointer_ = &view(index);
4195  }
4196  }
4197  }
4198  testInvariant();
4199 }
4200 
4203 template<class T, bool isConst, class A>
4206  const Iterator<T, false, A>& in
4207 )
4208 : view_(view_pointer(in.view_)),
4209  pointer_(pointer(in.pointer_)),
4210  index_(in.index_),
4211  coordinates_(in.coordinates_)
4212 {
4213  testInvariant();
4214 }
4215 
4218 template<class T, bool isConst, class A>
4219 inline typename Iterator<T, isConst, A>::reference
4221 {
4222  marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ < view_->size()));
4223  return *pointer_;
4224 }
4225 
4228 template<class T, bool isConst, class A>
4229 inline typename Iterator<T, isConst, A>::pointer
4231 {
4232  marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ < view_->size()));
4233  return pointer_;
4234 }
4235 
4238 template<class T, bool isConst, class A>
4239 inline typename Iterator<T, isConst, A>::reference
4242  const size_t x
4243 ) const
4244 {
4245  marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && x+index_ < view_->size()));
4246  return (*view_)(x+index_);
4247 }
4248 
4249 template<class T, bool isConst, class A>
4253  const difference_type& x
4254 )
4255 {
4256  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4257  if(index_ < view_->size()) { // view initialized and iterator not at the end
4258  if(index_ + x < view_->size()) {
4259  index_ += x;
4260  if(view_->isSimple()) {
4261  pointer_ += x;
4262  }
4263  else {
4264  pointer_ = &((*view_)(index_));
4265  view_->indexToCoordinates(index_, coordinates_.begin());
4266  }
4267  }
4268  else {
4269  // set to end iterator
4270  index_ = view_->size();
4271  if(view_->isSimple()) {
4272  pointer_ = &(*view_)(0) + view_->size();
4273  }
4274  else {
4275  pointer_ = (&(*view_)(view_->size()-1)) + 1;
4276  view_->indexToCoordinates(view_->size()-1, coordinates_.begin());
4277  if(view_->coordinateOrder() == LastMajorOrder) {
4278  ++coordinates_[0];
4279  }
4280  else { // FirstMajorOrder
4281  ++coordinates_[view_->dimension()-1];
4282  }
4283  }
4284  }
4285  }
4286  testInvariant();
4287  return *this;
4288 }
4289 
4290 template<class T, bool isConst, class A>
4292 Iterator<T, isConst, A>::operator-=
4294  const difference_type& x
4295 )
4296 {
4297  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4298  marray_detail::Assert(MARRAY_NO_ARG_TEST || static_cast<difference_type>(index_) >= x);
4299  index_ -= x;
4300  if(view_->isSimple()) {
4301  pointer_ -= x;
4302  }
4303  else {
4304  pointer_ = &((*view_)(index_));
4305  view_->indexToCoordinates(index_, coordinates_.begin());
4306  }
4307  testInvariant();
4308  return *this;
4309 }
4310 
4313 template<class T, bool isConst, class A>
4316 {
4317  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4318  if(index_ < view_->size()) { // view initialized and iterator not at the end
4319  ++index_;
4320  if(view_->isSimple()) {
4321  ++pointer_;
4322  }
4323  else {
4324  if(index_ < view_->size()) {
4325  if(view_->coordinateOrder() == LastMajorOrder) {
4326  for(size_t j=0; j<coordinates_.size(); ++j) {
4327  if(coordinates_[j] == view_->shape(j)-1) {
4328  pointer_ -= view_->strides(j) * coordinates_[j];
4329  coordinates_[j] = 0;
4330  }
4331  else {
4332  pointer_ += view_->strides(j);
4333  ++coordinates_[j];
4334  break;
4335  }
4336  }
4337  }
4338  else { // FirstMajorOrder
4339  size_t j = coordinates_.size() - 1;
4340  for(;;) {
4341  if(coordinates_[j] == view_->shape(j)-1) {
4342  pointer_ -= view_->strides(j) * coordinates_[j];
4343  coordinates_[j] = 0;
4344  }
4345  else {
4346  pointer_ += view_->strides(j);
4347  ++coordinates_[j];
4348  break;
4349  }
4350  if(j == 0) {
4351  break;
4352  }
4353  else {
4354  --j;
4355  }
4356  }
4357  }
4358  }
4359  else {
4360  // set to end iterator
4361  pointer_ = &((*view_)(view_->size()-1)) + 1;
4362  if(view_->coordinateOrder() == LastMajorOrder) {
4363  ++coordinates_[0];
4364  }
4365  else { // FirstMajorOrder
4366  ++coordinates_[view_->dimension()-1];
4367  }
4368  }
4369  }
4370  }
4371  testInvariant();
4372  return *this;
4373 }
4374 
4377 template<class T, bool isConst, class A>
4380 {
4381  marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ > 0));
4382  --index_;
4383  if(view_->isSimple()) {
4384  --pointer_;
4385  }
4386  else {
4387  if(index_ == view_->size()) {
4388  // decrement from end iterator
4389  --pointer_;
4390  if(view_->coordinateOrder() == LastMajorOrder) {
4391  --coordinates_[0];
4392  }
4393  else { // FirstMajorOrder
4394  --coordinates_[view_->dimension() - 1];
4395  }
4396  }
4397  else {
4398  if(view_->coordinateOrder() == LastMajorOrder) {
4399  for(size_t j=0; j<coordinates_.size(); ++j) {
4400  if(coordinates_[j] == 0) {
4401  coordinates_[j] = view_->shape(j)-1;
4402  pointer_ += view_->strides(j) * coordinates_[j];
4403  }
4404  else {
4405  pointer_ -= view_->strides(j);
4406  --coordinates_[j];
4407  break;
4408  }
4409  }
4410  }
4411  else { // FirstMajorOrder
4412  size_t j = view_->dimension() - 1;
4413  for(;;) {
4414  if(coordinates_[j] == 0) {
4415  coordinates_[j] = view_->shape(j)-1;
4416  pointer_ += view_->strides(j) * coordinates_[j];
4417  }
4418  else {
4419  pointer_ -= view_->strides(j);
4420  --coordinates_[j];
4421  break;
4422  }
4423  if(j == 0) {
4424  break;
4425  }
4426  else {
4427  --j;
4428  }
4429  }
4430  }
4431  }
4432  }
4433  testInvariant();
4434  return *this;
4435 }
4436 
4439 template<class T, bool isConst, class A>
4442 {
4443  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4444  Iterator<T, isConst, A> copy = *this;
4445  ++(*this);
4446  return copy;
4447 }
4448 
4451 template<class T, bool isConst, class A>
4454 {
4455  marray_detail::Assert(MARRAY_NO_DEBUG || (view_ != 0 && index_ > 0));
4456  Iterator<T, isConst, A> copy = *this;
4457  --(*this);
4458  return copy;
4459 }
4460 
4461 template<class T, bool isConst, class A>
4463 Iterator<T, isConst, A>::operator+
4465  const difference_type& x
4466 ) const
4467 {
4468  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4469  Iterator<T, isConst, A> tmp = *this;
4470  tmp += x;
4471  return tmp;
4472 }
4473 
4474 template<class T, bool isConst, class A>
4476 Iterator<T, isConst, A>::operator-
4478  const difference_type& x
4479 ) const
4480 {
4481  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4482  Iterator<T, isConst, A> tmp = *this;
4483  tmp -= x;
4484  return tmp;
4485 }
4486 
4487 template<class T, bool isConst, class A>
4488 template<bool isConstLocal>
4490 Iterator<T, isConst, A>::operator-
4493 ) const
4494 {
4495  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4496  marray_detail::Assert(MARRAY_NO_ARG_TEST || it.view_ != 0);
4497  return difference_type(index_)-difference_type(it.index_);
4498 }
4499 
4500 template<class T, bool isConst, class A>
4501 template<bool isConstLocal>
4502 inline bool
4503 Iterator<T, isConst, A>::operator==
4506 ) const
4507 {
4508  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4509  marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && (void*)it.view_ == (void*)view_));
4510  return index_ == it.index_;
4511 }
4512 
4513 template<class T, bool isConst, class A>
4514 template<bool isConstLocal>
4515 inline bool
4516 Iterator<T, isConst, A>::operator!=
4519 ) const
4520 {
4521  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4522  marray_detail::Assert(MARRAY_NO_ARG_TEST || it.view_ != 0);
4523  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
4524  static_cast<const void*>(it.view_) == static_cast<const void*>(view_));
4525  return index_ != it.index_;
4526 }
4527 
4528 template<class T, bool isConst, class A>
4529 template<bool isConstLocal>
4530 inline bool
4531 Iterator<T, isConst, A>::operator<
4534 ) const
4535 {
4536  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4537  marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
4538  return(index_ < it.index_);
4539 }
4540 
4541 template<class T, bool isConst, class A>
4542 template<bool isConstLocal>
4543 inline bool
4544 Iterator<T, isConst, A>::operator>
4547 ) const
4548 {
4549  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4550  marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
4551  return(index_ > it.index_);
4552 }
4553 
4554 template<class T, bool isConst, class A>
4555 template<bool isConstLocal>
4556 inline bool
4557 Iterator<T, isConst, A>::operator<=
4560 ) const
4561 {
4562  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4563  marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
4564  return(index_ <= it.index_);
4565 }
4566 
4567 template<class T, bool isConst, class A>
4568 template<bool isConstLocal>
4569 inline bool
4570 Iterator<T, isConst, A>::operator>=
4573 ) const
4574 {
4575  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4576  marray_detail::Assert(MARRAY_NO_ARG_TEST || (it.view_ != 0 && it.view_ == view_));
4577  return(index_ >= it.index_);
4578 }
4579 
4584 template<class T, bool isConst, class A>
4585 inline bool
4587 {
4588  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4589  return index_ < view_->size();
4590 }
4591 
4596 template<class T, bool isConst, class A>
4597 inline size_t
4599 {
4600  return index_;
4601 }
4602 
4608 template<class T, bool isConst, class A>
4609 template<class CoordinateIterator>
4610 inline void
4613  CoordinateIterator it
4614 ) const
4615 {
4616  marray_detail::Assert(MARRAY_NO_DEBUG || view_ != 0);
4617  marray_detail::Assert(MARRAY_NO_ARG_TEST || index_ < view_->size());
4618  if(view_->isSimple()) {
4619  view_->indexToCoordinates(index_, it);
4620  }
4621  else {
4622  for(size_t j=0; j<coordinates_.size(); ++j, ++it) {
4623  *it = coordinates_[j];
4624  }
4625  }
4626 }
4627 
4628 // Vector implementation
4629 
4634 template<class T, class A>
4635 inline
4638  const allocator_type& allocator
4639 )
4640 : base(allocator)
4641 {
4642  testInvariant();
4643 }
4644 
4649 template<class T, class A>
4650 template<class TLocal, bool isConstLocal, class ALocal>
4651 inline
4655 )
4656 {
4657  in.testInvariant();
4658  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
4659  in.data_ == 0 // un-initialized
4660  || (in.dimension() == 0 && in.size() == 1) // scalar
4661  || in.dimension() == 1 // vector
4662  );
4663  this->geometry_.size() = in.size();
4664  this->geometry_.coordinateOrder() = in.coordinateOrder();
4665  if(in.data_ != 0) { // in is initialized
4666  this->geometry_.resize(1);
4667  this->geometry_.shape(0) = in.size();
4668  this->geometry_.shapeStrides(0) = 1;
4669  this->geometry_.strides(0) = 1;
4670  this->data_ = this->dataAllocator_.allocate(this->size());
4671  if(in.dimension() == 0) { // in is a scalar
4672  this->data_[0] = static_cast<T>(in(0));
4673  }
4674  else {
4675  if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
4676  memcpy(this->data_, in.data_, (this->size())*sizeof(T));
4677  }
4678  else {
4679  for(size_t j=0; j<in.size(); ++j) {
4680  this->data_[j] = static_cast<T>(in(j));
4681  }
4682  }
4683  }
4684  }
4685  testInvariant();
4686 }
4687 
4694 template<class T, class A>
4695 inline
4698  const size_t size,
4699  const T& value,
4700  const allocator_type& allocator
4701 )
4702 : base(allocator)
4703 {
4704  if(size != 0) {
4705  size_t shape[1] = {size};
4706  this->data_ = this->dataAllocator_.allocate(size);
4707  base::base::assign(&shape[0], &shape[1], this->data_);
4708  for(size_t j=0; j<size; ++j) {
4709  this->data_[j] = value;
4710  }
4711  }
4712  testInvariant();
4713 }
4714 
4721 template<class T, class A>
4722 inline
4725  const InitializationSkipping& is,
4726  const size_t size,
4727  const allocator_type& allocator
4728 )
4729 : base(allocator)
4730 {
4731  if(size != 0) {
4732  size_t shape[1] = {size};
4733  this->data_ = this->dataAllocator_.allocate(size);
4734  base::base::assign(&shape[0], &shape[1], this->data_);
4735  }
4736  testInvariant();
4737 }
4738 
4744 template<class T, class A>
4745 template<class E, class Te>
4746 inline
4749  const ViewExpression<E, Te>& expression,
4750  const allocator_type& allocator
4751 )
4752 : base(expression, allocator)
4753 {
4754  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 1);
4755  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
4756  testInvariant();
4757 }
4758 
4759 #ifdef HAVE_CPP0X_INITIALIZER_LISTS
4760 template<class T, class A>
4766 inline
4768 (
4769  std::initializer_list<T> list,
4770  const allocator_type& allocator
4771 )
4772 : base(allocator)
4773 {
4774  if(list.size() != 0) {
4775  size_t shape[1] = {list.size()};
4776  this->data_ = this->dataAllocator_.allocate(list.size());
4777  base::base::assign(&shape[0], &shape[1], this->data_);
4778  int j=0;
4779  for(const T *p = list.begin(); p != list.end(); ++p, ++j) {
4780  this->data_[j] = *p;
4781  }
4782  }
4783  testInvariant();
4784 }
4785 #endif
4786 
4793 template<class T, class A>
4794 inline Vector<T, A>&
4795 Vector<T, A>::operator=
4797  const T& value
4798 )
4799 {
4800  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
4801  for(size_t j=0; j<this->size(); ++j) {
4802  this->data_[j] = value;
4803  }
4804  return *this;
4805 }
4806 
4813 template<class T, class A>
4814 inline Vector<T, A>&
4815 Vector<T, A>::operator=
4817  const Vector<T, A>& in
4818 )
4819 {
4820  in.testInvariant();
4821  base::operator=(in);
4822  testInvariant();
4823  return *this;
4824 }
4825 
4832 template<class T, class A>
4833 template<class TLocal, bool isConstLocal, class ALocal>
4834 inline Vector<T, A>&
4835 Vector<T, A>::operator=
4838 )
4839 {
4840  in.testInvariant();
4841  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
4842  in.data_ == 0 || // empty
4843  (in.dimension() == 0 && in.size() == 1) || // scalar
4844  in.dimension() == 1); // vector
4845  if(in.geometry_.dimension() == 0 && in.geometry_.size() == 1) { // in is a View to a scalar
4846  // copy data
4847  if(this->size() != 1) {
4848  this->dataAllocator_.deallocate(this->data_, this->size());
4849  this->data_ = this->dataAllocator_.allocate(1);
4850  }
4851  this->data_[0] = static_cast<T>(in(0));
4852  this->geometry_.resize(1);
4853  this->geometry_.shape(0) = 1;
4854  this->geometry_.shapeStrides(0) = 1;
4855  this->geometry_.strides(0) = 1;
4856  this->geometry_.size() = 1;
4857  this->geometry_.isSimple() = true;
4858  this->geometry_.coordinateOrder() = in.coordinateOrder();
4859  }
4860  else {
4861  base::operator=(in);
4862  }
4863  testInvariant();
4864  return *this;
4865 }
4866 
4871 template<class T, class A>
4872 template<class E, class Te>
4873 inline Vector<T, A>&
4874 Vector<T, A>::operator=
4876  const ViewExpression<E, Te>& expression
4877 )
4878 {
4879  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 1);
4880  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
4881  base::operator=(expression);
4882  return *this;
4883 }
4884 
4894 template<class T, class A>
4895 inline void
4898  const size_t size
4899 )
4900 {
4901  marray_detail::Assert(size == this->size());
4902 }
4903 
4909 template<class T, class A>
4910 inline void
4913  const size_t size,
4914  const T& value
4915 )
4916 {
4917  if(size == 0) {
4918  base::assign();
4919  }
4920  else {
4921  size_t shape[1] = {size};
4922  base::resize(&shape[0], &shape[1], value);
4923  }
4924  testInvariant();
4925 }
4926 
4932 template<class T, class A>
4933 inline void
4936  const InitializationSkipping& is,
4937  const size_t size
4938 )
4939 {
4940  if(size == 0) {
4941  base::assign();
4942  }
4943  else {
4944  size_t shape[1] = {size};
4945  base::resize(is, &shape[0], &shape[1]);
4946  }
4947  testInvariant();
4948 }
4949 
4952 template<class T, class A>
4953 inline T&
4954 Vector<T, A>::operator[]
4956  const size_t index
4957 )
4958 {
4959  testInvariant();
4960  return this->operator()(index);
4961 }
4962 
4965 template<class T, class A>
4966 inline const T&
4967 Vector<T, A>::operator[]
4969  const size_t index
4970 ) const
4971 {
4972  testInvariant();
4973  return this->operator()(index);
4974 }
4975 
4978 template<class T, class A>
4979 inline void
4981 {
4983  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ == 0 ||
4984  (this->geometry_.isSimple() && this->geometry_.dimension() == 1));
4985 }
4986 
4987 // Matrix implementation
4988 
4993 template<class T, class A>
4994 inline
4997  const allocator_type& allocator
4998 )
4999 : base(allocator)
5000 {
5001  testInvariant();
5002 }
5003 
5008 template<class T, class A>
5009  template<class TLocal, bool isConstLocal, class ALocal>
5010 inline
5014 )
5015 {
5016  in.testInvariant();
5017  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
5018  in.data_ == 0 || // not initialized
5019  (in.dimension() == 0 && in.size() == 1) || // scalar
5020  in.dimension() == 2); // matrix
5021  this->geometry_.size() = in.size();
5022  this->geometry_.coordinateOrder() = in.coordinateOrder();
5023  if(in.data_ != 0) { // 'in' is uninitialized
5024  this->geometry_.resize(2);
5025  if(in.dimension() == 0) { // in is a scalar
5026  this->geometry_.shape(0) = 1;
5027  this->geometry_.shape(1) = 1;
5028  this->geometry_.shapeStrides(0) = 1;
5029  this->geometry_.shapeStrides(1) = 1;
5030  this->geometry_.strides(0) = 1;
5031  this->geometry_.strides(1) = 1;
5032  this->data_ = this->dataAllocator_.allocate(1);
5033  this->data_[0] = static_cast<T>(in(0));
5034  }
5035  else {
5036  this->geometry_.shape(0) = in.shape(0);
5037  this->geometry_.shape(1) = in.shape(1);
5038  this->geometry_.shapeStrides(0) = in.geometry_.shapeStrides(0);
5039  this->geometry_.shapeStrides(1) = in.geometry_.shapeStrides(1);
5040  this->geometry_.strides(0) = in.geometry_.shapeStrides(0); // !
5041  this->geometry_.strides(1) = in.geometry_.shapeStrides(1); // !
5042  this->data_ = this->dataAllocator_.allocate(this->size());
5043  if(in.isSimple() && marray_detail::IsEqual<T, TLocal>::type) {
5044  memcpy(this->data_, in.data_, (this->size())*sizeof(T));
5045  }
5046  else {
5047  for(size_t j=0; j<in.size(); ++j) {
5048  this->data_[j] = static_cast<T>(in(j));
5049  }
5050  }
5051  }
5052  }
5053  testInvariant();
5054 }
5055 
5065 template<class T, class A>
5066 inline
5069  const size_t n1,
5070  const size_t n2,
5071  const T& value,
5072  const CoordinateOrder& coordinateOrder,
5073  const allocator_type& allocator
5074 )
5075 : base(allocator)
5076 {
5077  if(n1 > 0 && n2 > 0) {
5078  size_t shape[2] = {n1, n2};
5079  T* data = this->dataAllocator_.allocate(n1 * n2);
5080  base::base::assign(&shape[0], &shape[2], data,
5081  coordinateOrder, coordinateOrder);
5082  for(size_t j=0; j<this->size(); ++j) {
5083  this->data_[j] = value;
5084  }
5085  }
5086  testInvariant();
5087 }
5088 
5089 
5099 template<class T, class A>
5100 inline
5103  const InitializationSkipping& is,
5104  const size_t n1,
5105  const size_t n2,
5106  const CoordinateOrder& coordinateOrder,
5107  const allocator_type& allocator
5108 )
5109 : base(allocator)
5110 {
5111  if(n1 > 0 && n2 > 0) {
5112  size_t shape[2] = {n1, n2};
5113  this->data_ = this->dataAllocator_.allocate(n1 * n2);
5114  base::base::assign(&shape[0], &shape[2], this->data_,
5115  coordinateOrder, coordinateOrder);
5116  }
5117  testInvariant();
5118 }
5119 
5125 template<class T, class A>
5126 template<class E, class Te>
5127 inline
5130  const ViewExpression<E, Te>& expression,
5131  const allocator_type& allocator
5132 )
5133 : base(expression, allocator)
5134 {
5135  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 2);
5136  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
5137  testInvariant();
5138 }
5139 
5146 template<class T, class A>
5147 inline Matrix<T, A>&
5150  const T& value
5151 )
5152 {
5153  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ != 0);
5154  for(size_t j=0; j<this->size(); ++j) {
5155  this->data_[j] = value;
5156  }
5157  return *this;
5158 }
5159 
5164 template<class T, class A>
5165 inline Matrix<T, A>&
5166 Matrix<T, A>::operator=
5168  const Matrix<T, A>& in
5169 )
5170 {
5171  in.testInvariant();
5172  base::operator=(in);
5173  testInvariant();
5174  return *this;
5175 }
5176 
5181 template<class T, class A>
5182 template<class TLocal, bool isConstLocal, class ALocal>
5183 inline Matrix<T, A>&
5184 Matrix<T, A>::operator=
5187 )
5188 {
5189  marray_detail::Assert(MARRAY_NO_ARG_TEST ||
5190  in.data_ != 0 || // empty
5191  (in.dimension() == 0 && in.size() == 1) || // scalar
5192  in.dimension() == 2);
5193  if(in.dimension() == 0 && in.size() == 1) { // in is a View to a scalar
5194  // copy data
5195  if(this->size() != 1) {
5196  this->dataAllocator_.deallocate(this->data_, this->size());
5197  this->data_ = this->dataAllocator_.allocate(1);
5198  }
5199  this->data_[0] = static_cast<T>(in(0));
5200  this->geometry_.resize(2);
5201  this->geometry_.shape(0) = 1;
5202  this->geometry_.shape(1) = 1;
5203  this->geometry_.shapeStrides(0) = 1;
5204  this->geometry_.shapeStrides(1) = 1;
5205  this->geometry_.strides(0) = 1;
5206  this->geometry_.strides(1) = 1;
5207  this->geometry_.size() = 1;
5208  this->geometry_.isSimple() = true;
5209  this->geometry_.coordinateOrder() = in.coordinateOrder();
5210  }
5211  else {
5212  base::operator=(in);
5213  }
5214  testInvariant();
5215  return *this;
5216 }
5217 
5222 template<class T, class A>
5223 template<class E, class Te>
5224 inline Matrix<T, A>&
5225 Matrix<T, A>::operator=
5227  const ViewExpression<E, Te>& expression
5228 )
5229 {
5230  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.dimension() == 2);
5231  marray_detail::Assert(MARRAY_NO_ARG_TEST || expression.size() > 0);
5232  base::operator=(expression);
5233  return *this;
5234 }
5235 
5242 template<class T, class A>
5243 inline void
5246  const size_t n1,
5247  const size_t n2,
5248  const T& value
5249 )
5250 {
5251  if(n1 == 0 || n2 == 0) {
5252  base::assign();
5253  }
5254  else {
5255  size_t shape[2] = {n1, n2};
5256  base::resize(&shape[0], &shape[2], value);
5257  }
5258  testInvariant();
5259 }
5260 
5267 template<class T, class A>
5268 inline void
5271  const InitializationSkipping& is,
5272  const size_t n1,
5273  const size_t n2
5274 )
5275 {
5276  if(n1 == 0 || n2 == 0) {
5277  base::assign();
5278  }
5279  else {
5280  size_t shape[2] = {n1, n2};
5281  base::resize(is, &shape[0], &shape[2]);
5282  }
5283  testInvariant();
5284 }
5285 
5293 template<class T, class A>
5294 inline void
5297  const size_t n1,
5298  const size_t n2
5299 )
5300 {
5301  marray_detail::Assert(MARRAY_NO_ARG_TEST || (n2 > 0 && n1 > 0));
5302  size_t shape[2] = {n1, n2};
5303  base::reshape(&shape[0], &shape[2]);
5304  testInvariant();
5305 }
5306 
5309 template<class T, class A>
5310 inline void
5312 {
5314  marray_detail::Assert(MARRAY_NO_DEBUG || this->data_ == 0 ||
5315  (this->geometry_.isSimple() && this->geometry_.dimension() == 2));
5316 }
5317 
5318 // expression templates
5319 
5320 template<class E, class T>
5321 class ViewExpression {
5322 public:
5323  typedef E expression_type;
5324  typedef T value_type;
5325 
5326  const size_t dimension() const
5327  { return static_cast<const E&>(*this).dimension(); }
5328  const size_t size() const
5329  { return static_cast<const E&>(*this).size(); }
5330  const size_t shape(const size_t j) const
5331  { return static_cast<const E&>(*this).shape(j); }
5332  const size_t* shapeBegin() const
5333  { return static_cast<const E&>(*this).shapeBegin(); }
5334  const size_t* shapeEnd() const
5335  { return static_cast<const E&>(*this).shapeEnd(); }
5336  template<class Tv, bool isConst, class A>
5337  bool overlaps(const View<Tv, isConst, A>& v) const
5338  { return static_cast<const E&>(*this).overlaps(v); }
5340  { return static_cast<const E&>(*this).coordinateOrder(); }
5341  const bool isSimple() const
5342  { return static_cast<const E&>(*this).isSimple(); }
5343  template<class Accessor>
5344  const T& operator()(Accessor it) const
5345  { return static_cast<const E&>(*this)(it); }
5346  const T& operator()(const size_t c0, const size_t c1) const
5347  { return static_cast<const E&>(*this)(c0, c1); }
5348  const T& operator()(const size_t c0, const size_t c1, const size_t c2) const
5349  { return static_cast<const E&>(*this)(c0, c1, c2); }
5350  const T& operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
5351  { return static_cast<const E&>(*this)(c0, c1, c2, c3); }
5352  const T& operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
5353  { return static_cast<const E&>(*this)(c0, c1, c2, c3, c4); }
5354  const T& operator[](const size_t offset) const
5355  { return static_cast<const E&>(*this)[offset]; }
5356  operator E&()
5357  { return static_cast<E&>(*this); }
5358  operator E const&() const
5359  { return static_cast<const E&>(*this); }
5360 
5361  // \cond suppress doxygen
5362  class ExpressionIterator {
5363  public:
5364  ExpressionIterator(const ViewExpression<E, T>& expression)
5365  : expression_(expression), // cast!
5366  data_(&expression_(0)),
5367  offset_(0)
5368  {}
5369  void incrementCoordinate(const size_t coordinateIndex)
5370  { offset_ += expression_.strides(coordinateIndex); }
5371  void resetCoordinate(const size_t coordinateIndex)
5372  { offset_ -= expression_.strides(coordinateIndex)
5373 
5374  * (expression_.shape(coordinateIndex) - 1); }
5375  const T& operator*() const
5376  { // return expression_[offset_];
5377  // would require making this nested class a friend of View
5378  // which in turn would require a forward declaration of
5379  // this class. work around:
5380  return data_[offset_]; }
5381  private:
5382  const E& expression_;
5383  const T* data_;
5384  size_t offset_;
5385  };
5386  // \endcond suppress doxygen
5387 };
5388 
5389 // \cond suppress doxygen
5390 template<class E, class T, class UnaryFunctor>
5391 class UnaryViewExpression
5392 : public ViewExpression<UnaryViewExpression<E, T, UnaryFunctor>, T>
5393 {
5394 public:
5395  typedef E expression_type;
5396  typedef T value_type;
5397 
5398  UnaryViewExpression(const ViewExpression<E, T>& e)
5399  : e_(e), // cast!
5400  unaryFunctor_(UnaryFunctor())
5401  {}
5402  const size_t dimension() const
5403  { return e_.dimension(); }
5404  const size_t size() const
5405  { return e_.size(); }
5406  const size_t shape(const size_t j) const
5407  { return e_.shape(j); }
5408  const size_t* shapeBegin() const
5409  { return e_.shapeBegin(); }
5410  const size_t* shapeEnd() const
5411  { return e_.shapeEnd(); }
5412  template<class Tv, bool isConst, class A>
5413  bool overlaps(const View<Tv, isConst, A>& v) const
5414  { return e_.overlaps(v); }
5415  const CoordinateOrder& coordinateOrder() const
5416  { return e_.coordinateOrder(); }
5417  const bool isSimple() const
5418  { return e_.isSimple(); }
5419  template<class Accessor>
5420  const T operator()(Accessor it) const
5421  { return unaryFunctor_(e_(it)); }
5422  const T operator()(const size_t c0, const size_t c1) const
5423  { return unaryFunctor_(e_(c0, c1)); }
5424  const T operator()(const size_t c0, const size_t c1,const size_t c2) const
5425  { return unaryFunctor_(e_(c0, c1, c2)); }
5426  const T operator()(const size_t c0, const size_t c1,const size_t c2, const size_t c3) const
5427  { return unaryFunctor_(e_(c0, c1, c2, c3)); }
5428  const T operator()(const size_t c0, const size_t c1,const size_t c2, const size_t c3, const size_t c4) const
5429  { return unaryFunctor_(e_(c0, c1, c2, c3, c4)); }
5430  const T operator[](const size_t offset) const
5431  { return unaryFunctor_(e_[offset]); }
5432 
5433  class ExpressionIterator {
5434  public:
5435  ExpressionIterator(const UnaryViewExpression<E, T, UnaryFunctor>& expression)
5436  : unaryFunctor_(expression.unaryFunctor_),
5437  iterator_(expression.e_)
5438  {}
5439  void incrementCoordinate(const size_t coordinateIndex)
5440  { iterator_.incrementCoordinate(coordinateIndex); }
5441  void resetCoordinate(const size_t coordinateIndex)
5442  { iterator_.resetCoordinate(coordinateIndex); }
5443  const T operator*() const
5444  { return unaryFunctor_(*iterator_); }
5445  private:
5446  UnaryFunctor unaryFunctor_;
5447  typename E::ExpressionIterator iterator_;
5448  };
5449 
5450 private:
5451  const E& e_;
5452  UnaryFunctor unaryFunctor_;
5453 };
5454 
5455 template<class E1, class T1, class E2, class T2, class BinaryFunctor>
5456 class BinaryViewExpression
5457 : public ViewExpression<BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>,
5458  typename marray_detail::PromoteType<T1, T2>::type>
5459 {
5460 public:
5461  typedef E1 expression_type_1;
5462  typedef E2 expression_type_2;
5463  typedef T1 value_type_1;
5464  typedef T2 value_type_2;
5465  typedef typename marray_detail::PromoteType<T1, T2>::type value_type;
5466  typedef BinaryFunctor functor_type;
5467  typedef ViewExpression<BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>,
5468  value_type> base;
5469 
5470  BinaryViewExpression(const ViewExpression<E1, T1>& e1,
5471  const ViewExpression<E2, T2>& e2)
5472  : e1_(e1), e2_(e2), // cast!
5473  binaryFunctor_(BinaryFunctor())
5474  {
5475  if(!MARRAY_NO_DEBUG) {
5476  marray_detail::Assert(e1_.size() != 0 && e2_.size() != 0);
5477  marray_detail::Assert(e1_.dimension() == e2_.dimension());
5478  for(size_t j=0; j<e1_.dimension(); ++j) {
5479  marray_detail::Assert(e1_.shape(j) == e2_.shape(j));
5480  }
5481  }
5482  }
5483  const size_t dimension() const
5484  { return e1_.dimension() < e2_.dimension() ? e2_.dimension() : e1_.dimension(); }
5485  const size_t size() const
5486  { return e1_.size() < e2_.size() ? e2_.size() : e1_.size(); }
5487  const size_t shape(const size_t j) const
5488  { return e1_.dimension() < e2_.dimension() ? e2_.shape(j) : e1_.shape(j); }
5489  const size_t* shapeBegin() const
5490  { return e1_.dimension() < e2_.dimension() ? e2_.shapeBegin() : e1_.shapeBegin(); }
5491  const size_t* shapeEnd() const
5492  { return e1_.dimension() < e2_.dimension() ? e2_.shapeEnd() : e1_.shapeEnd(); }
5493  template<class Tv, bool isConst, class A>
5494  bool overlaps(const View<Tv, isConst, A>& v) const
5495  { return e1_.overlaps(v) || e2_.overlaps(v); }
5496  const CoordinateOrder& coordinateOrder() const
5497  { return e1_.coordinateOrder(); }
5498  const bool isSimple() const
5499  { return e1_.isSimple() && e2_.isSimple()
5500  && e1_.coordinateOrder() == e2_.coordinateOrder(); }
5501  template<class Accessor>
5502  const value_type operator()(Accessor it) const
5503  { return binaryFunctor_(e1_(it), e2_(it)); }
5504  const value_type operator()(const size_t c0, const size_t c1) const
5505  { return binaryFunctor_(e1_(c0, c1), e2_(c0, c1)); }
5506  const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
5507  { return binaryFunctor_(e1_(c0, c1, c2), e2_(c0, c1, c2)); }
5508  const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
5509  { return binaryFunctor_(e1_(c0, c1, c2, c3), e2_(c0, c1, c2, c3)); }
5510  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
5511  { return binaryFunctor_(e1_(c0, c1, c2, c3, c4), e2_(c0, c1, c2, c3, c4)); }
5512  const value_type operator[](const size_t offset) const
5513  { return binaryFunctor_(e1_[offset], e2_[offset]); }
5514 
5515  class ExpressionIterator {
5516  public:
5517  ExpressionIterator(const BinaryViewExpression<E1, T1, E2, T2, BinaryFunctor>& expression)
5518  : binaryFunctor_(expression.binaryFunctor_),
5519  iterator1_(expression.e1_),
5520  iterator2_(expression.e2_)
5521  {}
5522  void incrementCoordinate(const size_t coordinateIndex)
5523  { iterator1_.incrementCoordinate(coordinateIndex);
5524  iterator2_.incrementCoordinate(coordinateIndex); }
5525  void resetCoordinate(const size_t coordinateIndex)
5526  { iterator1_.resetCoordinate(coordinateIndex);
5527  iterator2_.resetCoordinate(coordinateIndex); }
5528  const value_type operator*() const
5529  { return binaryFunctor_(*iterator1_, *iterator2_); }
5530  private:
5531  BinaryFunctor binaryFunctor_;
5532  typename E1::ExpressionIterator iterator1_;
5533  typename E2::ExpressionIterator iterator2_;
5534  };
5535 
5536 private:
5537  const expression_type_1& e1_;
5538  const expression_type_2& e2_;
5539  BinaryFunctor binaryFunctor_;
5540 };
5541 
5542 template<class E, class T, class S, class BinaryFunctor>
5543 class BinaryViewExpressionScalarFirst
5544 : public ViewExpression<BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>,
5545  typename marray_detail::PromoteType<T, S>::type> {
5546 public:
5547  typedef E expression_type;
5548  typedef T value_type_1;
5549  typedef S scalar_type;
5550  typedef typename marray_detail::PromoteType<T, S>::type value_type;
5551  typedef BinaryFunctor functor_type;
5552  typedef ViewExpression<BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>,
5553  value_type> base;
5554 
5555  BinaryViewExpressionScalarFirst(const ViewExpression<E, T>& e,
5556  const scalar_type& scalar)
5557  : e_(e), // cast!
5558  scalar_(scalar), binaryFunctor_(BinaryFunctor())
5559  { }
5560  const size_t dimension() const
5561  { return e_.dimension(); }
5562  const size_t size() const
5563  { return e_.size(); }
5564  const size_t shape(const size_t j) const
5565  { return e_.shape(j); }
5566  const size_t* shapeBegin() const
5567  { return e_.shapeBegin(); }
5568  const size_t* shapeEnd() const
5569  { return e_.shapeEnd(); }
5570  template<class Tv, bool isConst, class A>
5571  bool overlaps(const View<Tv, isConst, A>& v) const
5572  { return e_.overlaps(v); }
5573  const CoordinateOrder& coordinateOrder() const
5574  { return e_.coordinateOrder(); }
5575  const bool isSimple() const
5576  { return e_.isSimple(); }
5577  template<class Accessor>
5578  const value_type operator()(Accessor it) const
5579  { return binaryFunctor_(scalar_, e_(it)); }
5580  const value_type operator()(const size_t c0, const size_t c1) const
5581  { return binaryFunctor_(scalar_, e_(c0, c1)); }
5582  const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
5583  { return binaryFunctor_(scalar_, e_(c0, c1, c2)); }
5584  const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
5585  { return binaryFunctor_(scalar_, e_(c0, c1, c2, c3)); }
5586  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
5587  { return binaryFunctor_(scalar_, e_(c0, c1, c2, c3, c4)); }
5588  const value_type operator[](const size_t offset) const
5589  { return binaryFunctor_(scalar_, e_[offset]); }
5590 
5591  class ExpressionIterator {
5592  public:
5593  ExpressionIterator(const BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>& expression)
5594  : binaryFunctor_(expression.binaryFunctor_),
5595  scalar_(expression.scalar_),
5596  iterator_(expression.e_)
5597  {}
5598  void incrementCoordinate(const size_t coordinateIndex)
5599  { iterator_.incrementCoordinate(coordinateIndex); }
5600  void resetCoordinate(const size_t coordinateIndex)
5601  { iterator_.resetCoordinate(coordinateIndex); }
5602  const T operator*() const
5603  { return binaryFunctor_(scalar_, *iterator_); }
5604  private:
5605  BinaryFunctor binaryFunctor_;
5606  const typename BinaryViewExpressionScalarFirst<E, T, S, BinaryFunctor>::scalar_type& scalar_;
5607  typename E::ExpressionIterator iterator_;
5608  };
5609 
5610 private:
5611  const expression_type& e_;
5612  const scalar_type scalar_;
5613  BinaryFunctor binaryFunctor_;
5614 };
5615 
5616 template<class E, class T, class S, class BinaryFunctor>
5617 class BinaryViewExpressionScalarSecond
5618 : public ViewExpression<BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>,
5619  typename marray_detail::PromoteType<T, S>::type> {
5620 public:
5621  typedef T value_type_1;
5622  typedef E expression_type;
5623  typedef S scalar_type;
5624  typedef typename marray_detail::PromoteType<T, S>::type value_type;
5625  typedef BinaryFunctor functor_type;
5626  typedef ViewExpression<BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>,
5627  value_type> base;
5628 
5629  BinaryViewExpressionScalarSecond(const ViewExpression<E, T>& e,
5630  const scalar_type& scalar)
5631  : e_(e), // cast!
5632  scalar_(scalar), binaryFunctor_(BinaryFunctor())
5633  { }
5634  const size_t dimension() const
5635  { return e_.dimension(); }
5636  const size_t size() const
5637  { return e_.size(); }
5638  const size_t shape(const size_t j) const
5639  { return e_.shape(j); }
5640  const size_t* shapeBegin() const
5641  { return e_.shapeBegin(); }
5642  const size_t* shapeEnd() const
5643  { return e_.shapeEnd(); }
5644  template<class Tv, bool isConst, class A>
5645  bool overlaps(const View<Tv, isConst, A>& v) const
5646  { return e_.overlaps(v); }
5647  const CoordinateOrder& coordinateOrder() const
5648  { return e_.coordinateOrder(); }
5649  const bool isSimple() const
5650  { return e_.isSimple(); }
5651  template<class Accessor>
5652  const value_type operator()(Accessor it) const
5653  { return binaryFunctor_(e_(it), scalar_); }
5654  const value_type operator()(const size_t c0, const size_t c1) const
5655  { return binaryFunctor_(e_(c0, c1), scalar_); }
5656  const value_type operator()(const size_t c0, const size_t c1, const size_t c2) const
5657  { return binaryFunctor_(e_(c0, c1, c2), scalar_); }
5658  const value_type operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
5659  { return binaryFunctor_(e_(c0, c1, c2, c3), scalar_); }
5660  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
5661  { return binaryFunctor_(e_(c0, c1, c2, c3, c4), scalar_); }
5662  const value_type operator[](const size_t offset) const
5663  { return binaryFunctor_(e_[offset], scalar_); }
5664 
5665  class ExpressionIterator {
5666  public:
5667  ExpressionIterator(const BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>& expression)
5668  : binaryFunctor_(expression.binaryFunctor_),
5669  scalar_(expression.scalar_),
5670  iterator_(expression.e_)
5671  {}
5672  void incrementCoordinate(const size_t coordinateIndex)
5673  { iterator_.incrementCoordinate(coordinateIndex); }
5674  void resetCoordinate(const size_t coordinateIndex)
5675  { iterator_.resetCoordinate(coordinateIndex); }
5676  const T operator*() const
5677  { return binaryFunctor_(*iterator_, scalar_); }
5678  private:
5679  BinaryFunctor binaryFunctor_;
5680  const typename BinaryViewExpressionScalarSecond<E, T, S, BinaryFunctor>::scalar_type& scalar_;
5681  typename E::ExpressionIterator iterator_;
5682  };
5683 
5684 private:
5685  const expression_type& e_;
5686  const scalar_type scalar_;
5687  BinaryFunctor binaryFunctor_;
5688 };
5689 // \endcond suppress doxygen
5690 
5691 // implementation of marray_detail
5692 
5693 // \cond suppress doxygen
5694 namespace marray_detail {
5695 
5696 template<class A>
5697 class Geometry
5698 {
5699 public:
5700  typedef typename A::template rebind<size_t>::other allocator_type;
5701 
5702  Geometry(const allocator_type& = allocator_type());
5703  Geometry(const size_t, const CoordinateOrder& = defaultOrder,
5704  const size_t = 0, const bool = true,
5705  const allocator_type& = allocator_type());
5706  template<class ShapeIterator>
5707  Geometry(ShapeIterator, ShapeIterator,
5708  const CoordinateOrder& = defaultOrder,
5709  const CoordinateOrder& = defaultOrder,
5710  const allocator_type& = allocator_type());
5711  template<class ShapeIterator, class StrideIterator>
5712  Geometry(ShapeIterator, ShapeIterator, StrideIterator,
5713  const CoordinateOrder& = defaultOrder,
5714  const allocator_type& = allocator_type());
5715  Geometry(const Geometry<A>&);
5716  ~Geometry();
5717 
5718  Geometry<A>& operator=(const Geometry<A>&);
5719 
5720  void resize(const size_t dimension);
5721  const size_t dimension() const;
5722  const size_t shape(const size_t) const;
5723  size_t& shape(const size_t);
5724  const size_t shapeStrides(const size_t) const;
5725  size_t& shapeStrides(const size_t);
5726  const size_t strides(const size_t) const;
5727  size_t& strides(const size_t);
5728  const size_t* shapeBegin() const;
5729  size_t* shapeBegin();
5730  const size_t* shapeEnd() const;
5731  size_t* shapeEnd();
5732  const size_t* shapeStridesBegin() const;
5733  size_t* shapeStridesBegin();
5734  const size_t* shapeStridesEnd() const;
5735  size_t* shapeStridesEnd();
5736  const size_t* stridesBegin() const;
5737  size_t* stridesBegin();
5738  const size_t* stridesEnd() const;
5739  size_t* stridesEnd();
5740  const size_t size() const;
5741  size_t& size();
5742  const CoordinateOrder& coordinateOrder() const;
5743  CoordinateOrder& coordinateOrder();
5744  const bool isSimple() const;
5745  void updateSimplicity();
5746  bool& isSimple();
5747 
5748 private:
5749  allocator_type allocator_;
5750  size_t* shape_;
5751  size_t* shapeStrides_;
5752  // Intended redundancy: shapeStrides_ could be
5753  // computed from shape_ and coordinateOrder_
5754  size_t* strides_;
5755  size_t dimension_;
5756  size_t size_;
5757  // intended redundancy: size_ could be computed from shape_
5758  CoordinateOrder coordinateOrder_;
5759  bool isSimple_;
5760  // simple array: an array which is unstrided (i.e. the strides
5761  // equal the shape strides), cf. the function testInvariant of
5762  // View for the formal definition.
5763 };
5764 
5765 template<class A>
5766 inline
5767 Geometry<A>::Geometry
5768 (
5769  const typename Geometry<A>::allocator_type& allocator
5770 )
5771 : allocator_(allocator),
5772  shape_(0),
5773  shapeStrides_(0),
5774  strides_(0),
5775  dimension_(0),
5776  size_(0),
5777  coordinateOrder_(defaultOrder),
5778  isSimple_(true)
5779 {
5780 }
5781 
5782 template<class A>
5783 inline
5784 Geometry<A>::Geometry
5785 (
5786  const Geometry<A>& g
5787 )
5788 : allocator_(g.allocator_),
5789  shape_(g.dimension_==0 ? 0 : allocator_.allocate(g.dimension_*3)),
5790  shapeStrides_(shape_ + g.dimension_),
5791  strides_(shapeStrides_ + g.dimension_),
5792  dimension_(g.dimension_),
5793  size_(g.size_),
5794  coordinateOrder_(g.coordinateOrder_),
5795  isSimple_(g.isSimple_)
5796 {
5797  /*
5798  for(size_t j=0; j<dimension_; ++j) {
5799  shape_[j] = g.shape_[j];
5800  shapeStrides_[j] = g.shapeStrides_[j];
5801  strides_[j] = g.strides_[j];
5802  }
5803  */
5804  memcpy(shape_, g.shape_, (dimension_*3)*sizeof(size_t));
5805 }
5806 
5807 template<class A>
5808 inline
5809 Geometry<A>::Geometry
5810 (
5811  const size_t dimension,
5812  const CoordinateOrder& order,
5813  const size_t size,
5814  const bool isSimple,
5815  const typename Geometry<A>::allocator_type& allocator
5816 )
5817 : allocator_(allocator),
5818  shape_(allocator_.allocate(dimension*3)),
5819  shapeStrides_(shape_+dimension),
5820  strides_(shapeStrides_+dimension),
5821  dimension_(dimension),
5822  size_(size),
5823  coordinateOrder_(order),
5824  isSimple_(isSimple)
5825 {
5826 }
5827 
5828 template<class A>
5829 template<class ShapeIterator>
5830 inline
5831 Geometry<A>::Geometry
5832 (
5833  ShapeIterator begin,
5834  ShapeIterator end,
5835  const CoordinateOrder& externalCoordinateOrder,
5836  const CoordinateOrder& internalCoordinateOrder,
5837  const typename Geometry<A>::allocator_type& allocator
5838 )
5839 : allocator_(allocator),
5840  shape_(allocator_.allocate(std::distance(begin, end) * 3)),
5841  shapeStrides_(shape_ + std::distance(begin, end)),
5842  strides_(shapeStrides_ + std::distance(begin, end)),
5843  dimension_(std::distance(begin, end)),
5844  size_(1),
5845  coordinateOrder_(internalCoordinateOrder),
5846  isSimple_(true)
5847 {
5848  if(dimension_ != 0) { // if the array is not a scalar
5849  isSimple_ = (externalCoordinateOrder == internalCoordinateOrder);
5850  for(size_t j=0; j<dimension(); ++j, ++begin) {
5851  const size_t s = static_cast<size_t>(*begin);
5852  shape(j) = s;
5853  size() *= s;
5854  }
5855  stridesFromShape(shapeBegin(), shapeEnd(), stridesBegin(),
5856  externalCoordinateOrder);
5857  stridesFromShape(shapeBegin(), shapeEnd(), shapeStridesBegin(),
5858  internalCoordinateOrder);
5859  }
5860 }
5861 
5862 template<class A>
5863 template<class ShapeIterator, class StrideIterator>
5864 inline
5865 Geometry<A>::Geometry
5866 (
5867  ShapeIterator begin,
5868  ShapeIterator end,
5869  StrideIterator it,
5870  const CoordinateOrder& internalCoordinateOrder,
5871  const typename Geometry<A>::allocator_type& allocator
5872 )
5873 : allocator_(allocator),
5874  shape_(allocator_.allocate(std::distance(begin, end) * 3)),
5875  shapeStrides_(shape_ + std::distance(begin, end)),
5876  strides_(shapeStrides_ + std::distance(begin, end)),
5877  dimension_(std::distance(begin, end)),
5878  size_(1),
5879  coordinateOrder_(internalCoordinateOrder),
5880  isSimple_(true)
5881 {
5882  if(dimension() != 0) {
5883  for(size_t j=0; j<dimension(); ++j, ++begin, ++it) {
5884  const size_t s = static_cast<size_t>(*begin);
5885  shape(j) = s;
5886  size() *= s;
5887  strides(j) = *it;
5888  }
5889  stridesFromShape(shapeBegin(), shapeEnd(), shapeStridesBegin(),
5890  internalCoordinateOrder);
5891  updateSimplicity();
5892  }
5893 }
5894 
5895 template<class A>
5896 inline
5897 Geometry<A>::~Geometry()
5898 {
5899  allocator_.deallocate(shape_, dimension_*3);
5900 }
5901 
5902 template<class A>
5903 inline Geometry<A>&
5904 Geometry<A>::operator=
5905 (
5906  const Geometry<A>& g
5907 )
5908 {
5909  if(&g != this) { // no self-assignment
5910  if(g.dimension_ != dimension_) {
5911  allocator_.deallocate(shape_, dimension_*3);
5912  dimension_ = g.dimension_;
5913  shape_ = allocator_.allocate(dimension_*3);
5914  shapeStrides_ = shape_+dimension_;
5915  strides_ = shapeStrides_+dimension_;
5916  dimension_ = g.dimension_;
5917  }
5918  /*
5919  for(size_t j=0; j<dimension_; ++j) {
5920  shape_[j] = g.shape_[j];
5921  shapeStrides_[j] = g.shapeStrides_[j];
5922  strides_[j] = g.strides_[j];
5923  }
5924  */
5925  memcpy(shape_, g.shape_, (dimension_*3)*sizeof(size_t));
5926  size_ = g.size_;
5927  coordinateOrder_ = g.coordinateOrder_;
5928  isSimple_ = g.isSimple_;
5929  }
5930  return *this;
5931 }
5932 
5933 template<class A>
5934 inline void
5935 Geometry<A>::resize
5936 (
5937  const size_t dimension
5938 )
5939 {
5940  if(dimension != dimension_) {
5941  size_t* newShape = allocator_.allocate(dimension*3);
5942  size_t* newShapeStrides = newShape + dimension;
5943  size_t* newStrides = newShapeStrides + dimension;
5944  for(size_t j=0; j<( (dimension < dimension_) ? dimension : dimension_); ++j) {
5945  // save existing entries
5946  newShape[j] = shape(j);
5947  newShapeStrides[j] = shapeStrides(j);
5948  newStrides[j] = strides(j);
5949  }
5950  allocator_.deallocate(shape_, dimension_*3);
5951  shape_ = newShape;
5952  shapeStrides_ = newShapeStrides;
5953  strides_ = newStrides;
5954  dimension_ = dimension;
5955  }
5956 }
5957 
5958 template<class A>
5959 inline const size_t
5960 Geometry<A>::dimension() const
5961 {
5962  return dimension_;
5963 }
5964 
5965 template<class A>
5966 inline const size_t
5967 Geometry<A>::shape(const size_t j) const
5968 {
5969  Assert(MARRAY_NO_DEBUG || j<dimension_);
5970  return shape_[j];
5971 }
5972 
5973 template<class A>
5974 inline size_t&
5975 Geometry<A>::shape(const size_t j)
5976 {
5977  Assert(MARRAY_NO_DEBUG || j<dimension_);
5978  return shape_[j];
5979 }
5980 
5981 template<class A>
5982 inline const size_t
5983 Geometry<A>::shapeStrides
5984 (
5985  const size_t j
5986 ) const
5987 {
5988  Assert(MARRAY_NO_DEBUG || j<dimension_);
5989  return shapeStrides_[j];
5990 }
5991 
5992 template<class A>
5993 inline size_t&
5994 Geometry<A>::shapeStrides
5995 (
5996  const size_t j
5997 )
5998 {
5999  Assert(MARRAY_NO_DEBUG || j<dimension_);
6000  return shapeStrides_[j];
6001 }
6002 
6003 template<class A>
6004 inline const size_t
6005 Geometry<A>::strides
6006 (
6007  const size_t j
6008 ) const
6009 {
6010  Assert(MARRAY_NO_DEBUG || j<dimension_);
6011  return strides_[j];
6012 }
6013 
6014 template<class A>
6015 inline size_t&
6016 Geometry<A>::strides
6017 (
6018  const size_t j
6019 )
6020 {
6021  Assert(MARRAY_NO_DEBUG || j<dimension_);
6022  return strides_[j];
6023 }
6024 
6025 template<class A>
6026 inline const size_t*
6027 Geometry<A>::shapeBegin() const
6028 {
6029  return shape_;
6030 }
6031 
6032 template<class A>
6033 inline size_t*
6034 Geometry<A>::shapeBegin()
6035 {
6036  return shape_;
6037 }
6038 
6039 template<class A>
6040 inline const size_t*
6041 Geometry<A>::shapeEnd() const
6042 {
6043  return shape_ + dimension_;
6044 }
6045 
6046 template<class A>
6047 inline size_t*
6048 Geometry<A>::shapeEnd()
6049 {
6050  return shape_ + dimension_;
6051 }
6052 
6053 template<class A>
6054 inline const size_t*
6055 Geometry<A>::shapeStridesBegin() const
6056 {
6057  return shapeStrides_;
6058 }
6059 
6060 template<class A>
6061 inline size_t*
6062 Geometry<A>::shapeStridesBegin()
6063 {
6064  return shapeStrides_;
6065 }
6066 
6067 template<class A>
6068 inline const size_t*
6069 Geometry<A>::shapeStridesEnd() const
6070 {
6071  return shapeStrides_ + dimension_;
6072 }
6073 
6074 template<class A>
6075 inline size_t*
6076 Geometry<A>::shapeStridesEnd()
6077 {
6078  return shapeStrides_ + dimension_;
6079 }
6080 
6081 template<class A>
6082 inline const size_t*
6083 Geometry<A>::stridesBegin() const
6084 {
6085  return strides_;
6086 }
6087 
6088 template<class A>
6089 inline size_t*
6090 Geometry<A>::stridesBegin()
6091 {
6092  return strides_;
6093 }
6094 
6095 template<class A>
6096 inline const size_t*
6097 Geometry<A>::stridesEnd() const
6098 {
6099  return strides_ + dimension_;
6100 }
6101 
6102 template<class A>
6103 inline size_t*
6104 Geometry<A>::stridesEnd()
6105 {
6106  return strides_ + dimension_;
6107 }
6108 
6109 template<class A>
6110 inline const size_t
6111 Geometry<A>::size() const
6112 {
6113  return size_;
6114 }
6115 
6116 template<class A>
6117 inline size_t&
6118 Geometry<A>::size()
6119 {
6120  return size_;
6121 }
6122 
6123 template<class A>
6124 inline const CoordinateOrder&
6125 Geometry<A>::coordinateOrder() const
6126 {
6127  return coordinateOrder_;
6128 }
6129 
6130 template<class A>
6131 inline CoordinateOrder&
6132 Geometry<A>::coordinateOrder()
6133 {
6134  return coordinateOrder_;
6135 }
6136 
6137 template<class A>
6138 inline const bool
6139 Geometry<A>::isSimple() const
6140 {
6141  return isSimple_;
6142 }
6143 
6144 template<class A>
6145 inline bool&
6146 Geometry<A>::isSimple()
6147 {
6148  return isSimple_;
6149 }
6150 
6151 template<class A>
6152 inline void
6153 Geometry<A>::updateSimplicity()
6154 {
6155  for(size_t j=0; j<dimension(); ++j) {
6156  if(shapeStrides(j) != strides(j)) {
6157  isSimple_ = false;
6158  return;
6159  }
6160  }
6161  isSimple_ = true;
6162  // a 0-dimensional geometry is simple
6163 }
6164 
6165 template<class ShapeIterator, class StridesIterator>
6166 inline void
6167 stridesFromShape
6168 (
6169  ShapeIterator begin,
6170  ShapeIterator end,
6171  StridesIterator strideBegin,
6172  const CoordinateOrder& coordinateOrder
6173 )
6174 {
6175  Assert(MARRAY_NO_ARG_TEST || std::distance(begin, end) != 0);
6176  size_t dimension = std::distance(begin, end);
6177  ShapeIterator shapeIt;
6178  StridesIterator strideIt;
6179  if(coordinateOrder == FirstMajorOrder) {
6180  shapeIt = begin + (dimension-1);
6181  strideIt = strideBegin + (dimension-1);
6182  *strideIt = 1;
6183  for(size_t j=1; j<dimension; ++j) {
6184  size_t tmp = *strideIt;
6185  --strideIt;
6186  (*strideIt) = tmp * (*shapeIt);
6187  --shapeIt;
6188  }
6189  }
6190  else {
6191  shapeIt = begin;
6192  strideIt = strideBegin;
6193  *strideIt = 1;
6194  for(size_t j=1; j<dimension; ++j) {
6195  size_t tmp = *strideIt;
6196  ++strideIt;
6197  (*strideIt) = tmp * (*shapeIt);
6198  ++shapeIt;
6199  }
6200  }
6201 }
6202 
6203 template<unsigned short N, class Functor, class T, class A>
6204 struct OperateHelperUnary
6205 {
6206  static inline void operate
6207  (
6208  View<T, false, A>& v,
6209  Functor f,
6210  T* data
6211  )
6212  {
6213  for(size_t j=0; j<v.shape(N-1); ++j) {
6214  OperateHelperUnary<N-1, Functor, T, A>::operate(v, f, data);
6215  data += v.strides(N-1);
6216  }
6217  data -= v.shape(N-1) * v.strides(N-1);
6218  }
6219 };
6220 
6221 
6222 template<class Functor, class T, class A>
6223 struct OperateHelperUnary<0, Functor, T, A>
6224 {
6225  static inline void operate
6226  (
6227  View<T, false, A>& v,
6228  Functor f,
6229  T* data
6230  )
6231  {
6232  f(*data);
6233  }
6234 };
6235 
6236 template<unsigned short N, class Functor, class T1, class T2, class A>
6237 struct OperateHelperBinaryScalar
6238 {
6239  static inline void operate
6240  (
6241  View<T1, false, A>& v,
6242  const T2& x,
6243  Functor f,
6244  T1* data
6245  )
6246  {
6247  for(size_t j=0; j<v.shape(N-1); ++j) {
6248  OperateHelperBinaryScalar<N-1, Functor, T1, T2, A>::operate(
6249  v, x, f, data);
6250  data += v.strides(N-1);
6251  }
6252  data -= v.shape(N-1) * v.strides(N-1);
6253  }
6254 };
6255 
6256 template<class Functor, class T1, class T2, class A>
6257 struct OperateHelperBinaryScalar<0, Functor, T1, T2, A>
6258 {
6259  static inline void operate
6260  (
6261  View<T1, false, A>& v,
6262  const T2& x,
6263  Functor f,
6264  T1* data
6265  )
6266  {
6267  f(*data, x);
6268  }
6269 };
6270 
6271 template<unsigned short N, class Functor, class T1, class T2,
6272  bool isConst, class A1, class A2>
6273 struct OperateHelperBinary
6274 {
6275  static inline void operate
6276  (
6277  View<T1, false, A1>& v,
6278  const View<T2, isConst, A2>& w,
6279  Functor f,
6280  T1* data1,
6281  const T2* data2
6282  )
6283  {
6284  for(size_t j=0; j<v.shape(N-1); ++j) {
6285  OperateHelperBinary<N-1, Functor, T1, T2, isConst, A1, A2>::operate(
6286  v, w, f, data1, data2);
6287  data1 += v.strides(N-1);
6288  data2 += w.strides(N-1);
6289  }
6290  data1 -= v.shape(N-1) * v.strides(N-1);
6291  data2 -= w.shape(N-1) * w.strides(N-1);
6292  }
6293 };
6294 
6295 template<class Functor, class T1, class T2, bool isConst, class A1, class A2>
6296 struct OperateHelperBinary<0, Functor, T1, T2, isConst, A1, A2>
6297 {
6298  static inline void operate
6299  (
6300  View<T1, false, A1>& v,
6301  const View<T2, isConst, A2>& w,
6302  Functor f,
6303  T1* data1,
6304  const T2* data2
6305  )
6306  {
6307  f(*data1, *data2);
6308  }
6309 };
6310 
6311 template<class TFrom, class TTo, class AFrom, class ATo>
6312 struct AssignmentOperatorHelper<false, TFrom, TTo, AFrom, ATo>
6313 {
6314  // from constant to mutable
6315  //
6316  // here, 'to' must be initialized (which is asserted) because
6317  // otherwise, the pointer to.data_ to mutable data would have
6318  // to be initialized with the pointer from.data_ to constant
6319  // data which we don't do.
6320  //
6321  static void execute
6322  (
6323  const View<TFrom, true, AFrom>& from,
6324  View<TTo, false, ATo>& to
6325  )
6326  {
6327  typedef typename View<TFrom, true, AFrom>::const_iterator FromIterator;
6328  typedef typename View<TTo, false, ATo>::iterator ToIterator;
6329  if(!MARRAY_NO_ARG_TEST) {
6330  Assert(from.data_ != 0 && from.dimension() == to.dimension());
6331  for(size_t j=0; j<from.dimension(); ++j) {
6332  Assert(from.shape(j) == to.shape(j));
6333  }
6334  }
6335  if(from.overlaps(to)) {
6336  Marray<TFrom, AFrom> m = from; // temporary copy
6337  execute(m, to);
6338  }
6339  else if(from.coordinateOrder() == to.coordinateOrder()
6340  && from.isSimple() && to.isSimple()
6341  && IsEqual<TFrom, TTo>::type) {
6342  memcpy(to.data_, from.data_, (from.size())*sizeof(TFrom));
6343  }
6344  else if(from.dimension() == 1)
6345  OperateHelperBinary<1, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6346  else if(from.dimension() == 2)
6347  OperateHelperBinary<2, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6348  else if(from.dimension() == 3)
6349  OperateHelperBinary<3, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6350  else if(from.dimension() == 4)
6351  OperateHelperBinary<4, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6352  else if(from.dimension() == 5)
6353  OperateHelperBinary<5, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6354  else if(from.dimension() == 6)
6355  OperateHelperBinary<6, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6356  else if(from.dimension() == 7)
6357  OperateHelperBinary<7, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6358  else if(from.dimension() == 8)
6359  OperateHelperBinary<8, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6360  else if(from.dimension() == 9)
6361  OperateHelperBinary<9, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6362  else if(from.dimension() == 10)
6363  OperateHelperBinary<10, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6364  else {
6365  FromIterator itFrom = from.begin();
6366  ToIterator itTo = to.begin();
6367  for(; itFrom.hasMore(); ++itFrom, ++itTo) {
6368  *itTo = static_cast<TTo>(*itFrom);
6369  }
6370  }
6371  }
6372 
6377  static void execute
6378  (
6379  const View<TFrom, false, AFrom>& from,
6380  View<TTo, false, ATo>& to
6381  )
6382  {
6383  typedef typename View<TFrom, false, AFrom>::const_iterator FromIterator;
6384  typedef typename View<TTo, false, ATo>::iterator ToIterator;
6385  if(static_cast<const void*>(&from) != static_cast<const void*>(&to)) { // no self-assignment
6386  if(to.data_ == 0) { // if the view 'to' is not initialized
6387  // initialize the view 'to' with source data
6388  Assert(MARRAY_NO_ARG_TEST || sizeof(TTo) == sizeof(TFrom));
6389  to.data_ = static_cast<TTo*>(static_cast<void*>(from.data_)); // copy pointer
6390  to.geometry_ = from.geometry_;
6391  }
6392  else { // if the view 'to' is initialized
6393  if(!MARRAY_NO_ARG_TEST) {
6394  Assert(from.data_ != 0 && from.dimension() == to.dimension());
6395  for(size_t j=0; j<from.dimension(); ++j) {
6396  Assert(from.shape(j) == to.shape(j));
6397  }
6398  }
6399  if(from.overlaps(to)) {
6400  Marray<TFrom, AFrom> m = from; // temporary copy
6401  execute(m, to);
6402  }
6403  else if(from.coordinateOrder() == to.coordinateOrder()
6404  && from.isSimple() && to.isSimple()
6405  && IsEqual<TFrom, TTo>::type) {
6406  memcpy(to.data_, from.data_, (from.size())*sizeof(TFrom));
6407  }
6408  else if(from.dimension() == 1)
6409  OperateHelperBinary<1, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6410  else if(from.dimension() == 2)
6411  OperateHelperBinary<2, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6412  else if(from.dimension() == 3)
6413  OperateHelperBinary<3, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6414  else if(from.dimension() == 4)
6415  OperateHelperBinary<4, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6416  else if(from.dimension() == 5)
6417  OperateHelperBinary<5, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6418  else if(from.dimension() == 6)
6419  OperateHelperBinary<6, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6420  else if(from.dimension() == 7)
6421  OperateHelperBinary<7, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6422  else if(from.dimension() == 8)
6423  OperateHelperBinary<8, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6424  else if(from.dimension() == 9)
6425  OperateHelperBinary<9, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6426  else if(from.dimension() == 10)
6427  OperateHelperBinary<10, Assign<TTo, TFrom>, TTo, TFrom, true, ATo, AFrom>::operate(to, from, Assign<TTo, TFrom>(), &to(0), &from(0));
6428  else {
6429  FromIterator itFrom = from.begin();
6430  ToIterator itTo = to.begin();
6431  for(; itFrom.hasMore(); ++itFrom, ++itTo) {
6432  *itTo = static_cast<TTo>(*itFrom);
6433  }
6434  }
6435  }
6436  }
6437  }
6438 };
6439 
6440 template<class TFrom, class TTo, class AFrom, class ATo>
6441 struct AssignmentOperatorHelper<true, TFrom, TTo, AFrom, ATo>
6442 {
6444  template<bool isConstFrom>
6445  static void execute
6446  (
6447  const View<TFrom, isConstFrom, AFrom>& from,
6448  View<TTo, true, ATo>& to
6449  )
6450  {
6451  Assert(MARRAY_NO_ARG_TEST || sizeof(TFrom) == sizeof(TTo));
6452  to.data_ = static_cast<const TTo*>(
6453  static_cast<const void*>(from.data_)); // copy pointer
6454  to.geometry_ = from.geometry_;
6455  }
6456 };
6457 
6458 template<>
6459 struct AccessOperatorHelper<true>
6460 {
6461  // access by scalar index
6462  template<class T, class U, bool isConst, class A>
6463  static typename View<T, isConst, A>::reference
6464  execute(const View<T, isConst, A>& v, const U& index)
6465  {
6466  v.testInvariant();
6467  Assert(MARRAY_NO_DEBUG || v.data_ != 0);
6468  Assert(MARRAY_NO_DEBUG || v.dimension() != 0 || index == 0);
6469  size_t offset;
6470  v.indexToOffset(index, offset);
6471  return v.data_[offset];
6472  }
6473 };
6474 
6475 template<>
6476 struct AccessOperatorHelper<false>
6477 {
6478  // access by iterator
6479  template<class T, class U, bool isConst, class A>
6480  static typename View<T, isConst, A>::reference
6481  execute(const View<T, isConst, A>& v, U it)
6482  {
6483  v.testInvariant();
6484  Assert(MARRAY_NO_DEBUG || v.data_ != 0 );
6485  Assert(MARRAY_NO_DEBUG || v.dimension() != 0 || *it == 0);
6486  size_t offset;
6487  v.coordinatesToOffset(it, offset);
6488  return v.data_[offset];
6489  }
6490 };
6491 
6492 template<class Functor, class T, class A>
6493 inline void
6494 operate
6495 (
6496  View<T, false, A>& v,
6497  Functor f
6498 )
6499 {
6500  if(v.isSimple()) {
6501  T* data = &v(0);
6502  for(size_t j=0; j<v.size(); ++j) {
6503  f(data[j]);
6504  }
6505  }
6506  else if(v.dimension() == 1)
6507  OperateHelperUnary<1, Functor, T, A>::operate(v, f, &v(0));
6508  else if(v.dimension() == 2)
6509  OperateHelperUnary<2, Functor, T, A>::operate(v, f, &v(0));
6510  else if(v.dimension() == 3)
6511  OperateHelperUnary<3, Functor, T, A>::operate(v, f, &v(0));
6512  else if(v.dimension() == 4)
6513  OperateHelperUnary<4, Functor, T, A>::operate(v, f, &v(0));
6514  else if(v.dimension() == 5)
6515  OperateHelperUnary<5, Functor, T, A>::operate(v, f, &v(0));
6516  else if(v.dimension() == 6)
6517  OperateHelperUnary<6, Functor, T, A>::operate(v, f, &v(0));
6518  else if(v.dimension() == 7)
6519  OperateHelperUnary<7, Functor, T, A>::operate(v, f, &v(0));
6520  else if(v.dimension() == 8)
6521  OperateHelperUnary<8, Functor, T, A>::operate(v, f, &v(0));
6522  else if(v.dimension() == 9)
6523  OperateHelperUnary<9, Functor, T, A>::operate(v, f, &v(0));
6524  else if(v.dimension() == 10)
6525  OperateHelperUnary<10, Functor, T, A>::operate(v, f, &v(0));
6526  else {
6527  for(typename View<T, false, A>::iterator it = v.begin(); it.hasMore(); ++it) {
6528  f(*it);
6529  }
6530  }
6531 }
6532 
6533 template<class Functor, class T, class A>
6534 inline void
6535 operate
6536 (
6537  View<T, false, A>& v,
6538  const T& x,
6539  Functor f
6540 )
6541 {
6542  if(v.isSimple()) {
6543  T* data = &v(0);
6544  for(size_t j=0; j<v.size(); ++j) {
6545  f(data[j], x);
6546  }
6547  }
6548  else if(v.dimension() == 1)
6549  OperateHelperBinaryScalar<1, Functor, T, T, A>::operate(v, x, f, &v(0));
6550  else if(v.dimension() == 2)
6551  OperateHelperBinaryScalar<2, Functor, T, T, A>::operate(v, x, f, &v(0));
6552  else if(v.dimension() == 3)
6553  OperateHelperBinaryScalar<3, Functor, T, T, A>::operate(v, x, f, &v(0));
6554  else if(v.dimension() == 4)
6555  OperateHelperBinaryScalar<4, Functor, T, T, A>::operate(v, x, f, &v(0));
6556  else if(v.dimension() == 5)
6557  OperateHelperBinaryScalar<5, Functor, T, T, A>::operate(v, x, f, &v(0));
6558  else if(v.dimension() == 6)
6559  OperateHelperBinaryScalar<6, Functor, T, T, A>::operate(v, x, f, &v(0));
6560  else if(v.dimension() == 7)
6561  OperateHelperBinaryScalar<7, Functor, T, T, A>::operate(v, x, f, &v(0));
6562  else if(v.dimension() == 8)
6563  OperateHelperBinaryScalar<8, Functor, T, T, A>::operate(v, x, f, &v(0));
6564  else if(v.dimension() == 9)
6565  OperateHelperBinaryScalar<9, Functor, T, T, A>::operate(v, x, f, &v(0));
6566  else if(v.dimension() == 10)
6567  OperateHelperBinaryScalar<10, Functor, T, T, A>::operate(v, x, f, &v(0));
6568  else {
6569  for(typename View<T, false, A>::iterator it = v.begin(); it.hasMore(); ++it) {
6570  f(*it, x);
6571  }
6572  }
6573 }
6574 
6575 template<class Functor, class T1, class T2, bool isConst, class A>
6576 inline void
6577 operate
6578 (
6579  View<T1, false, A>& v,
6580  const View<T2, isConst, A>& w,
6581  Functor f
6582 )
6583 {
6584  if(!MARRAY_NO_ARG_TEST) {
6585  Assert(v.size() != 0 && w.size() != 0);
6586  Assert(w.dimension() == 0 || v.dimension() == w.dimension());
6587  if(w.dimension() != 0) {
6588  for(size_t j=0; j<v.dimension(); ++j) {
6589  Assert(v.shape(j) == w.shape(j));
6590  }
6591  }
6592  }
6593  if(w.dimension() == 0) {
6594  T2 x = w(0);
6595  if(v.isSimple()) {
6596  T1* dataV = &v(0);
6597  for(size_t j=0; j<v.size(); ++j) {
6598  f(dataV[j], x);
6599  }
6600  }
6601  else if(v.dimension() == 1)
6602  OperateHelperBinaryScalar<1, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6603  else if(v.dimension() == 2)
6604  OperateHelperBinaryScalar<2, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6605  else if(v.dimension() == 3)
6606  OperateHelperBinaryScalar<3, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6607  else if(v.dimension() == 4)
6608  OperateHelperBinaryScalar<4, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6609  else if(v.dimension() == 5)
6610  OperateHelperBinaryScalar<5, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6611  else if(v.dimension() == 6)
6612  OperateHelperBinaryScalar<6, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6613  else if(v.dimension() == 7)
6614  OperateHelperBinaryScalar<7, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6615  else if(v.dimension() == 8)
6616  OperateHelperBinaryScalar<8, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6617  else if(v.dimension() == 9)
6618  OperateHelperBinaryScalar<9, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6619  else if(v.dimension() == 10)
6620  OperateHelperBinaryScalar<10, Functor, T1, T2, A>::operate(v, x, f, &v(0));
6621  else {
6622  for(typename View<T1, false>::iterator it = v.begin(); it.hasMore(); ++it) {
6623  f(*it, x);
6624  }
6625  }
6626  }
6627  else {
6628  if(v.overlaps(w)) {
6629  Marray<T2> m = w; // temporary copy
6630  operate(v, m, f); // recursive call
6631  }
6632  else {
6633  if(v.coordinateOrder() == w.coordinateOrder()
6634  && v.isSimple() && w.isSimple()) {
6635  T1* dataV = &v(0);
6636  const T2* dataW = &w(0);
6637  for(size_t j=0; j<v.size(); ++j) {
6638  f(dataV[j], dataW[j]);
6639  }
6640  }
6641  else if(v.dimension() == 1)
6642  OperateHelperBinary<1, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6643  else if(v.dimension() == 2)
6644  OperateHelperBinary<2, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6645  else if(v.dimension() == 3)
6646  OperateHelperBinary<3, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6647  else if(v.dimension() == 4)
6648  OperateHelperBinary<4, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6649  else if(v.dimension() == 5)
6650  OperateHelperBinary<5, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6651  else if(v.dimension() == 6)
6652  OperateHelperBinary<6, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6653  else if(v.dimension() == 7)
6654  OperateHelperBinary<7, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6655  else if(v.dimension() == 8)
6656  OperateHelperBinary<8, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6657  else if(v.dimension() == 9)
6658  OperateHelperBinary<9, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6659  else if(v.dimension() == 10)
6660  OperateHelperBinary<10, Functor, T1, T2, isConst, A, A>::operate(v, w, f, &v(0), &w(0));
6661  else {
6662  typename View<T1, false>::iterator itV = v.begin();
6663  typename View<T2, isConst>::const_iterator itW = w.begin();
6664  for(; itV.hasMore(); ++itV, ++itW) {
6665  Assert(MARRAY_NO_DEBUG || itW.hasMore());
6666  f(*itV, *itW);
6667  }
6668  Assert(MARRAY_NO_DEBUG || !itW.hasMore());
6669  }
6670  }
6671  }
6672 }
6673 
6674 template<class Functor, class T1, class A, class E, class T2>
6675 inline void operate
6676 (
6677  View<T1, false, A>& v,
6678  const ViewExpression<E, T2>& expression,
6679  Functor f
6680 )
6681 {
6682  const E& e = expression; // cast
6683  if(!MARRAY_NO_DEBUG) {
6684  Assert(v.size() != 0 && e.size() != 0);
6685  Assert(e.dimension() == v.dimension());
6686  if(v.dimension() == 0) {
6687  Assert(v.size() == 1 && e.size() == 1);
6688  }
6689  else {
6690  for(size_t j=0; j<v.dimension(); ++j) {
6691  Assert(v.shape(j) == e.shape(j));
6692  }
6693  }
6694  }
6695  if(e.overlaps(v)) {
6696  Marray<T1, A> m(e); // temporary copy
6697  operate(v, m, f);
6698  }
6699  else if(v.dimension() == 0) {
6700  f(v[0], e[0]);
6701  }
6702  else if(v.isSimple() && e.isSimple()
6703  && v.coordinateOrder() == e.coordinateOrder()) {
6704  for(size_t j=0; j<v.size(); ++j) {
6705  f(v[j], e[j]);
6706  }
6707  }
6708  else {
6709  // loop unrolling does not improve performance here
6710  typename E::ExpressionIterator itE(e);
6711  size_t offsetV = 0;
6712  std::vector<size_t> coordinate(v.dimension());
6713  size_t maxDimension = v.dimension() - 1;
6714  for(;;) {
6715  f(v[offsetV], *itE);
6716  for(size_t j=0; j<v.dimension(); ++j) {
6717  if(coordinate[j]+1 == v.shape(j)) {
6718  if(j == maxDimension) {
6719  return;
6720  }
6721  else {
6722  offsetV -= coordinate[j] * v.strides(j);
6723  itE.resetCoordinate(j);
6724  coordinate[j] = 0;
6725  }
6726  }
6727  else {
6728  offsetV += v.strides(j);
6729  itE.incrementCoordinate(j);
6730  ++coordinate[j];
6731  break;
6732  }
6733  }
6734  }
6735  }
6736 }
6737 
6738 } // namespace marray_detail
6739 // \endcond suppress doxygen
6740 
6741 } // namespace marray
6742 
6743 #endif // #ifndef MARRAY_HXX
6744 
View< T, isConst, A > & operator=(const T &)
Assignment.
Definition: marray.hxx:1925
void assign(const allocator_type &=allocator_type())
Clear Marray.
Definition: marray.hxx:3350
View< T, isConst, A > squeezedView() const
Get a View where all singleton dimensions have been removed by setting their coordinates to zero...
Definition: marray.hxx:2454
Marray< T, A > base
Definition: marray.hxx:633
const size_t * stridesBegin() const
Get a constant iterator to the beginning of the strides vector.
Definition: marray.hxx:1788
base::const_pointer const_pointer
Definition: marray.hxx:693
static const bool Const
Flag to be used with the template parameter isConst of View and Iterator.
Definition: marray.hxx:26
const T & const_reference
Definition: marray.hxx:214
base::const_reverse_iterator const_reverse_iterator
Definition: marray.hxx:559
const T & operator()(const size_t c0, const size_t c1, const size_t c2) const
Definition: marray.hxx:5348
STL-compliant random access iterator for View and Marray.
Definition: marray.hxx:49
static const CoordinateOrder defaultOrder
Default order of coordinate tuples.
Definition: marray.hxx:28
A::template rebind< value_type >::other allocator_type
Definition: marray.hxx:560
Marray(const allocator_type &=allocator_type())
Empty constructor.
Definition: marray.hxx:3369
View< T, false, A > base
Definition: marray.hxx:550
Runtime-flexible multi-dimensional views and arrays.
Definition: marray.hxx:20
base::reverse_iterator reverse_iterator
Definition: marray.hxx:640
void view(BaseIterator, ShapeIterator, View< T, isConst, A > &) const
Get a sub-view with the same coordinate order.
Definition: marray.hxx:1987
const size_t * shapeEnd() const
Definition: marray.hxx:5334
Iterator< T, isConst, A > iterator
Definition: marray.hxx:215
Iterator< T, true, A > const_iterator
Definition: marray.hxx:216
void permute(CoordinateIterator)
Permute dimensions.
Definition: marray.hxx:2493
base::value_type value_type
Definition: marray.hxx:690
const T * const_pointer
Definition: marray.hxx:212
iterator end()
Get the end-iterator.
Definition: marray.hxx:2727
Flag to indicate initialization skipping.
Definition: marray.hxx:24
const size_t shape(const size_t) const
Get the shape in one dimension.
Definition: marray.hxx:1725
Marray< T, A > & operator=(const T &)
Assignment.
Definition: marray.hxx:3764
base::pointer pointer
Definition: marray.hxx:552
const T & operator()(Accessor it) const
Definition: marray.hxx:5344
void reshape(const size_t)
Reshape.
Definition: marray.hxx:4897
marray_detail::IfBool< isConst, const T &, T & >::type reference
Definition: marray.hxx:213
void indexToCoordinates(size_t, CoordinateIterator) const
Compute the coordinate sequence that corresponds to an index.
Definition: marray.hxx:832
reverse_iterator rbegin()
Get a reserve iterator to the beginning.
Definition: marray.hxx:2767
Iterator< T, isConst, A > & operator-=(const difference_type &)
Definition: marray.hxx:4293
STL namespace.
Iterator< T, isConst, A > operator+(const difference_type &) const
Definition: marray.hxx:4464
base::reverse_iterator reverse_iterator
Definition: marray.hxx:697
View< T, isConst, A > shiftedView(const int) const
Get a View which dimensions cycle shifted.
Definition: marray.hxx:2697
Array-Interface to an interval of memory.
Definition: marray.hxx:44
const bool isSimple() const
Definition: marray.hxx:5341
base::iterator iterator
Definition: marray.hxx:696
void coordinatesToIndex(CoordinateIterator, size_t &) const
Compute the index that corresponds to a sequence of coordinates.
Definition: marray.hxx:766
void resize(const size_t, const size_t, const T &=T())
Resize (existing entries are preserved, new entries are initialized).
Definition: marray.hxx:5245
std::random_access_iterator_tag iterator_category
Definition: marray.hxx:477
Matrix< T, A > & operator=(const T &)
Assignment.
Definition: marray.hxx:5149
base::const_pointer const_pointer
Definition: marray.hxx:636
base::const_iterator const_iterator
Definition: marray.hxx:558
Matrix(const allocator_type &=allocator_type())
Empty constructor.
Definition: marray.hxx:4996
const size_t * shapeBegin() const
Definition: marray.hxx:5332
One-dimensional Marray.
Definition: marray.hxx:50
const bool MARRAY_NO_DEBUG
General assertion testing enabled.
Definition: marray.hxx:59
base::pointer pointer
Definition: marray.hxx:691
void indexToOffset(size_t, size_t &) const
Compute the offset that corresponds to an index.
Definition: marray.hxx:872
void reshape(const size_t, const size_t)
Reshape.
Definition: marray.hxx:5296
#define MARRAY_BINARY_OPERATOR_ALL_TYPES(op, functorname)
Definition: marray.hxx:3319
base::reference reference
Definition: marray.hxx:694
iterator begin()
Get an iterator to the beginning.
Definition: marray.hxx:2714
base::value_type value_type
Definition: marray.hxx:634
#define MARRAY_UNARY_OPERATOR_ALL_TYPES(op, functorname)
Definition: marray.hxx:3203
bool overlaps(const View< TLocal, isConstLocal, ALocal > &) const
Check whether two Views overlap.
Definition: marray.hxx:2930
const CoordinateOrder & coordinateOrder() const
Definition: marray.hxx:5339
base::allocator_type allocator_type
Definition: marray.hxx:700
friend class View
Definition: marray.hxx:438
bool operator>(const Iterator< T, isConstLocal, A > &) const
Definition: marray.hxx:4545
void coordinatesToOffset(CoordinateIterator, size_t &) const
Compute the offset that corresponds to a sequence of coordinates.
Definition: marray.hxx:808
size_t index() const
Get the corresponding index in the View.
Definition: marray.hxx:4598
Iterator< T, isConst, A > & operator--()
Prefix decrement.
Definition: marray.hxx:4379
base::const_reverse_iterator const_reverse_iterator
Definition: marray.hxx:699
const BinaryViewExpression< E1, T1, E2, T2, marray_detail::Times< T1, T2, typename marray_detail::PromoteType< T1, T2 >::type > > operator*(const ViewExpression< E1, T1 > &expression1, const ViewExpression< E2, T2 > &expression2)
Definition: marray.hxx:3251
std::string asString(const StringStyle &=MatrixStyle) const
Output as string.
Definition: marray.hxx:2960
std::ptrdiff_t difference_type
Definition: marray.hxx:479
void constView(BaseIterator, ShapeIterator, View< T, true, A > &) const
Get a sub-view to constant data with the same coordinate order.
Definition: marray.hxx:2084
const size_t dimension() const
Get the dimension.
Definition: marray.hxx:1711
A::template rebind< value_type >::other allocator_type
Definition: marray.hxx:220
marray_detail::IfBool< isConst, const T *, T * >::type pointer
Definition: marray.hxx:211
const bool MARRAY_NO_ARG_TEST
Argument testing enabled.
Definition: marray.hxx:60
void reshape(ShapeIterator, ShapeIterator)
Reshape the View.
Definition: marray.hxx:2275
View< T, isConst, A > boundView(const size_t, const size_t=0) const
Get a View where one coordinate is bound to a value.
Definition: marray.hxx:2374
const T & operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3, const size_t c4) const
Definition: marray.hxx:5352
ViewExpression< View< T, isConst, A >, T > base
Definition: marray.hxx:219
base::iterator iterator
Definition: marray.hxx:556
base::const_iterator const_iterator
Definition: marray.hxx:698
Two-dimensional Marray.
Definition: marray.hxx:51
bool operator!=(const Iterator< T, isConstLocal, A > &) const
Definition: marray.hxx:4517
Vector(const allocator_type &=allocator_type())
Empty constructor.
Definition: marray.hxx:4637
marray_detail::IfBool< isConst, const View< T, true, A > *, View< T, false, A > * >::type view_pointer
Definition: marray.hxx:485
const size_t strides(const size_t) const
Get the strides in one dimension.
Definition: marray.hxx:1771
Marray< T, A > base
Definition: marray.hxx:688
View< T, isConst, A > permutedView(CoordinateIterator) const
Get a View with permuted dimensions.
Definition: marray.hxx:2540
void coordinate(CoordinateIterator) const
Get the corresponding coordinate sequence in the View.
Definition: marray.hxx:4612
base::const_reverse_iterator const_reverse_iterator
Definition: marray.hxx:642
CoordinateOrder
Definition: marray.hxx:23
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698
marray_detail::IfBool< isConst, const T &, T & >::type reference
Definition: marray.hxx:481
bool hasMore() const
Fast alternative to comparing with the end iterator.
Definition: marray.hxx:4586
void shift(const int)
Cycle shift dimensions.
Definition: marray.hxx:2665
const T & operator()(const size_t c0, const size_t c1) const
Definition: marray.hxx:5346
reference operator*() const
De-reference.
Definition: marray.hxx:4220
base::reference reference
Definition: marray.hxx:554
base::pointer pointer
Definition: marray.hxx:635
void transpose()
Reverse dimensions.
Definition: marray.hxx:2597
const size_t shape(const size_t j) const
Definition: marray.hxx:5330
base::const_reference const_reference
Definition: marray.hxx:638
const size_t dimension() const
Definition: marray.hxx:5326
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: marray.hxx:218
bool overlaps(const View< Tv, isConst, A > &v) const
Definition: marray.hxx:5337
~Marray()
Destructor.
Definition: marray.hxx:3615
marray_detail::IfBool< isConst, const T *, T * >::type pointer
Definition: marray.hxx:480
base::allocator_type allocator_type
Definition: marray.hxx:643
marray_detail::IfBool< isConst, const View< T, true, A > &, View< T, false, A > & >::type view_reference
Definition: marray.hxx:487
void squeeze()
Remove singleton dimensions by setting their coordinates to zero.
Definition: marray.hxx:2414
std::reverse_iterator< iterator > reverse_iterator
Definition: marray.hxx:217
base::iterator iterator
Definition: marray.hxx:639
void resize(const size_t, const T &=T())
Resize (existing entries are preserved, new entries are initialized).
Definition: marray.hxx:4912
base::reference reference
Definition: marray.hxx:637
Runtime-flexible multi-dimensional array.
Definition: marray.hxx:52
pointer operator->() const
Pointer.
Definition: marray.hxx:4230
base::value_type value_type
Definition: marray.hxx:551
const size_t * stridesEnd() const
Get a constant iterator to the end of the strides vector.
Definition: marray.hxx:1802
const size_t size() const
Definition: marray.hxx:5328
const T & operator[](const size_t offset) const
Definition: marray.hxx:5354
const bool isSimple() const
Determine whether the shape strides equal the strides of the View.
Definition: marray.hxx:1827
base::const_iterator const_iterator
Definition: marray.hxx:641
View< T, isConst, A > transposedView() const
Get a View with dimensions reversed.
Definition: marray.hxx:2649
Vector< T, A > & operator=(const T &)
Assignment.
Definition: marray.hxx:4796
static const bool Mutable
Flag to be used with the template parameter isConst of View and Iterator.
Definition: marray.hxx:27
reverse_iterator rend()
Get the reverse end-iterator.
Definition: marray.hxx:2779
base::const_pointer const_pointer
Definition: marray.hxx:553
base::reverse_iterator reverse_iterator
Definition: marray.hxx:557
Iterator< T, isConst, A > & operator+=(const difference_type &)
Definition: marray.hxx:4252
Iterator< T, isConst, A > operator-(const difference_type &) const
Definition: marray.hxx:4477
Iterator< T, isConst, A > & operator++()
Prefix increment.
Definition: marray.hxx:4315
static const InitializationSkipping SkipInitialization
Flag to indicate initialization skipping.
Definition: marray.hxx:29
reference operator()(U)
Reference data.
Definition: marray.hxx:1245
const size_t * shapeEnd() const
Get a constant iterator to the end of the shape vector.
Definition: marray.hxx:1756
base::const_reference const_reference
Definition: marray.hxx:555
View< T, isConst, A > reshapedView(ShapeIterator, ShapeIterator) const
Get a reshaped View.
Definition: marray.hxx:2307
const size_t * shapeBegin() const
Get a constant iterator to the beginning of the shape vector.
Definition: marray.hxx:1742
const CoordinateOrder & coordinateOrder() const
Get the coordinate order used for scalar indexing and iterators.
Definition: marray.hxx:1815
T & operator[](const size_t)
Element access.
Definition: marray.hxx:4955
void resize(ShapeIterator, ShapeIterator, const T &=T())
Resize (existing entries are preserved, new entries are initialized).
Definition: marray.hxx:3886
reference operator[](const size_t) const
Element access.
Definition: marray.hxx:4241
StringStyle
Definition: marray.hxx:22
Iterator()
Empty constructor.
Definition: marray.hxx:4031
bool operator==(const Iterator< T, isConstLocal, A > &) const
Definition: marray.hxx:4504
bool operator>=(const Iterator< T, isConstLocal, A > &) const
Definition: marray.hxx:4571
base::const_reference const_reference
Definition: marray.hxx:695
const T & operator()(const size_t c0, const size_t c1, const size_t c2, const size_t c3) const
Definition: marray.hxx:5350
void assign(const allocator_type &=allocator_type())
Clear View.
Definition: marray.hxx:1105