C++QEDCore  v2 Milestone 10
a framework for simulating open quantum dynamics – core
BlitzArraySliceIterator.h
Go to the documentation of this file.
1 // Copyright András Vukics 2006–2014. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt)
2 // -*- C++ -*-
4 #ifndef CPPQEDCORE_UTILS_BLITZARRAYSLICEITERATOR_H_INCLUDED
5 #define CPPQEDCORE_UTILS_BLITZARRAYSLICEITERATOR_H_INCLUDED
6 
7 #include "BlitzArraySliceIteratorFwd.h"
8 
9 #include "BlitzArrayTraits.h"
10 #include "MultiIndexIterator.h"
11 #include "TMP_Tools.h"
12 
13 #include "Exception.h"
14 
15 #include <boost/mpl/size.hpp>
16 #include <boost/mpl/sort.hpp>
17 #include <boost/mpl/unique.hpp>
18 #include <boost/mpl/max_element.hpp>
19 
20 #include <boost/range.hpp>
21 
22 #include <list>
23 
24 
25 
26 namespace blitzplusplus {
27 
28 
29 using cpputils::Rank;
30 
31 
33 namespace basi {
34 
36 template <typename V> struct Size : boost::mpl::size<V> {};
37 
39 namespace ttd {
40 
41 template <int RANK, bool IS_CONST> using ConditionalConstCArray=typename tmptools::ConditionalAddConst<CArray<RANK>,IS_CONST>::type;
42 
43 template <typename V> using ResCArray=CArray<Size<V>::value>;
44 
45 template <typename V, bool IS_CONST> using ConditionalConstResCArray=ConditionalConstCArray<Size<V>::value,IS_CONST>;
46 
47 template <typename I, typename V, bool IS_CONST> using ForwardIteratorHelper=boost::forward_iterator_helper<I,ConditionalConstResCArray<V,IS_CONST> >;
48 
49 template <int RANK, typename V> using VecIdxTiny=IdxTiny<RANK-Size<V>::value>;
50 // note that Array::lbound and ubound return a TinyVector<int,...>, so that here we have to use int as well.
51 
52 }
53 
54 using cpputils::mii::Begin; using cpputils::mii::End;
55 
56 
58 
66 template<int RANK, typename V> struct ConsistencyChecker
67 {
68  static_assert( RANK >= Size<V>::value , "Indexer with nonpositive RANK." );
69 
70  typedef typename boost::mpl::sort<V>::type SortedV;
71  static_assert( boost::mpl::equal<typename boost::mpl::unique<SortedV,boost::is_same<boost::mpl::_1,boost::mpl::_2> >::type,SortedV>::value , "basi::Iterator inconsistent vector" );
72  static_assert( boost::mpl::deref<typename boost::mpl::max_element<V>::type>::type::value < RANK , "basi::Iterator vector out of range" );
73 };
74 
75 
77 template<int RANK, int I1, int I2> struct ConsistencyChecker<RANK,boost::mpl::range_c<int,I1,I2> > { static_assert( I1>=0 && I2<RANK , "basi::Iterator vector out of range" ); };
78 
80 template<int RANK, int N, int Nbeg> struct ConsistencyChecker<RANK,tmptools::Range<N,Nbeg> > : private ConsistencyChecker<RANK,boost::mpl::range_c<int,Nbeg,Nbeg+N> > {};
81 template<int RANK, int N> struct ConsistencyChecker<RANK,tmptools::Ordinals<N> > : private ConsistencyChecker<RANK,tmptools:: Range <N,0> > {};
86 
96 template<int RANK, typename V>
97 const ttd::VecIdxTiny<RANK,V>
98 filterOut(const IdxTiny<RANK>& idx);
99 
100 
101 
103 //
104 // The essential part of the work
105 //
107 
108 
128 template<int RANK>
131 
133 template<int RANK, typename V>
135 {
136 public:
138 
160  static
161  CArray<RANK>&
164 
165 };
166 
167 #pragma GCC diagnostic push
168 #pragma GCC diagnostic ignored "-Wunused-parameter"
169 
171 template<int RANK, typename V>
172 class Indexer : public Transposer<RANK,V>
173 {
174 public:
176 
199  static
200  ttd::ResCArray<V>&
202  ttd::ResCArray<V>& resArray,
203  const ttd::VecIdxTiny<RANK,V>& idx
204  )
206 
207 };
208 
209 #pragma GCC diagnostic pop
210 
214 //
216 // BlitzArraySliceIterator
217 //
219 
220 // Think over: is the following solution based on inheritance to solve the specialization problem optimal? Note: this is NOT allowed (specialization depending on a template parameter)
221 // template<typename V, bool IS_CONST> Iterator<Size<V>::value,V,IS_CONST>;
222 
223 namespace details {
224 
225 template<typename, bool>
226 class BaseTrivial;
227 
228 template<typename, bool>
229 class BaseSpecial;
230 
231 template<int, typename, bool>
232 class Base;
233 
234 } // details
235 
236 #define BASE_class boost::mpl::if_c<RANK==1,\
237  details::BaseTrivial<V,IS_CONST>,\
238  typename boost::mpl::if_c<RANK==Size<V>::value,\
239  details::BaseSpecial<V,IS_CONST>,\
240  details::Base<RANK,V,IS_CONST>\
241  >::type\
242  >::type
243 
245 
296 template<int RANK, typename V, bool IS_CONST>
297 class Iterator
298  : public ttd::ForwardIteratorHelper<Iterator<RANK,V,IS_CONST>,V,IS_CONST>, // The inheritance has to be public here because of types necessary to inherit
299  public BASE_class,
300  private ConsistencyChecker<RANK,V>
301 {
302 public:
303  typedef typename BASE_class Base;
304 
305 #undef BASE_class
306 
307  typedef typename Base::CcCA CcCA;
308 
309  typedef boost::iterator_range<Iterator> Range;
310 
311  Iterator& operator++() {Base::increment(); return *this;}
312 
314 
315  template<bool IS_END>
316  Iterator(CcCA& array, boost::mpl::bool_<IS_END> isEnd) : Base(array,isEnd) {}
317 
318 };
319 
320 
321 #define NS_NAME basi
322 #define RETURN_type1(IS_CONST) Iterator<Rank<A>::value,V_S,IS_CONST>
323 #define ADDITIONAL_PARAMETER
324 #define ADDITIONAL_ARGUMENT
325 
326 #include "details_BlitzArraySliceIteratorReentrant.h"
327 
328 namespace details {
329 
331 //
332 // Base
333 //
335 
337 template<int RANK, typename V, bool IS_CONST>
338 class Base : public Indexer<RANK,V>
339 {
340 public:
341  typedef CArray<RANK> CA ;
342  typedef ttd::ConditionalConstCArray<RANK,IS_CONST> CcCA ;
343  typedef ttd::ResCArray<V> CARes;
344  typedef ttd::ConditionalConstResCArray<V,IS_CONST> CcCARes;
345 
346  typedef ttd::VecIdxTiny<RANK,V> VecIdxTiny;
347 
348  static const int RANKIDX=RANK-Size<V>::value;
349 
351 
352  Base(CcCA&, Begin); // if it's not the end, it's the beginning
353  Base(CcCA&, End );
354 
355  void increment() {++impl_;}
356 
357  CcCARes& operator*() const {return Indexer<RANK,V>::index(array_,arrayRes_,*impl_);}
358  // This has to return a reference, cf eg. ElementLiovillean::JumpStrategy takes its argument as a non-const reference. Or, it has to take a copy there...
359 
360  friend bool operator==(const Base& i1, const Base& i2) {return i1.impl_==i2.impl_ /* && i1.array_==i2.array_ */;}
361  // The user has to ensure that the two arrays are actually the same
362 
363  const Impl& operator()() const {return impl_;}
364 
365 private:
366  template<bool TAG>
367  static Impl ctorHelper(CcCA&);
368 
369  mutable CA array_;
370  // By value, so that the necessary transposition specified by V can be readily performed. In this case, however, neither stored array can ever be const.
371 
372  mutable CARes arrayRes_;
373 
374  Impl impl_;
375 
376 };
377 
378 
380 //
381 // BaseTrivial
382 //
384 
385 class OutOfRange : public cpputils::Exception {};
386 
387 
389 template<typename V, bool IS_CONST>
390 class BaseTrivial
391 {
392 public:
393  static const int RANK=Size<V>::value;
394 
395  typedef CArray<RANK> CA;
396  typedef ttd::ConditionalConstCArray<RANK,IS_CONST> CcCA;
397 
398  BaseTrivial(CcCA&, Begin); // if it's not the end, it's the beginning
399  BaseTrivial(CcCA&, End );
400 
401  void increment() {if (!isEnd_) isEnd_=true; else throw OutOfRange();}
402 
403  CcCA& operator*() const {if (isEnd_) throw OutOfRange(); return array_;}
404 
405  friend bool operator==(const BaseTrivial& i1, const BaseTrivial& i2) {return i1.isEnd_==i2.isEnd_;}
406 
407 protected:
408  mutable CA array_;
409 
410 private:
411  bool isEnd_;
412 
413 };
414 
416 //
417 // BaseSpecial
418 //
420 
422 template<typename V, bool IS_CONST>
423 class BaseSpecial : public BaseTrivial<V,IS_CONST>
424 {
425 public:
426  typedef typename BaseTrivial<V,IS_CONST>::CcCA CcCA;
427 
428  BaseSpecial(CcCA&, Begin); // if it's not the end, it's the beginning
429  BaseSpecial(CcCA&, End );
430 
431 };
432 
433 } // details
434 
435 } // basi
436 
437 
438 
440 
453 template<int RANK, typename V>
455 {
456 public:
457  typedef std::list<ptrdiff_t> Impl;
458 
459  friend class basi_fast::Iterator<RANK,V, true>;
460  friend class basi_fast::Iterator<RANK,V,false>;
461 
463 
464  SlicesData(const CArray<RANK>& array);
465 
466 private:
467  static const Impl ctorHelper(const CArray<RANK>&);
468 
469  const Impl firstOffsets_;
470 
471  const blitz::TinyVector<int ,basi::Size<V>::value> shape_;
472  const blitz::TinyVector<ptrdiff_t,basi::Size<V>::value> stride_;
473 
474  const blitz::GeneralArrayStorage<basi::Size<V>::value> storage_;
475 
476 };
477 
478 
479 
481 namespace basi_fast {
482 
484 
492 template<int RANK, typename V, bool IS_CONST>
493 class Iterator
494  : public basi::ttd::ForwardIteratorHelper<Iterator<RANK,V,IS_CONST>,V,IS_CONST>
495 {
496 public:
497  typedef basi::ttd::ConditionalConstCArray<RANK,IS_CONST> CcCA ;
498  typedef basi::ttd::ResCArray<V> CARes;
499  typedef basi::ttd::ConditionalConstResCArray<V,IS_CONST> CcCARes;
500 
501  typedef boost::iterator_range<Iterator> Range;
502 
503  Iterator& operator++() {++iter_; return *this;}
504 
505  CcCARes& operator*() const
506  {
507  arrayRes_.reference(CARes(arrayData_+*iter_,slicesData_.shape_,slicesData_.stride_,blitz::neverDeleteData,slicesData_.storage_));
508  return arrayRes_;
509  }
510 
511  friend bool operator==(const Iterator& i1, const Iterator& i2) {return i1.iter_==i2.iter_;}
512 
513  template<bool IS_END>
514  Iterator(CcCA& array, const SlicesData<RANK,V>&, boost::mpl::bool_<IS_END> b);
515 
516 private:
518 
519  mutable CARes arrayRes_;
520 
521  dcomp*const arrayData_;
522  // This can be non_const because the constructor and the dereferencing operator will anyway ensure const-correctness
523 
524  const SlicesData<RANK,V>& slicesData_;
525 
526 };
527 
528 
529 
530 #define NS_NAME basi_fast
531 #define RETURN_type1(IS_CONST) Iterator<Rank<A>::value,V_S,IS_CONST>
532 #define ADDITIONAL_PARAMETER , sd
533 #define ADDITIONAL_ARGUMENT , const SlicesData<Rank<A>::value,V_S>& sd
534 
535 #include "details_BlitzArraySliceIteratorReentrant.h"
536 
537 
538 } // basi_fast
539 
540 
541 namespace basi {
542 
544 
545 template<typename V, typename A>
546 const Iterator<Rank<A>::value,V,false>
547 begin( A& array );
548 
550 template<typename V, typename A>
551 const Iterator<Rank<A>::value,V,false>
552 end ( A& array );
553 
555 
556 template<typename V, typename A>
557 const Iterator<Rank<A>::value,V,true>
558 begin(const A& array );
559 
561 template<typename V, typename A>
562 const Iterator<Rank<A>::value,V,true>
563 end (const A& array );
564 
566 
570 template<typename V, typename A>
571 const boost::iterator_range<Iterator<Rank<A>::value,V,false> >
572 fullRange( A& array );
573 
575 template<typename V, typename A>
576 const boost::iterator_range<Iterator<Rank<A>::value,V,true> >
577 fullRange(const A& array );
578 
579 } // basi
580 
581 namespace basi_fast {
582 
584 template<typename V, typename A>
585 const Iterator<Rank<A>::value,V,false>
586 begin( A& array , const SlicesData<Rank<A>::value,V>& sd);
587 
589 template<typename V, typename A>
590 const Iterator<Rank<A>::value,V,true>
591 begin(const A& array , const SlicesData<Rank<A>::value,V>& sd);
592 
594 template<typename V, typename A>
595 const Iterator<Rank<A>::value,V,false>
596 end ( A& array , const SlicesData<Rank<A>::value,V>& sd);
597 
599 template<typename V, typename A>
600 const Iterator<Rank<A>::value,V,true>
601 end (const A& array , const SlicesData<Rank<A>::value,V>& sd);
602 
604 template<typename V, typename A>
605 const boost::iterator_range<Iterator<Rank<A>::value,V,true> >
606 fullRange(const A& array , const SlicesData<Rank<A>::value,V>& sd);
607 
609 template<typename V, typename A>
610 const boost::iterator_range<Iterator<Rank<A>::value,V,false> >
611 fullRange( A& array , const SlicesData<Rank<A>::value,V>& sd);
612 
613 } // basi_fast
614 
615 
616 namespace basi {
617 
716 } // basi
717 
718 
719 } // blitzplusplus
720 
721 
722 
723 #endif // CPPQEDCORE_UTILS_BLITZARRAYSLICEITERATOR_H_INCLUDED
724 
725 
The class that is (meant to be, at least) the base of all exceptions in the framework.
Definition: Exception.h:18
Applies add_const if ADD_CONST = true.
Definition: TMP_Tools.h:62
blitz::TinyVector< ptrdiff_t, RANK > IdxTiny
A tiny vector used for indexing of objects of arbitrary arity.
Definition: BlitzTiny.h:32
A forwarding metafunction to boost::mpl::size.
blitz::Array< dcomp,RANK > CArray
A complex array of arbitrary arity.
Definition: BlitzArray.h:16
boost::iterator_range< Iterator > Range
Boost.Range-compliant range.
template metafunction for the rank (arity) of the multi-array A
Definition: ArrayTraits.h:15
Performs the slicing on an array already transposed by Transposer.
static CArray< RANK > & transpose(CArray< RANK > &)
Static worker.
Exception thrown if the partial specialization of Transposer or Indexer for the given RANK does not e...
Iterator & operator++()
For the ForwardIterator concept.
const ttd::VecIdxTiny< RANK, V > filterOut(const IdxTiny< RANK > &idx)
Filters out the indices corresponding to a subsystem.
Iterator(CcCA &array, boost::mpl::bool_< IS_END > isEnd)
Can be initialized either to the beginning or the end of the sequence of dummy-index combinations...
Class performing the “possible permutation” of the retained indices (cf. Synopsis).
An iterator over all possible combinations of indices (a number of integers) between certain bounds...
std::list< ptrdiff_t > Impl
Data structure for the sequence of slices.
“Fast” version of basi::Iterator relying on a pre-calculated set of slices stored by SlicesData ...
Checking the consistency of template arguments for use in slicing.
Defines class MultiIndexIterator and a few helpers.
Template metaprogramming tools.
Definition: TMP_Tools.h:51
Base::CcCA CcCA
ttd::ConditionalConstCArray
Template metaprogramming tools, extending (and based on) Boost.MPL.
std::complex< double > dcomp
Double-precision complex number.
static ttd::ResCArray< V > & index(CArray< RANK > &array, ttd::ResCArray< V > &resArray, const ttd::VecIdxTiny< RANK, V > &idx)
Static worker.
Contains data for pre-calculated slices for basi_fast::Iterator.
SlicesData(const CArray< RANK > &array)
Constructor from a reference array.
Comprises our own extensions to Blitz++.
Implementations of the traits functions declared in ArrayTraits.h for blitz::Array ...
Defines tentative base classes for the exception classes of the framework.