OSHUN  beta
Arbitrary Order Spherical-Harmonic 1D-3P Vlasov-Fokker-Planck-Maxwell code
lib-array.h
Go to the documentation of this file.
1 
51 //--------------------------------------------------------------
52 //--------------------------------------------------------------
53 
54 #ifndef ARRAY_LIBRARY_N_AXIS_H
55 #define ARRAY_LIBRARY_N_AXIS_H
56 
57 using namespace std;
58 
59 //**************************************************************
60 // Non-Constant Generalized Slice Iterator
61 //**************************************************************
62 //--------------------------------------------------------------
63 // forward Declarations to allow friend declarations
64 //--------------------------------------------------------------
65 template<class T> class GSlice_iter;
66 template<class T> bool operator==(const GSlice_iter<T>&, const GSlice_iter<T>&);
67 template<class T> bool operator!=(const GSlice_iter<T>&, const GSlice_iter<T>&);
68 template<class T> bool operator< (const GSlice_iter<T>&, const GSlice_iter<T>&);
69 //--------------------------------------------------------------
70 
71 //--------------------------------------------------------------
72 template<class T> class GSlice_iter : public iterator<forward_iterator_tag, T> {
73 //--------------------------------------------------------------
74 // Iterator definition Stroustrup p552-p553
75 // Generalized slice Stroustrup p677-p678
76 //--------------------------------------------------------------
77 private:
78  valarray<T>* v;
79  gslice gs;
80  size_t curr; // index of current element
81  valarray<size_t> gsizes;
82  T& ref(size_t i) const;
83 
84 public:
85  // Constructor
86  GSlice_iter(valarray<T>* vv,gslice gss);
87 
88  // Pointer to the end
89  GSlice_iter end() const {
90  GSlice_iter t = *this;
91  t.curr = gsizes[0];
92  return t;
93  }
94 
95  GSlice_iter& operator++() {++curr; return *this;} //prefix
96  GSlice_iter operator++(int) {GSlice_iter t = *this; ++curr; return t;} //postfix
97 
98  T& operator[](size_t i) {return ref(i);} // C style subscript
99  T& operator()(size_t i) {return ref(i);} // Fortran style subscript
100  T& operator*() {return ref(curr);} // Current element
101 
102  friend bool operator==<>(const GSlice_iter& p, const GSlice_iter& q);
103  friend bool operator!=<>(const GSlice_iter& p, const GSlice_iter& q);
104  friend bool operator< <>(const GSlice_iter& p, const GSlice_iter& q);
105 };
106 
107 //--------------------------------------------------------------
108 // Referencing this iterator
109 //--------------------------------------------------------------
110 template<class T>
111 T& GSlice_iter<T>::ref(size_t i) const {
112  size_t loc(0);
113  for (size_t ic = 0; ic < gsizes.size()-1; ++ic){
114  loc += (i/gsizes[ic+1]) * gs.stride()[ic];
115  i %= gsizes[ic+1];
116  }
117  loc += i * gs.stride()[gsizes.size()-1];
118  return (*v)[gs.start()+loc];
119 }
120 
121 //--------------------------------------------------------------
122 // Generalized slice iterator constructor
123 //--------------------------------------------------------------
124 template<class T>
125 GSlice_iter<T>::GSlice_iter(valarray<T>* vv,gslice gss) :
126  v(vv), gs(gss), curr(0), gsizes(gs.size()){
127  for (size_t ic(1); ic < gsizes.size(); ++ic) {
128  gsizes[gss.size().size()-ic-1] *= gsizes[gss.size().size()-ic];
129  }
130 }
131 
132 //--------------------------------------------------------------
133 // Comparison operators for this iterator:
134 //--------------------------------------------------------------
135 template<class T>
136 bool operator==(const GSlice_iter<T>& p, const GSlice_iter<T>& q){
137  size_t count(0);
138  if (p.curr==q.curr && p.gs.start() == q.gs.start())
139  while ( (p.gs.stride()[count] == p.gs.stride()[count])
140  && (p.gs.size()[count] == p.gs.size()[count] ))
141  if (count++ == q.gs.size().size()-1) return true;
142  return false;
143 }
144 
145 template<class T>
146 bool operator!=(const GSlice_iter<T>& p, const GSlice_iter<T>& q){
147  return !(p==q);
148 }
149 
150 template<class T>
151 bool operator< (const GSlice_iter<T>& p, const GSlice_iter<T>& q){
152  size_t count(0);
153  if (p.curr<q.curr && p.gs.start() == q.gs.start())
154  while ( (p.gs.stride()[count] == p.gs.stride()[count])
155  && (p.gs.size()[count] == p.gs.size()[count] ))
156  if (count++ == q.gs.size().size()-1) return true;
157  return false;
158 }
159 //--------------------------------------------------------------
160 
161 //**************************************************************
162 // Constant Generalized Slice Iterator
163 //**************************************************************
164 //--------------------------------------------------------------
165 // forward Declarations to allow friend declarations
166 //--------------------------------------------------------------
167 template<class T> class CGSlice_iter;
168 template<class T> bool operator==(const CGSlice_iter<T>&, const CGSlice_iter<T>&);
169 template<class T> bool operator!=(const CGSlice_iter<T>&, const CGSlice_iter<T>&);
170 template<class T> bool operator< (const CGSlice_iter<T>&, const CGSlice_iter<T>&);
171 //--------------------------------------------------------------
172 
173 //--------------------------------------------------------------
174 template<class T> class CGSlice_iter : public iterator<forward_iterator_tag, T,const T*, const T&> {
175 //--------------------------------------------------------------
176 // Iterator definition: Stroustrup p552-p553
177 // Generalized Slice: Stroustrup p677-p678yy
178 //--------------------------------------------------------------
179 private:
180  valarray<T>* v;
181  gslice gs;
182  size_t curr; // index of current element
183  valarray<size_t> gsizes;
184  const T& ref(size_t i) const;
185 
186 public:
187  // Constructor
188  CGSlice_iter(valarray<T>* vv,gslice gss);
189 
190  // Pointer to the end
191  CGSlice_iter end() const {
192  CGSlice_iter t = *this;
193  t.curr = gsizes[0];
194  return t;
195  }
196 
197  CGSlice_iter& operator++() {++curr; return *this;} //prefix
198  CGSlice_iter operator++(int) {CGSlice_iter t = *this; ++curr; return t;} //postfix
199 
200  const T& operator[](size_t i) const {return ref(i);} // C style subscript
201  const T& operator()(size_t i) const {return ref(i);} // Fortran style subscript
202  const T& operator*() const {return ref(curr);} // Current element
203 
204  friend bool operator==<>(const CGSlice_iter& p, const CGSlice_iter& q);
205  friend bool operator!=<>(const CGSlice_iter& p, const CGSlice_iter& q);
206  friend bool operator< <>(const CGSlice_iter& p, const CGSlice_iter& q);
207 };
208 
209 //--------------------------------------------------------------
210 // Referencing this iterator
211 //--------------------------------------------------------------
212 template<class T>
213 const T& CGSlice_iter<T>::ref(size_t i) const {
214  size_t loc(0);
215  for (size_t ic = 0; ic < gsizes.size()-1; ++ic){
216  loc += (i/gsizes[ic+1]) * gs.stride()[ic];
217  i %= gsizes[ic+1];
218  }
219  loc += i * gs.stride()[gsizes.size()-1];
220  return (*v)[gs.start()+loc];
221 }
222 
223 //--------------------------------------------------------------
224 // Generalized slice iterator constructor
225 //--------------------------------------------------------------
226 template<class T>
227 CGSlice_iter<T>::CGSlice_iter(valarray<T>* vv,gslice gss) :
228  v(vv), gs(gss), curr(0), gsizes(gs.size()){
229  for (int ic=1; ic < gsizes.size(); ++ic) {
230  gsizes[gss.size().size()-ic-1] *= gsizes[gss.size().size()-ic];
231  }
232 }
233 
234 //--------------------------------------------------------------
235 // Comparison operators for this iterator:
236 //--------------------------------------------------------------
237 template<class T>
238 bool operator==(const CGSlice_iter<T>& p, const CGSlice_iter<T>& q){
239  size_t count(0);
240  if (p.curr==q.curr && p.gs.start() == q.gs.start())
241  while ( (p.gs.stride()[count] == p.gs.stride()[count])
242  && (p.gs.size()[count] == p.gs.size()[count] ))
243  if (count++ == q.gs.size().size()-1) return true;
244  return false;
245 }
246 
247 template<class T>
248 bool operator!=(const CGSlice_iter<T>& p, const CGSlice_iter<T>& q){
249  return !(p==q);
250 }
251 
252 template<class T>
253 bool operator< (const CGSlice_iter<T>& p, const CGSlice_iter<T>& q){
254  size_t count(0);
255  if (p.curr<q.curr && p.gs.start() == q.gs.start())
256  while ( (p.gs.stride()[count] == p.gs.stride()[count])
257  && (p.gs.size()[count] == p.gs.size()[count] ))
258  if (count++ == q.gs.size().size()-1) return true;
259  return false;
260 }
261 //--------------------------------------------------------------
262 //**************************************************************
263 
264 /**************************************************************
265  * 2D Array Class
266  *
267  * Using Stroustrup's matrices p672-p673
268  * This container is similar to Fortran-style arrays.
269  * Custom operations, no standard Matrix algebra.
270  * No error-checking.
271  * Compile with -ftree-vectorize
272  */
273 template<class T> class Array2D {
274 //--------------------------------------------------------------
275 // 2D Array decleration
276 //--------------------------------------------------------------
277 private:
278  valarray<T> *v;
279  size_t d1, d2; // for VFP: p, x
280 
281 public:
282 // Constructors/Destructors
283  Array2D(size_t x, size_t y);
284  Array2D(const Array2D& other);
285  ~Array2D();
286 
287 // Basic Info
288  size_t dim() const {return d1*d2;}
289  size_t dim1() const {return d1;}
290  size_t dim2() const {return d2;}
291  valarray<T>& array() const {return *v;}
292 
293 // Access
294  T& operator()(size_t i, size_t j); // Fortran-style
295  T operator()(size_t i, size_t j) const;
296  T& operator()(size_t i); // 1D-style
297  T operator()(size_t i) const;
298  vector<T> d2c(size_t j);
299 
300 // Slice iterators
301  GSlice_iter<T> d1c(size_t b, size_t e); // b: beginning, e: end (non-contiguous)
302  GSlice_iter<T> d2c(size_t b, size_t e); // b: beginning, e: end (contiguous)
303  GSlice_iter<T> SubArray2D(size_t st, size_t nx, size_t ny); // st: starting cell
304 
305 // Constant slice iterators
306  CGSlice_iter<T> d2c(size_t b, size_t e) const;
307  CGSlice_iter<T> d1c(size_t b, size_t e) const;
308  CGSlice_iter<T> SubArray2D(size_t st, size_t nx, size_t ny) const;
309 
310 // Operators
311  Array2D& operator=(const T& d);
312  Array2D& operator=(const Array2D& other);
313  Array2D& operator*=(const T& d);
314  Array2D& operator*=(const Array2D& vmulti);
315  Array2D& operator+=(const T& d);
316  Array2D& operator+=(const Array2D& vadd);
317  Array2D& operator-=(const T& d);
318  Array2D& operator-=(const Array2D& vmin);
319 
320 // Array * Vector
321  Array2D& multid1(const valarray<T>& vmulti); // M*valarray(d1)
322  Array2D& multid2(const valarray<T>& vmulti); // M*valarray(d2)
323 
324 // Central difference
325  Array2D& Dd1(); // in the direction d1 (requires dim1() > 2)
326  Array2D& Dd2(); // in the direction d2 (requires dim2() > 2)
327 
328 // Filter first N-cells in d1 direction
329  Array2D& Filterd1(size_t N);
330 };
331 //--------------------------------------------------------------
332 
333 //--------------------------------------------------------------
334 // Constructor and Destructor
335 //--------------------------------------------------------------
336 // Constructor
337 template<class T> Array2D<T>:: Array2D(size_t x,size_t y) : d1(x), d2(y) {
338  v = new valarray<T>(d1*d2);
339 }
340 // Copy constructor
341 template<class T> Array2D<T>:: Array2D(const Array2D& other){
342  d1 = other.dim1();
343  d2 = other.dim2();
344  v = new valarray<T>(d1*d2);
345  (*v) = other.array();
346 }
347 // Destructor
348 template<class T> Array2D<T>:: ~Array2D(){
349  delete v;
350 }
351 
352 //--------------------------------------------------------------
353 // Access
354 //--------------------------------------------------------------
355 // Access Fortan-style
356 template<class T> inline T& Array2D<T>:: operator()(size_t i, size_t j){
357  return (*v)[i+j*d1];
358 }
359 // Constant access Fortan-style
360 template<class T> inline T Array2D<T>:: operator()(size_t i, size_t j) const {
361  return (*v)[i+j*d1];
362 }
363 // 1D style access
364 template<class T> inline T& Array2D<T>:: operator() (size_t i){
365  return (*v)[i];
366 }
367 // 1D style const access
368 template<class T> inline T Array2D<T>:: operator() (size_t i) const {
369  return (*v)[i];
370 }
371 // Consider Array2D a list of d2-vectors and multiply with vmulti
372 template<class T> vector<T> Array2D<T>::d2c(size_t j){
373  vector<T> d1vec(d1);
374  for (size_t i(0); i < d1; ++i ){
375  d1vec[i] = (*v)[i+j*d1];
376  }
377  return d1vec;
378 }
379 //--------------------------------------------------------------
380 // Slicers
381 //--------------------------------------------------------------
382 // slices for given d1 value range
383 template<class T>
384 inline GSlice_iter<T> Array2D<T>::d1c(size_t b, size_t e){
385  valarray<size_t> sz(2), str(2);
386  str[1] = d1; str[0] = 1;
387  sz[1] = d2; sz[0] = e-b+1;
388  return GSlice_iter<T>(v,gslice(b,sz,str));
389 }
390 // const slices for given d1 value range
391 template<class T>
392 inline CGSlice_iter<T> Array2D<T>::d1c(size_t b, size_t e) const{
393  valarray<size_t> sz(2), str(2);
394  str[1] = d1; str[0] = 1;
395  sz[1] = d2; sz[0] = e-b+1;
396  return CGSlice_iter<T>(v,gslice(b,sz,str));
397 }
398 // slices for given d2 value range
399 template<class T>
400 inline GSlice_iter<T> Array2D<T>::d2c(size_t b, size_t e){
401  valarray<size_t> sz(1), str(1); // sz --> size, str --> stride
402  str[0] = 1; sz[0] = (e-b+1)*d1;
403  return GSlice_iter<T>(v,gslice(b*d1,sz,str));
404 }
405 // const slices for given d2 value range
406 template<class T>
407 inline CGSlice_iter<T> Array2D<T>::d2c(size_t b, size_t e) const{
408  valarray<size_t> sz(1), str(1); // sz --> size, str --> stride
409  str[0] = 1; sz[0] = (e-b+1)*d1;
410  return CGSlice_iter<T>(v,gslice(b*d1,sz,str));
411 }
412 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
413 
414 // scan Subarray
415 template<class T>
416 inline GSlice_iter<T> Array2D<T>::SubArray2D(size_t st, size_t nx, size_t ny) {
417  valarray<size_t> sz(2), str(2);
418  str[1] = 1; str[0] = dim1();
419  sz[1] = nx; sz[0] = ny;
420  return GSlice_iter<T>(v,gslice(st,sz,str));
421 }
422 // scan const Subarray
423 template<class T>
424 inline CGSlice_iter<T> Array2D<T>::SubArray2D(size_t st, size_t nx, size_t ny) const{
425  valarray<size_t> sz(2), str(2);
426  str[1] = 1; str[0] = dim1();
427  sz[1] = nx; sz[0] = ny;
428  return CGSlice_iter<T>(v,gslice(st,sz,str));
429 }
430 
431 //--------------------------------------------------------------
432 // Operators
433 //--------------------------------------------------------------
434 // Copy assignment operator
435 template<class T> Array2D<T>& Array2D<T>::operator=(const T& d){
436  (*v) = d;
437  return *this;
438 }
439 template<class T> Array2D<T>& Array2D<T>::operator=(const Array2D& other){
440  if (this != &other) { //self-assignment
441  (*v) = other.array();
442  }
443  return *this;
444 }
445 
446 // *=
447 template<class T> Array2D<T>& Array2D<T>::operator*=(const T& d){
448  (*v) *=d;
449  return *this;
450 }
451 template<class T> Array2D<T>& Array2D<T>::operator*=(const Array2D& vmulti){
452  (*v) *= vmulti.array();
453  return *this;
454 }
455 
456 // +=
457 template<class T> Array2D<T>& Array2D<T>::operator+=(const T& d){
458  (*v) +=d;
459  return *this;
460 }
461 template<class T> Array2D<T>& Array2D<T>::operator+=(const Array2D& vadd){
462  (*v) += vadd.array();
463  return *this;
464 }
465 
466 // -=
467 template<class T> Array2D<T>& Array2D<T>::operator-=(const T& d){
468  (*v) -=d;
469  return *this;
470 }
471 template<class T> Array2D<T>& Array2D<T>::operator-=(const Array2D& vmin){
472  (*v) -= vmin.array();
473  return *this;
474 }
475 
476 //--------------------------------------------------------------
477 // Array2D * Vector
478 //--------------------------------------------------------------
479 // Consider Array2D a list of d1-vectors and multiply with vmulti
480 template<class T> Array2D<T>& Array2D<T>::multid1(const valarray<T>& vmulti){
481  for (size_t j(0); j< d1*d2; j+=d1 ){
482  for (size_t i(0); i< d1; ++i ){
483  (*v)[i+j] *= vmulti[i];
484  }
485  }
486  return *this;
487 }
488 
489 // Consider Array2D a list of d2-vectors and multiply with vmulti
490 template<class T> Array2D<T>& Array2D<T>::multid2(const valarray<T>& vmulti){
491  for (size_t j(0); j< d2; ++j ){
492  for (size_t i(j*d1); i< (j+1)*d1; ++i ){
493  (*v)[i] *= vmulti[j];
494  }
495  }
496  return *this;
497 }
498 //--------------------------------------------------------------
499 // Central difference
500 //--------------------------------------------------------------
501 // (minus) Central difference for contiguous elements
502 // Example: 0 4 8 12 16 -2 -2 -2 -2 -2
503 // 1 5 9 13 17 --> -2 -2 -2 -2 -2
504 // 2 6 10 14 18 -2 -2 -2 -2 -2
505 // 3 7 11 15 19 -2 -2 -2 -2 19
506 // Requires at least 3 elements in d1
507 template<class T> Array2D<T>& Array2D<T>::Dd1(){
508  for(long i(0); i< long(d1*d2)-2; ++i) {
509  (*v)[i] -= (*v)[i+2];
510  }
511  for(long i(d1*d2-3); i>-1; --i) {
512  (*v)[i+1] = (*v)[i];
513  }
514 
515 
516  // Array2D<T> temp(*this);
517 
518  // for (long i2(0); i2<long(d2);++i2){
519 
520 
521  // /// Second Order
522  // temp(0,i2) = 2.0*((*this)(0,i2)-(*this)(1,i2));
523 
524 
525 
526  // // temp(i1,1) = 1.0/12.0*((*this)(i1,4)-6.0*(*this)(i1,3)+18.0*(*this)(i1,2)-10.0*(*this)(i1,1)-3.0*(*this)(i1,0));
527 
528  // for (long i1(1); i1<long(d1)-1;++i1){
529  // // temp(i1,i2) = 1.0/12.0*(-(*this)(i1,i2+2)+8.0*(*this)(i1,i2+1)-8.0*(*this)(i1,i2-1)+(*this)(i1,i2-2));
530 
531  // /// Second Order
532  // temp(i1,i2) = (*this)(i1-1,i2) - (*this)(i1+1,i2);
533  // }
534 
535 
536 
537 
538  // // temp(i1,long(d2)-2) = 1.0/12.0*(3.0*(*this)(i1,long(d2)-1)+10.0*(*this)(i1,long(d2)-2)-18.0*(*this)(i1,long(d2)-3)+6.0*(*this)(i1,long(d2)-4)-(*this)(i1,long(d2)-5));
539  // // temp(i1,long(d2)-1) = (*this)(i1,long(d2)-1)-(*this)(i1,long(d2)-2);
540 
541  // /// Second Order
542  // temp(long(d1)-1,i2) = 2.0*((*this)(long(d1)-2,i2)-(*this)(long(d1)-1,i2));
543  // }
544 
545  // *this = temp;
546  return *this;
547 
548 }
549 
550 // (minus) Central difference for elements with distance d1 (row-wise)
551 // Example: 0 4 8 12 16 -8 -8 -8 -8 16
552 // 1 5 9 13 17 --> -8 -8 -8 -8 17
553 // 2 6 10 14 18 -8 -8 -8 -8 18
554 // 3 7 11 15 19 -8 -8 -8 -8 19
555 // Requires at least 3 elements in d2
556 template<class T> Array2D<T>& Array2D<T>::Dd2(){
557  // Array2D<T> temp(*this);
558 
559  // for (long i1(0); i1<long(d1);++i1){
560  // /// Second Order
561  // temp(i1,0) = 2.0*((*this)(i1,0)-(*this)(i1,1));
562  // // std::cout << "this(" << i1 << ")" << (*this)(i1,0) << "\n";
563  // // std::cout << "temp(" << i1 << ")" << temp(i1,0) << "\n";
564 
565  // // temp(i1,1) = 1.0/12.0*((*this)(i1,4)-6.0*(*this)(i1,3)+18.0*(*this)(i1,2)-10.0*(*this)(i1,1)-3.0*(*this)(i1,0));
566  // for (long i2(1); i2<long(d2)-1;++i2){
567  // // temp(i1,i2) = 1.0/12.0*(-(*this)(i1,i2+2)+8.0*(*this)(i1,i2+1)-8.0*(*this)(i1,i2-1)+(*this)(i1,i2-2));
568  // /// Second Order
569  // temp(i1,i2) = (*this)(i1,i2-1) - (*this)(i1,i2+1);
570  // // std::cout << "this(" << i1 << "," << i2 << ")" << (*this)(i1,i2) << "\n";
571  // }
572  // // temp(i1,long(d2)-2) = 1.0/12.0*(3.0*(*this)(i1,long(d2)-1)+10.0*(*this)(i1,long(d2)-2)-18.0*(*this)(i1,long(d2)-3)+6.0*(*this)(i1,long(d2)-4)-(*this)(i1,long(d2)-5));
573  // // temp(i1,long(d2)-1) = (*this)(i1,long(d2)-1)-(*this)(i1,long(d2)-2);
574  // /// Second Order
575  // temp(i1,long(d2)-1) = 2.0*((*this)(i1,long(d2)-2)-(*this)(i1,long(d2)-1));
576  // // std::cout << "this(" << i1 << "," << long(d2)-1 << ")" << (*this)(i1,long(d2)-1) << "\n";
577  // }
578 
579  // *this = temp;
580  // return *this;
581 
582 
585  // std::cout << "\n d1*d2-twod1 = " << long(d1*d2)-2*d1 << "\n";
586 
587  long twod1(2*d1);
588  for(long i(0); i< long(d1*d2)-twod1; ++i) {
589  // std::cout << "v[" << i << "] = " << (*v)[i]
590  // << ", v[" << i+twod1 << "] = " << (*v)[i+twod1] << "\n";
591 
592  (*v)[i] -= (*v)[i+twod1];
593  }
594 
595  for(long i(d1*d2-twod1-1); i>-1; --i) {
596  (*v)[i+d1] = (*v)[i];
597  }
598  return *this;
600 }
601 //--------------------------------------------------------------
602 
603 // Remove data for N cells from dimension 1
604 template<class T> Array2D<T>& Array2D<T>::Filterd1(size_t N) {
605  for (size_t j(0); j < d2; ++j ){
606  for (size_t i(j*d1); i< j*d1+N; ++i ){
607  (*v)[i] = 0.0;
608  }
609  }
610  return *this;
611 }
612 //--------------------------------------------------------------
613 //**************************************************************
614 
615 /**************************************************************
616  * 2D Array Complex Class
617  *
618  * Using Stroustrup's matrices p672-p673
619  * This container is similar to Fortran-style arrays.
620  * Custom operations, no standard Matrix algebra.
621  * No error-checking.
622  * Compile with -ftree-vectorize
623  */
624 template<class T> class Array2D_cmplx {
625 //--------------------------------------------------------------
626 // 2D Array decleration
627 //--------------------------------------------------------------
628 private:
629  valarray<T> *v;
630  size_t d1, d2; // for VFP: p, x
631  size_t td1;
632 
633 public:
634 // Constructors/Destructors
635  Array2D_cmplx(size_t x, size_t y);
636  Array2D_cmplx(const Array2D_cmplx& other);
637  ~Array2D_cmplx();
638 
639 // Basic Info
640  size_t dim() const {return d1*d2;}
641  size_t dim1() const {return d1;}
642  size_t dim2() const {return d2;}
643  valarray<T>& array() const {return *v;}
644 
645 // Access
646  T& operator[](size_t i); // 1D-style
647  T operator[](size_t i) const;
648 
649  T& real(size_t i,size_t j); // 1D-style
650  T real(size_t i, size_t j) const;
651  T& imag(size_t i,size_t j); // 1D-style
652  T imag(size_t i, size_t j) const;
653 
654 //TODO vector<T> d2c(size_t j);
655 
656 // Slice iterators
657  GSlice_iter<T> d1c(size_t b, size_t e); // b: beginning, e: end (non-contiguous)
658  GSlice_iter<T> d2c(size_t b, size_t e); // b: beginning, e: end (contiguous)
659  GSlice_iter<T> SubArray2D(size_t st, size_t nx, size_t ny); // st: starting cell
660 
661 // Constant slice iterators
662  CGSlice_iter<T> d2c(size_t b, size_t e) const;
663  CGSlice_iter<T> d1c(size_t b, size_t e) const;
664  CGSlice_iter<T> SubArray2D(size_t st, size_t nx, size_t ny) const;
665 
666 // Operators
667  Array2D_cmplx& operator=(const T& d);
668  Array2D_cmplx& operator=(const complex<T>& c);
669  Array2D_cmplx& operator=(const Array2D<T>& other);
670  Array2D_cmplx& operator=(const Array2D_cmplx& other);
671  Array2D_cmplx& operator*=(const T& d);
672  Array2D_cmplx& operator*=(const complex<T>& c);
673  Array2D_cmplx& operator*=(const Array2D<T>& vmulti);
674  Array2D_cmplx& operator*=(const Array2D_cmplx& vmulti);
675  Array2D_cmplx& operator+=(const T& d);
676  Array2D_cmplx& operator+=(const complex<T>& c);
677  Array2D_cmplx& operator+=(const Array2D<T>& vadd);
678  Array2D_cmplx& operator+=(const Array2D_cmplx& vadd);
679  Array2D_cmplx& operator-=(const T& d);
680  Array2D_cmplx& operator-=(const complex<T>& c);
681  Array2D_cmplx& operator-=(const Array2D<T>& vmin);
682  Array2D_cmplx& operator-=(const Array2D_cmplx& vmin);
683 
684 // Array * Vector
685  Array2D_cmplx& multid1(const valarray<T>& vmulti); // M*valarray(d1)
686  Array2D_cmplx& multid1(const valarray< complex<T> >& vmulti); // M*valarray(d1)
687  Array2D_cmplx& multid2(const valarray<T>& vmulti); // M*valarray(d2)
688  Array2D_cmplx& multid2(const valarray< complex<T> >& vmulti); // M*valarray(d2)
689 
690 // Central difference
691  Array2D_cmplx& Dd1(); // in the direction d1 (requires dim1() > 2)
692  Array2D_cmplx& Dd2(); // in the direction d2 (requires dim2() > 2)
693 
694 // Filter first N-cells in d1 direction
695  Array2D_cmplx& Filterd1(size_t N);
696 };
697 //--------------------------------------------------------------
698 
699 //--------------------------------------------------------------
700 // Constructor and Destructor
701 //--------------------------------------------------------------
702 // Constructor
703 template<class T> Array2D_cmplx<T>:: Array2D_cmplx(size_t x,size_t y) : d1(x), d2(y) {
704  td1 = 2*d1;
705  v = new valarray<T>(2*d1*d2);
706 }
707 // Copy constructor
708 template<class T> Array2D_cmplx<T>:: Array2D_cmplx(const Array2D_cmplx& other){
709  d1 = other.dim1();
710  d2 = other.dim2();
711  td1 = 2*d1;
712  v = new valarray<T>(2*d1*d2);
713  (*v) = other.array();
714 }
715 // Destructor
717  delete v;
718 }
719 
720 //--------------------------------------------------------------
721 // Access
722 //--------------------------------------------------------------
723 // 1D style access
724 template<class T> inline T& Array2D_cmplx<T>::operator[] (size_t i){
725  return (*v)[i];
726 }
727 // 1D style const access
728 template<class T> inline T Array2D_cmplx<T>::operator[] (size_t i) const {
729  return (*v)[i];
730 }
731 // Access real part by reference
732 template<class T> inline T& Array2D_cmplx<T>::real(size_t i,size_t j){
733  return (*v)[2*i+j*td1];
734 }
735 // Const access of real part
736 template<class T> inline T Array2D_cmplx<T>::real(size_t i,size_t j) const{
737  return (*v)[2*i+j*td1];
738 }
739 // access of imag part
740 template<class T> inline T& Array2D_cmplx<T>::imag(size_t i,size_t j){
741  return (*v)[2*i+1+j*td1];
742 }
743 // Const access of imag part
744 template<class T> inline T Array2D_cmplx<T>::imag(size_t i,size_t j) const{
745  return (*v)[2*i+1+j*td1];
746 }
747 //--------------------------------------------------------------
748 // Slicers
749 //--------------------------------------------------------------
750 // slices for given d1 value range
751 template<class T>
752 inline GSlice_iter<T> Array2D_cmplx<T>::d1c(size_t b, size_t e){
753  valarray<size_t> sz(3), str(3);
754  str[2] = 1, str[1] = td1; str[0] = 2;
755  sz[2] = 2, sz[1] = d2; sz[0] = e-b+1;
756  return GSlice_iter<T>(v,gslice(2*b,sz,str));
757 }
758 // const slices for given d1 value range
759 template<class T>
760 inline CGSlice_iter<T> Array2D_cmplx<T>::d1c(size_t b, size_t e) const{
761  valarray<size_t> sz(3), str(3);
762  str[2] = 1, str[1] = td1; str[0] = 2;
763  sz[2] = 2, sz[1] = d2; sz[0] = e-b+1;
764  return CGSlice_iter<T>(v,gslice(2*b,sz,str));
765 }
766 // slices for given d2 value range
767 template<class T>
768 inline GSlice_iter<T> Array2D_cmplx<T>::d2c(size_t b, size_t e){
769  valarray<size_t> sz(1), str(1); // sz --> size, str --> stride
770  str[0] = 1; sz[0] = (e-b+1)*td1;
771  return GSlice_iter<T>(v,gslice(b*td1,sz,str));
772 }
773 // const slices for given d2 value range
774 template<class T>
775 inline CGSlice_iter<T> Array2D_cmplx<T>::d2c(size_t b, size_t e) const{
776  valarray<size_t> sz(1), str(1); // sz --> size, str --> stride
777  str[0] = 1; sz[0] = (e-b+1)*td1;
778  return CGSlice_iter<T>(v,gslice(b*td1,sz,str));
779 }
780 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
781 
782 // scan Subarray
783 template<class T>
784 inline GSlice_iter<T> Array2D_cmplx<T>::SubArray2D(size_t st, size_t nx, size_t ny) {
785  valarray<size_t> sz(2), str(2);
786  str[1] = 1; str[0] = td1;
787  sz[1] = 2*nx; sz[0] = ny;
788  return GSlice_iter<T>(v,gslice(2*st,sz,str));
789 }
790 // scan const Subarray
791 template<class T>
792 inline CGSlice_iter<T> Array2D_cmplx<T>::SubArray2D(size_t st, size_t nx, size_t ny) const{
793  valarray<size_t> sz(2), str(2);
794  str[1] = 1; str[0] = td1;
795  sz[1] = 2*nx; sz[0] = ny;
796  return CGSlice_iter<T>(v,gslice(2*st,sz,str));
797 }
798 
799 
800 //--------------------------------------------------------------
801 // Operators
802 //--------------------------------------------------------------
803 // Copy assignment operator
804 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator=(const T& d){
805  for (size_t i(0); i< td1*d2; i+=2) {
806  (*v)[i] = d;
807  (*v)[i+1] = 0.0;
808  }
809  return *this;
810 }
811 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator=(const complex<T>& c){
812  for (size_t i(0); i< td1*d2; i+=2) {
813  (*v)[i] =c.real();
814  (*v)[i+1] =c.imag();
815  }
816  return *this;
817 }
818 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator=(const Array2D<T>& other){
819  for (size_t i(0); i< d1*d2; ++i) {
820  (*v)[2*i] = other.array()[i];
821  (*v)[2*i+1] = 0.0;
822  }
823  return *this;
824 }
826  if (this != &other) { //self-assignment
827  (*v) = other.array();
828  }
829  return *this;
830 }
831 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
832 
833 // *=
834 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator*=(const T& d){
835  (*v) *=d;
836  return *this;
837 }
838 // *=
839 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator*=(const complex<T>& c){
840  for (size_t i(0); i< td1*d2; i+=2) { // suppose v[i]+iv[i+1]=A+iB, c=a+ib
841  T vi((*v)[i]*c.imag());
842  (*v)[i] *= c.real(); // v[i] = Aa
843  (*v)[i] -= (*v)[i+1]*c.imag(); // v[i] = Aa - Bb
844  (*v)[i+1] *= c.real(); // v[i+1] = Ba
845  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
846  }
847  return *this;
848 }
849 // *=
850 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator*=(const Array2D<T>& vmulti){
851  for (size_t i(0); i< d1*d2; ++i) {
852  (*v)[2*i] *= vmulti.array()[i];
853  (*v)[2*i+1] *= vmulti.array()[i];
854  }
855  return *this;
856 }
857 // *=
859  for (size_t i(0); i< td1*d2; i+=2) { // suppose v[i]+iv[i+1]=A+iB, vmulti[i] + ivmulti[i+1] = a+ib
860  T vi((*v)[i] * vmulti.array()[i+1]);
861  (*v)[i] *= vmulti.array()[i]; // v[i] = Aa
862  (*v)[i] -= (*v)[i+1]*vmulti.array()[i+1]; // v[i] = Aa - Bb
863  (*v)[i+1] *= vmulti.array()[i]; // v[i+1] = Ba
864  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
865  }
866  return *this;
867 }
868 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
869 
870 // +=
871 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator+=(const T& d){
872  for (size_t i(0); i< td1*d2; i+=2) {
873  (*v)[i] +=d;
874  }
875  return *this;
876 }
877 // +=
878 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator+=(const complex<T>& c){
879  for (size_t i(0); i< td1*d2; i+=2) {
880  (*v)[i] +=c.real();
881  (*v)[i+1] +=c.imag();
882  }
883  return *this;
884 }
885 // +=
887  for (size_t i(0); i< d1*d2; ++i) {
888  (*v)[2*i] += vadd.array()[i];
889  }
890  return *this;
891 }
892 // +=
894  (*v) += vadd.array();
895  return *this;
896 }
897 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
898 
899 // -=
900 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator-=(const T& d){
901  for (size_t i(0); i< td1*d2; i+=2) {
902  (*v)[i] -=d;
903  }
904  return *this;
905 }
906 // -=
907 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::operator-=(const complex<T>& c){
908  for (size_t i(0); i< td1*d2; i+=2) {
909  (*v)[i] -=c.real();
910  (*v)[i+1] -=c.imag();
911  }
912  return *this;
913 }
914 // -=
916  for (size_t i(0); i< d1*d2; ++i) {
917  (*v)[2*i] -= vmin.array()[i];
918  }
919  return *this;
920 }
921 // -=
923  (*v) -= vmin.array();
924  return *this;
925 }
926 
927 //--------------------------------------------------------------
928 // Array2D * Vector
929 //--------------------------------------------------------------
930 // Consider Array2D a list of d1-vectors and multiply with vmulti
931 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::multid1(const valarray<T>& vmulti){
932  for (size_t j(0); j< td1*d2; j+= td1 ){
933  for (size_t i(0); i< d1; ++i ){
934  (*v)[2*i+j] *= vmulti[i];
935  (*v)[2*i+1+j] *= vmulti[i];
936  }
937  }
938  return *this;
939 }
940 // Consider Array2D a list of d1-vectors and multiply with vmulti
941 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::multid1(const valarray< complex<T> >& vmulti){
942  for (size_t j(0); j< td1*d2; j+= td1 ){
943  for (size_t i(0); i< d1; ++i ){
944  T vi((*v)[2*i+j]*vmulti[i].imag());
945  (*v)[2*i+j] *= vmulti[i].real(); // v[i] = Aa
946  (*v)[2*i+j] -= (*v)[2*i+1+j] * vmulti[i].imag(); // v[i] = Aa - Bb
947  (*v)[2*i+1+j] *= vmulti[i].real(); // v[i+1] = Ba
948  (*v)[2*i+1+j] += vi; // v[i+1] = Ba + Ab
949  }
950  }
951  return *this;
952 }
953 
954 // Consider Array2D a list of d2-vectors and multiply with vmulti
955 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::multid2(const valarray<T>& vmulti){
956  for (size_t j(0); j< d2; ++j ){
957  for (size_t i(j*td1); i< (j+1)*td1; ++i ){
958  (*v)[i] *= vmulti[j];
959  }
960  }
961  return *this;
962 }
963 
964 // Consider Array2D a list of d2-vectors and multiply with vmulti
965 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::multid2(const valarray< complex<T> >& vmulti){
966  for (size_t j(0); j< d2; ++j ){
967  for (size_t i(j*td1); i< (j+1)*td1; i+=2 ){
968  T vi((*v)[i]* vmulti[j].imag());
969  (*v)[i] *= vmulti[j].real(); // v[i] = Aa
970  (*v)[i] -= (*v)[i+1] * vmulti[j].imag(); // v[i] = Aa - Bb
971  (*v)[i+1] *= vmulti[j].real(); // v[i+1] = Ba
972  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
973  }
974  }
975  return *this;
976 }
977 
978 //--------------------------------------------------------------
979 // Central difference
980 //--------------------------------------------------------------
981 // (minus) Central difference for contiguous elements
982 // Example: 0 4 8 12 16 -2 -2 -2 -2 -2
983 // 1 5 9 13 17 --> -2 -2 -2 -2 -2
984 // 2 6 10 14 18 -2 -2 -2 -2 -2
985 // 3 7 11 15 19 -2 -2 -2 -2 19
986 // Requires at least 3 elements in d1
988  for(long i(0); i< td1*d2-4; ++i) {
989  (*v)[i] -= (*v)[i+4];
990  }
991  for(long i(td1*d2-5); i>-1; --i) {
992  (*v)[i+2] = (*v)[i];
993  }
994  return *this;
995 }
996 
997 // (minus) Central difference for elements with distance d1 (row-wise)
998 // Example: 0 4 8 12 16 -8 -8 -8 -8 16
999 // 1 5 9 13 17 --> -8 -8 -8 -8 17
1000 // 2 6 10 14 18 -8 -8 -8 -8 18
1001 // 3 7 11 15 19 -8 -8 -8 -8 19
1002 // Requires at least 3 elements in d2
1004  int twotd1 = 2*td1;
1005  for(long i(0); i< td1*d2-twotd1; ++i) {
1006  (*v)[i] -= (*v)[i+twotd1];
1007  }
1008  for(long i(td1*d2-twotd1-1); i>-1; --i) {
1009  (*v)[i+td1] = (*v)[i];
1010  }
1011  return *this;
1012 }
1013 //--------------------------------------------------------------
1014 
1015 // Remove data for N cells from dimension 1 (if N=0 don't remove anything)
1016 template<class T> Array2D_cmplx<T>& Array2D_cmplx<T>::Filterd1(size_t N) {
1017  for (size_t j(0); j < d2; ++j ){
1018  for (size_t i(j*td1); i< j*td1+2*N; ++i ){
1019  (*v)[i] = 0.0;
1020  }
1021  }
1022  return *this;
1023 }
1024 //--------------------------------------------------------------
1025 //**************************************************************
1026 
1027 
1028 /**************************************************************
1029  * 3D Array Class
1030  * Using Stroustrup's matrices p672-p673
1031  * This container is similar to Fortran-style arrays.
1032  * Custom operations, no standard Matrix algebra.
1033  * No error-checking
1034  * Compile with -ftree-vectorize
1035  */
1036 template<class T> class Array3D {
1037 //--------------------------------------------------------------
1038 // 3D Array decleration
1039 //--------------------------------------------------------------
1040 private:
1041  valarray<T> *v;
1042  size_t d1, d2, d3; // for 2D VFP: p, x, y
1043  size_t d1d2;
1044 
1045 public:
1046 // Constructors/Destructors
1047  Array3D(size_t x, size_t y, size_t z);
1048  Array3D(const Array3D& other);
1049  ~Array3D();
1050 
1051 // Basic info
1052  size_t dim() const {return d1*d2*d3;}
1053  size_t dim1() const {return d1;}
1054  size_t dim2() const {return d2;}
1055  size_t dim3() const {return d3;}
1056  valarray<T>& array() const {return *v;};
1057 
1058 // Access
1059  T& operator()(size_t i, size_t j, size_t k); // Fortran-style
1060  T operator()(size_t i, size_t j, size_t k) const;
1061  T& operator()(size_t i); // 1D-style
1062  T operator()(size_t i) const;
1063 
1064 //TODO vector<T> d2d3c(size_t j);
1065 
1066 // Slice iterators
1067  GSlice_iter<T> d1c(size_t b, size_t e);
1068  GSlice_iter<T> d2c(size_t b, size_t e);
1069  GSlice_iter<T> d3c(size_t b, size_t e);
1070  GSlice_iter<T> SubArray3D(size_t st, size_t nx, size_t ny, size_t nz);
1071 
1072 // Constant slice iterators
1073  CGSlice_iter<T> d1c(size_t b, size_t e) const;
1074  CGSlice_iter<T> d2c(size_t b, size_t e) const;
1075  CGSlice_iter<T> d3c(size_t b, size_t e) const;
1076  CGSlice_iter<T> SubArray3D(size_t st, size_t nx, size_t ny, size_t nz) const;
1077 
1078 // Operators
1079  Array3D& operator=(const T& d);
1080  Array3D& operator=(const Array3D& other);
1081  Array3D& operator*=(const T& d);
1082  Array3D& operator*=(const Array3D& vmulti);
1083  Array3D& operator+=(const T& d);
1084  Array3D& operator+=(const Array3D& vadd);
1085  Array3D& operator-=(const T& d);
1086  Array3D& operator-=(const Array3D& vmin);
1087 
1088 // Array * Vector
1089  Array3D& multid1(const valarray<T>& vmulti);// M*valarray(d1)
1090  Array3D& multid2(const valarray<T>& vmulti);// M*valarray(d2)
1091  Array3D& multid3(const valarray<T>& vmulti);// M*valarray(d3)
1092 
1093 // Array3D * Array2D
1094  Array3D& multid2d3(const Array2D<T>& vd2d3);// M*valarray(d3)
1095 
1096 // Central difference
1097  Array3D& Dd1(); // in the direction d1 (requires dim1() > 2)
1098  Array3D& Dd2(); // in the direction d2 (requires dim2() > 2)
1099  Array3D& Dd3(); // in the direction d3 (requires dim3() > 2)
1100 
1101 // Filter first N-cells in d1 direction
1102  Array3D& Filterd1(size_t N);
1103 };
1104 //--------------------------------------------------------------
1105 
1106 //--------------------------------------------------------------
1107 // Constructor and Destructor
1108 //--------------------------------------------------------------
1109 
1110 // Constructor
1111 template<class T> Array3D<T>::
1112 Array3D(size_t x, size_t y, size_t z) : d1(x), d2(y), d3(z) {
1113  v = new valarray<T>(d1*d2*d3);
1114  d1d2 = d1*d2;
1115 }
1116 // Copy constructor
1117 template<class T> Array3D<T>:: Array3D(const Array3D& other){
1118  d1 = other.dim1();
1119  d2 = other.dim2();
1120  d3 = other.dim3();
1121  d1d2 = d1*d2;
1122  v = new valarray<T>(d1*d2*d3);
1123  (*v) = other.array();
1124 }
1125 // Destructor
1126 template<class T> Array3D<T>:: ~Array3D(){
1127  delete v;
1128 }
1129 
1130 //--------------------------------------------------------------
1131 // Access
1132 //--------------------------------------------------------------
1133 
1134 // Access Fortan-style
1135 template<class T>
1136 inline T& Array3D<T>:: operator()(size_t i, size_t j, size_t k){
1137  return (*v)[i+j*d1+k*d1d2];
1138 }
1139 
1140 // Access Fortan-style
1141 template<class T>
1142 inline T Array3D<T>:: operator()(size_t i, size_t j, size_t k) const {
1143  return (*v)[i+j*d1+k*d1d2];
1144 }
1145 
1146 // 1D style access
1147 template<class T>
1148 inline T& Array3D<T>:: operator()(size_t i){
1149  return (*v)[i];
1150 }
1151 
1152 // 1D style access
1153 template<class T>
1154 inline T Array3D<T>:: operator()(size_t i) const {
1155  return (*v)[i];
1156 }
1157 //--------------------------------------------------------------
1158 // Slicers
1159 //--------------------------------------------------------------
1160 // slices (surfaces) for given d1 value range
1161 template<class T>
1162 inline GSlice_iter<T> Array3D<T>::d1c(size_t b, size_t e){
1163  valarray<size_t> sz(3), str(3);
1164  str[2] = d1; str[1] = d1d2; str[0] = 1;
1165  sz[2] = d2; sz[1] = d3; sz[0] = e-b+1;
1166  return GSlice_iter<T>(v,gslice(b,sz,str));
1167 }
1168 // const slices (surfaces) for given d1 value range
1169 template<class T>
1170 inline CGSlice_iter<T> Array3D<T>::d1c(size_t b, size_t e) const{
1171  valarray<size_t> sz(3), str(3);
1172  str[2] = d1; str[1] = d1d2; str[0] = 1;
1173  sz[2] = d2; sz[1] = d3; sz[0] = e-b+1;
1174  return CGSlice_iter<T>(v,gslice(b,sz,str));
1175 }
1176 // slices (surfaces) for given d2 value range
1177 template<class T>
1178 inline GSlice_iter<T> Array3D<T>::d2c(size_t b, size_t e){
1179  valarray<size_t> sz(3), str(3);
1180  str[2] = 1; str[1] = d1d2; str[0] = d1;
1181  sz[2] = d1; sz[1] = d3; sz[0] = e-b+1;
1182  return GSlice_iter<T>(v,gslice(d1*b,sz,str));
1183 }
1184 // const slices (surfaces) for given d2 value range
1185 template<class T>
1186 inline CGSlice_iter<T> Array3D<T>::d2c(size_t b, size_t e) const{
1187  valarray<size_t> sz(3), str(3);
1188  str[2] = 1; str[1] = d1d2; str[0] = d1;
1189  sz[2] = d1; sz[1] = d3; sz[0] = e-b+1;
1190  return CGSlice_iter<T>(v,gslice(d1*b,sz,str));
1191 }
1192 // slices (surfaces) for given d3 value range
1193 template<class T>
1194 inline GSlice_iter<T> Array3D<T>::d3c(size_t b, size_t e){
1195  valarray<size_t> sz(2), str(2);
1196  str[1] = 1; str[0] = d1d2;
1197  sz[1] = d1d2; sz[0] = e-b+1;
1198  return GSlice_iter<T>(v,gslice(d1d2*b,sz,str));
1199 }
1200 // const slices (surfaces) for given d3 value range
1201 template<class T>
1202 inline CGSlice_iter<T> Array3D<T>::d3c(size_t b, size_t e) const{
1203  valarray<size_t> sz(2), str(2);
1204  str[1] = 1; str[0] = d1d2;
1205  sz[1] = d1d2; sz[0] = e-b+1;
1206  return CGSlice_iter<T>(v,gslice(d1d2*b,sz,str));
1207 }
1208 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1209 
1210 // scan Subarray
1211 template<class T>
1212 inline GSlice_iter<T> Array3D<T>::SubArray3D(size_t st, size_t nx, size_t ny, size_t nz){
1213  valarray<size_t> sz(3), str(3);
1214  str[2] = 1; str[1] = dim1(); str[0] = d1d2;
1215  sz[2] = nx; sz[1] = ny; sz[0] = nz;
1216  return GSlice_iter<T>(v,gslice(st,sz,str));
1217 }
1218 
1219 // scan const Subarray
1220 template<class T>
1221 inline CGSlice_iter<T> Array3D<T>::SubArray3D(size_t st, size_t nx, size_t ny, size_t nz) const{
1222  valarray<size_t> sz(3), str(3);
1223  str[2] = 1; str[1] = dim1(); str[0] = d1d2;
1224  sz[2] = nx; sz[1] = ny; sz[0] = nz;
1225  return CGSlice_iter<T>(v,gslice(st,sz,str));
1226 }
1227 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1228 
1229 //--------------------------------------------------------------
1230 // Operators
1231 //--------------------------------------------------------------
1232 // Copy assignment operator
1233 template<class T> Array3D<T>& Array3D<T>::operator=(const T& d){
1234  (*v) = d;
1235  return *this;
1236 }
1237 // Copy assignment operator
1238 template<class T> Array3D<T>& Array3D<T>::operator=(const Array3D& other){
1239  if (this != &other) { //self-assignment
1240  (*v) = other.array();
1241  }
1242  return *this;
1243 }
1244 
1245 // *=
1246 template<class T> Array3D<T>& Array3D<T>::operator*=(const T& d){
1247  (*v) *=d;
1248  return *this;
1249 }
1250 template<class T> Array3D<T>& Array3D<T>::operator*=(const Array3D& vmulti){
1251  (*v) *= vmulti.array();
1252  return *this;
1253 }
1254 
1255 // +=
1256 template<class T> Array3D<T>& Array3D<T>::operator+=(const T& d){
1257  (*v) +=d;
1258  return *this;
1259 }
1260 template<class T> Array3D<T>& Array3D<T>::operator+=(const Array3D& vadd){
1261  (*v) += vadd.array();
1262  return *this;
1263 }
1264 
1265 // -=
1266 template<class T> Array3D<T>& Array3D<T>::operator-=(const T& d){
1267  (*v) -=d;
1268  return *this;
1269 }
1270 template<class T> Array3D<T>& Array3D<T>::operator-=(const Array3D& vmin){
1271  (*v) -= vmin.array();
1272  return *this;
1273 }
1274 //--------------------------------------------------------------
1275 // Array3D * Vector
1276 //--------------------------------------------------------------
1277 // Vector multiplies every d1-length of Array3D
1278 template<class T> Array3D<T>& Array3D<T>::multid1(const valarray<T>& vmulti){
1279  for (size_t j(0); j< d1*d2*d3; j+=d1 ){
1280  for (size_t i(0); i< d1; ++i ){
1281  (*v)[i+j] *= vmulti[i];
1282  }
1283  }
1284  return *this;
1285 }
1286 
1287 // Vector multiplies every d2-length of Array3D
1288 template<class T> Array3D<T>& Array3D<T>::multid2(const valarray<T>& vmulti){
1289  for (size_t k(0); k< d3*d2*d1; k+=d1*d2 ) {
1290  for (size_t j(0); j< d2; ++j ) {
1291  for (size_t i(j*d1); i< (j+1)*d1; ++i ){
1292  (*v)[i+k] *= vmulti[j];
1293  }
1294  }
1295  }
1296  return *this;
1297 }
1298 
1299 // Vector multiplies every d3-length of Array3D
1300 template<class T> Array3D<T>& Array3D<T>::multid3(const valarray<T>& vmulti){
1301  for (size_t k(0); k< d3; ++k) {
1302  for (size_t i(k*d1*d2); i< (k+1)*d1*d2; ++i ){
1303  (*v)[i] *= vmulti[k];
1304  }
1305  }
1306  return *this;
1307 }
1308 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1309 
1310 // B(j,k) multiplies every A(i,j,k)
1311 template<class T> Array3D<T>& Array3D<T>::multid2d3(const Array2D<T>& vd2d3){
1312  for (size_t j(0); j < d2*d3; ++j ){
1313  for (size_t i(j*d1); i< (j+1)*d1; ++i ){
1314  (*v)[i] *= vd2d3.array()[j];
1315  }
1316  }
1317  return *this;
1318 }
1319 
1320 
1321 //--------------------------------------------------------------
1322 // Central difference
1323 //--------------------------------------------------------------
1324 // (minus) Central difference for contiguous elements
1325 template<class T> Array3D<T>& Array3D<T>::Dd1(){
1326  for(long i(0); i< d1*d2*d3-2; ++i) {
1327  (*v)[i] -= (*v)[i+2];
1328  }
1329  for(long i(d1*d2*d3-3); i>-1; --i) {
1330  (*v)[i+1] = (*v)[i];
1331  }
1332  return *this;
1333 }
1334 
1335 // (minus) Central difference in the d2 direction
1336 template<class T> Array3D<T>& Array3D<T>::Dd2(){
1337  long twod1 = 2*d1;
1338  for(long i(0); i< d1*d2*d3-twod1; ++i) {
1339  (*v)[i] -= (*v)[i+twod1];
1340  }
1341  for(long i(d1*d2*d3-twod1-1); i>-1; --i) {
1342  (*v)[i+d1] = (*v)[i];
1343  }
1344  return *this;
1345 }
1346 
1347 // (minus) Central difference in the d3 direction
1348 template<class T> Array3D<T>& Array3D<T>::Dd3() {
1349  long twod1d2 = 2*d1d2;
1350  for(long i(0); i< d1*d2*d3-twod1d2; ++i) {
1351  (*v)[i] -= (*v)[i+twod1d2];
1352  }
1353  for(long i(d1*d2*d3-twod1d2-1); i>-1; --i) {
1354  (*v)[i+d1d2] = (*v)[i];
1355  }
1356  return *this;
1357 }
1358 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1359 
1360 // Remove data for N cells from dimension 1
1361 template<class T> Array3D<T>& Array3D<T>::Filterd1(size_t N) {
1362  for (size_t j(0); j < d2*d3; ++j ){
1363  for (size_t i(j*d1); i< j*d1+N; ++i ){
1364  (*v)[i] = 0.0;
1365  }
1366  }
1367  return *this;
1368 }
1369 //**************************************************************
1370 
1371 /**************************************************************
1372 * 3D Complex Array Class
1373 * Using Stroustrup's matrices p672-p673
1374 * This container is similar to Fortran-style arrays.
1375 * Custom operations, no standard Matrix algebra.
1376 * No error-checking
1377 * Compile with -ftree-vectorize
1378 */
1379 template<class T> class Array3D_cmplx {
1380 //--------------------------------------------------------------
1381 // 3D Array decleration
1382 //--------------------------------------------------------------
1383 private:
1384  valarray<T> *v;
1385  size_t d1, d2, d3; // for 2D VFP: p, x, y
1386  size_t td1;
1387  size_t td1d2;
1388 
1389 public:
1390 // Constructors/Destructors
1391  Array3D_cmplx(size_t x, size_t y, size_t z);
1392  Array3D_cmplx(const Array3D_cmplx& other);
1393  ~Array3D_cmplx();
1394 
1395 // Basic info
1396  size_t dim() const {return d1*d2*d3;}
1397  size_t dim1() const {return d1;}
1398  size_t dim2() const {return d2;}
1399  size_t dim3() const {return d3;}
1400  valarray<T>& array() const {return *v;};
1401 
1402 // Access
1403  T& operator[](size_t i); // 1D-style
1404  T operator[](size_t i) const;
1405 
1406  T& real(size_t i,size_t j,size_t k); // 1D-style
1407  T real(size_t i,size_t j,size_t k) const;
1408  T& imag(size_t i,size_t j,size_t k); // 1D-style
1409  T imag(size_t i,size_t j,size_t k) const;
1410 
1411 //TODO vector<T> d2d3c(size_t j);
1412 
1413 // Slice iterators
1414  GSlice_iter<T> d1c(size_t b, size_t e);
1415  GSlice_iter<T> d2c(size_t b, size_t e);
1416  GSlice_iter<T> d3c(size_t b, size_t e);
1417  GSlice_iter<T> SubArray3D(size_t st, size_t nx, size_t ny, size_t nz);
1418 
1419 // Constant slice iterators
1420  CGSlice_iter<T> d1c(size_t b, size_t e) const;
1421  CGSlice_iter<T> d2c(size_t b, size_t e) const;
1422  CGSlice_iter<T> d3c(size_t b, size_t e) const;
1423  CGSlice_iter<T> SubArray3D(size_t st, size_t nx, size_t ny, size_t nz) const;
1424 
1425 // Operators
1426  Array3D_cmplx& operator=(const T& d);
1427  Array3D_cmplx& operator=(const complex<T>& c);
1428  Array3D_cmplx& operator=(const Array3D<T>& other);
1429  Array3D_cmplx& operator=(const Array3D_cmplx& other);
1430  Array3D_cmplx& operator*=(const T& d);
1431  Array3D_cmplx& operator*=(const complex<T>& c);
1432  Array3D_cmplx& operator*=(const Array3D<T>& vmulti);
1433  Array3D_cmplx& operator*=(const Array3D_cmplx& vmulti);
1434  Array3D_cmplx& operator+=(const T& d);
1435  Array3D_cmplx& operator+=(const complex<T>& c);
1436  Array3D_cmplx& operator+=(const Array3D<T>& vadd);
1437  Array3D_cmplx& operator+=(const Array3D_cmplx& vadd);
1438  Array3D_cmplx& operator-=(const T& d);
1439  Array3D_cmplx& operator-=(const complex<T>& c);
1440  Array3D_cmplx& operator-=(const Array3D<T>& vmin);
1441  Array3D_cmplx& operator-=(const Array3D_cmplx& vmin);
1442 
1443 // Array * Vector
1444  Array3D_cmplx& multid1(const valarray<T>& vmulti);// M*valarray(d1)
1445  Array3D_cmplx& multid1(const valarray< complex<T> >& vmulti);// M*valarray(d1)
1446  Array3D_cmplx& multid2(const valarray<T>& vmulti);// M*valarray(d2)
1447  Array3D_cmplx& multid2(const valarray< complex<T> >& vmulti);// M*valarray(d2)
1448  Array3D_cmplx& multid3(const valarray<T>& vmulti);// M*valarray(d3)
1449  Array3D_cmplx& multid3(const valarray< complex<T> >& vmulti);// M*valarray(d3)
1450 
1451 // Array3D * Array2D
1452  Array3D_cmplx& multid2d3(const Array2D<T>& vd2d3);
1453  Array3D_cmplx& multid2d3(const Array2D_cmplx<T>& vd2d3);
1454 
1455 // Central difference
1456  Array3D_cmplx& Dd1(); // in the direction d1 (requires dim1() > 2)
1457  Array3D_cmplx& Dd2(); // in the direction d2 (requires dim2() > 2)
1458  Array3D_cmplx& Dd3(); // in the direction d3 (requires dim3() > 2)
1459 
1460 // Filter first N-cells in d1 direction
1461  Array3D_cmplx& Filterd1(size_t N);
1462 };
1463 //--------------------------------------------------------------
1464 
1465 //--------------------------------------------------------------
1466 // Constructor and Destructor
1467 //--------------------------------------------------------------
1468 // Constructor
1469 template<class T> Array3D_cmplx<T>:: Array3D_cmplx(size_t x,size_t y,size_t z) : d1(x), d2(y), d3(z) {
1470  v = new valarray<T>(2*d1*d2*d3);
1471  td1 = 2*d1;
1472  td1d2 = 2*d1*d2;
1473 }
1474 // Copy constructor
1475 template<class T> Array3D_cmplx<T>:: Array3D_cmplx(const Array3D_cmplx& other){
1476  d1 = other.dim1();
1477  d2 = other.dim2();
1478  d3 = other.dim3();
1479  td1 = 2*d1;
1480  td1d2 = 2*d1*d2;
1481  v = new valarray<T>(2*d1*d2*d3);
1482  (*v) = other.array();
1483 }
1484 // Destructor
1486  delete v;
1487 }
1488 
1489 //--------------------------------------------------------------
1490 // Access
1491 //--------------------------------------------------------------
1492 // 1D style access
1493 template<class T> inline T& Array3D_cmplx<T>::operator[] (size_t i){
1494  return (*v)[i];
1495 }
1496 // 1D style const access
1497 template<class T> inline T Array3D_cmplx<T>::operator[] (size_t i) const {
1498  return (*v)[i];
1499 }
1500 // Access real part by reference
1501 template<class T> inline T& Array3D_cmplx<T>::real(size_t i,size_t j,size_t k){
1502  return (*v)[2*i+j*td1+k*td1d2];
1503 }
1504 // Const access of real part
1505 template<class T> inline T Array3D_cmplx<T>::real(size_t i,size_t j,size_t k) const{
1506  return (*v)[2*i+j*td1+k*td1d2];
1507 }
1508 // access of imag part
1509 template<class T> inline T& Array3D_cmplx<T>::imag(size_t i,size_t j,size_t k){
1510  return (*v)[2*i+1+j*td1+k*td1d2];
1511 }
1512 // Const access of imag part
1513 template<class T> inline T Array3D_cmplx<T>::imag(size_t i,size_t j,size_t k) const{
1514  return (*v)[2*i+1+j*td1+k*td1d2];
1515 }
1516 //--------------------------------------------------------------
1517 // Slicers
1518 //--------------------------------------------------------------
1519 // slices (surfaces) for given d1 value range
1520 template<class T>
1521 inline GSlice_iter<T> Array3D_cmplx<T>::d1c(size_t b, size_t e){
1522  valarray<size_t> sz(4), str(4);
1523  str[3] = 1, str[2] = td1; str[1] = td1d2; str[0] = 2;
1524  sz[3] = 2, sz[2] = d2; sz[1] = d3; sz[0] = e-b+1;
1525  return GSlice_iter<T>(v,gslice(2*b,sz,str));
1526 }
1527 // const slices (surfaces) for given d1 value range
1528 template<class T>
1529 inline CGSlice_iter<T> Array3D_cmplx<T>::d1c(size_t b, size_t e) const{
1530  valarray<size_t> sz(4), str(4);
1531  str[3] = 1, str[2] = td1; str[1] = td1d2; str[0] = 2;
1532  sz[3] = 2, sz[2] = d2; sz[1] = d3; sz[0] = e-b+1;
1533  return CGSlice_iter<T>(v,gslice(2*b,sz,str));
1534 }
1535 // slices (surfaces) for given d2 value range
1536 template<class T>
1537 inline GSlice_iter<T> Array3D_cmplx<T>::d2c(size_t b, size_t e){
1538  valarray<size_t> sz(3), str(3);
1539  str[2] = 1; str[1] = td1d2; str[0] = td1;
1540  sz[2] = td1; sz[1] = d3; sz[0] = e-b+1;
1541  return GSlice_iter<T>(v,gslice(td1*b,sz,str));
1542 }
1543 // const slices (surfaces) for given d2 value range
1544 template<class T>
1545 inline CGSlice_iter<T> Array3D_cmplx<T>::d2c(size_t b, size_t e) const{
1546  valarray<size_t> sz(3), str(3);
1547  str[2] = 1; str[1] = td1d2; str[0] = td1;
1548  sz[2] = td1; sz[1] = d3; sz[0] = e-b+1;
1549  return CGSlice_iter<T>(v,gslice(td1*b,sz,str));
1550 }
1551 // slices (surfaces) for given d3 value range
1552 template<class T>
1553 inline GSlice_iter<T> Array3D_cmplx<T>::d3c(size_t b, size_t e){
1554  valarray<size_t> sz(2), str(2);
1555  str[1] = 1; str[0] = td1d2;
1556  sz[1] = td1d2; sz[0] = e-b+1;
1557  return GSlice_iter<T>(v,gslice(td1d2*b,sz,str));
1558 }
1559 // const slices (surfaces) for given d3 value range
1560 template<class T>
1561 inline CGSlice_iter<T> Array3D_cmplx<T>::d3c(size_t b, size_t e) const{
1562  valarray<size_t> sz(2), str(2);
1563  str[1] = 1; str[0] = td1d2;
1564  sz[1] = td1d2; sz[0] = e-b+1;
1565  return CGSlice_iter<T>(v,gslice(td1d2*b,sz,str));
1566 }
1567 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1568 
1569 // scan Subarray
1570 template<class T>
1571 inline GSlice_iter<T> Array3D_cmplx<T>::SubArray3D(size_t st, size_t nx, size_t ny, size_t nz){
1572  valarray<size_t> sz(3), str(3);
1573  str[2] = 1; str[1] = td1; str[0] = td1d2;
1574  sz[2] = 2*nx; sz[1] = ny; sz[0] = nz;
1575  return GSlice_iter<T>(v,gslice(2*st,sz,str));
1576 }
1577 
1578 // scan const Subarray
1579 template<class T>
1580 inline CGSlice_iter<T> Array3D_cmplx<T>::SubArray3D(size_t st, size_t nx, size_t ny, size_t nz) const{
1581  valarray<size_t> sz(3), str(3);
1582  str[2] = 1; str[1] = td1; str[0] = td1d2;
1583  sz[2] = 2*nx; sz[1] = ny; sz[0] = nz;
1584  return CGSlice_iter<T>(v,gslice(2*st,sz,str));
1585 }
1586 
1587 //--------------------------------------------------------------
1588 // Operators
1589 //--------------------------------------------------------------
1590 // Copy assignment operator
1591 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator=(const T& d){
1592  for (size_t i(0); i< td1*d2*d3; i+=2) {
1593  (*v)[i] = d;
1594  (*v)[i+1] = 0.0;
1595  }
1596  return *this;
1597 }
1598 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator=(const complex<T>& c){
1599  for (size_t i(0); i< td1*d2*d3; i+=2) {
1600  (*v)[i] =c.real();
1601  (*v)[i+1] =c.imag();
1602  }
1603  return *this;
1604 }
1606  for (size_t i(0); i< d1*d2*d3; ++i) {
1607  (*v)[2*i] = other.array()[i];
1608  (*v)[2*i+1] = 0.0;
1609  }
1610  return *this;
1611 }
1613  if (this != &other) { //self-assignment
1614  (*v) = other.array();
1615  }
1616  return *this;
1617 }
1618 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1619 
1620 // *=
1621 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator*=(const T& d){
1622  (*v) *=d;
1623  return *this;
1624 }
1625 // *=
1626 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator*=(const complex<T>& c){
1627  for (size_t i(0); i< td1*d2*d3; i+=2) { // suppose v[i]+iv[i+1]=A+iB, c=a+ib
1628  T vi((*v)[i]*c.imag());
1629  (*v)[i] *= c.real(); // v[i] = Aa
1630  (*v)[i] -= (*v)[i+1]*c.imag(); // v[i] = Aa - Bb
1631  (*v)[i+1] *= c.real(); // v[i+1] = Ba
1632  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
1633  }
1634  return *this;
1635 }
1636 // *=
1638  for (size_t i(0); i< d1*d2*d3; ++i) {
1639  (*v)[2*i] *= vmulti.array()[i];
1640  (*v)[2*i+1] *= vmulti.array()[i];
1641  }
1642  return *this;
1643 }
1644 // *=
1646  for (size_t i(0); i< td1*d2*d3; i+=2) { // suppose v[i]+iv[i+1]=A+iB, vmulti[i] + ivmulti[i+1] = a+ib
1647  T vi((*v)[i] * vmulti.array()[i+1]);
1648  (*v)[i] *= vmulti.array()[i]; // v[i] = Aa
1649  (*v)[i] -= (*v)[i+1]*vmulti.array()[i+1]; // v[i] = Aa - Bb
1650  (*v)[i+1] *= vmulti.array()[i]; // v[i+1] = Ba
1651  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
1652  }
1653  return *this;
1654 }
1655 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1656 
1657 // +=
1658 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator+=(const T& d){
1659  for (size_t i(0); i< td1*d2*d3; i+=2) {
1660  (*v)[i] +=d;
1661  }
1662  return *this;
1663 }
1664 // +=
1665 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator+=(const complex<T>& c){
1666  for (size_t i(0); i< td1*d2*d3; i+=2) {
1667  (*v)[i] +=c.real();
1668  (*v)[i+1] +=c.imag();
1669  }
1670  return *this;
1671 }
1672 // +=
1674  for (size_t i(0); i< d1*d2*d3; ++i) {
1675  (*v)[2*i] += vadd.array()[i];
1676  }
1677  return *this;
1678 }
1679 // +=
1681  (*v) += vadd.array();
1682  return *this;
1683 }
1684 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1685 
1686 // -=
1687 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator-=(const T& d){
1688  for (size_t i(0); i< td1*d2*d3; i+=2) {
1689  (*v)[i] -=d;
1690  }
1691  return *this;
1692 }
1693 // -=
1694 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::operator-=(const complex<T>& c){
1695  for (size_t i(0); i< td1*d2*d3; i+=2) {
1696  (*v)[i] -=c.real();
1697  (*v)[i+1] -=c.imag();
1698  }
1699  return *this;
1700 }
1701 // -=
1703  for (size_t i(0); i< d1*d2*d3; ++i) {
1704  (*v)[2*i] -= vmin.array()[i];
1705  }
1706  return *this;
1707 }
1708 // -=
1710  (*v) -= vmin.array();
1711  return *this;
1712 }
1713 
1714 //--------------------------------------------------------------
1715 // Array3D * Vector
1716 //--------------------------------------------------------------
1717 // Vector multiplies every d1-length of Array3D
1718 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid1(const valarray<T>& vmulti){
1719  for (size_t j(0); j< td1*d2*d3; j+=td1 ){
1720  for (size_t i(0); i< d1; ++i ){
1721  (*v)[2*i+j] *= vmulti[i];
1722  (*v)[2*i+1+j] *= vmulti[i];
1723  }
1724  }
1725  return *this;
1726 }
1727 
1728 // Vector multiplies every d1-length of Array3D
1729 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid1(const valarray< complex<T> >& vmulti){
1730  for (size_t j(0); j< td1*d2*d3; j+=td1 ){
1731  for (size_t i(0); i< d1; ++i ){
1732  T vi((*v)[2*i+j]*vmulti[i].imag());
1733  (*v)[2*i+j] *= vmulti[i].real(); // v[i] = Aa
1734  (*v)[2*i+j] -= (*v)[2*i+1+j] * vmulti[i].imag(); // v[i] = Aa - Bb
1735  (*v)[2*i+1+j] *= vmulti[i].real(); // v[i+1] = Ba
1736  (*v)[2*i+1+j] += vi; // v[i+1] = Ba + Ab
1737  }
1738  }
1739  return *this;
1740 }
1741 
1742 // Vector multiplies every d2-length of Array3D
1743 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid2(const valarray<T>& vmulti){
1744  for (size_t k(0); k< d3*d2*td1; k+=td1*d2 ) {
1745  for (size_t j(0); j< d2; ++j ) {
1746  for (size_t i(j*td1); i< (j+1)*td1; ++i ){
1747  (*v)[i+k] *= vmulti[j];
1748  }
1749  }
1750  }
1751  return *this;
1752 }
1753 
1754 // Vector multiplies every d2-length of Array3D
1755 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid2(const valarray< complex<T> >& vmulti){
1756  for (size_t k(0); k< d3*d2*td1; k+=td1*d2 ) {
1757  for (size_t j(0); j< d2; ++j ) {
1758  for (size_t i(j*td1); i< (j+1)*td1; i+=2 ){
1759  T vi((*v)[i+k]* vmulti[j].imag());
1760  (*v)[i+k] *= vmulti[j].real(); // v[i] = Aa
1761  (*v)[i+k] -= (*v)[i+k+1] * vmulti[j].imag(); // v[i] = Aa - Bb
1762  (*v)[i+k+1] *= vmulti[j].real(); // v[i+1] = Ba
1763  (*v)[i+k+1] += vi; // v[i+1] = Ba + Ab
1764  }
1765  }
1766  }
1767  return *this;
1768 }
1769 
1770 // Vector multiplies every d3-length of Array3D
1771 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid3(const valarray<T>& vmulti){
1772  for (size_t k(0); k< d3; ++k) {
1773  for (size_t i(k*td1*d2); i< (k+1)*td1*d2; ++i ){
1774  (*v)[i] *= vmulti[k];
1775  }
1776  }
1777  return *this;
1778 }
1779 
1780 // Vector multiplies every d3-length of Array3D
1781 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::multid3(const valarray< complex<T> >& vmulti){
1782  for (size_t k(0); k< d3; ++k) {
1783  for (size_t i(k*td1*d2); i< (k+1)*td1*d2; i+=2 ){
1784  T vi((*v)[i]* vmulti[k].imag());
1785  (*v)[i] *= vmulti[k].real(); // v[i] = Aa
1786  (*v)[i] -= (*v)[i+1] * vmulti[k].imag(); // v[i] = Aa - Bb
1787  (*v)[i+1] *= vmulti[k].real(); // v[i+1] = Ba
1788  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
1789  }
1790  }
1791  return *this;
1792 }
1793 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1794 
1795 // B(j,k) multiplies every A(i,j,k)
1797  for (size_t j(0); j < d2*d3; ++j ){
1798  for (size_t i(j*td1); i< (j+1)*td1; ++i ){
1799  (*v)[i] *= vd2d3.array()[j];
1800  }
1801  }
1802  return *this;
1803 }
1804 
1805 
1806 // B(j,k) multiplies every A(i,j,k)
1808  for (size_t j(0); j < d2*d3; ++j ){
1809  for (size_t i(j*td1); i< (j+1)*td1; i+=2 ){
1810  T vi((*v)[i]*vd2d3.array()[2*j+1]);
1811  (*v)[i] *= vd2d3.array()[2*j]; // v[i] = Aa
1812  (*v)[i] -= (*v)[i+1]*vd2d3.array()[2*j+1]; // v[i] = Aa - Bb
1813  (*v)[i+1] *= vd2d3.array()[2*j]; // v[i+1] = Ba
1814  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
1815  }
1816  }
1817  return *this;
1818 }
1819 //--------------------------------------------------------------
1820 // Central difference
1821 //--------------------------------------------------------------
1822 // (minus) Central difference for contiguous elements
1824  for(long i(0); i< td1*d2*d3-4; ++i) {
1825  (*v)[i] -= (*v)[i+4];
1826  }
1827  for(long i(td1*d2*d3-5); i>-1; --i) {
1828  (*v)[i+2] = (*v)[i];
1829  }
1830  return *this;
1831 }
1832 
1833 // (minus) Central difference in the d2 direction
1835  long twotd1 = 2*td1;
1836  for(long i(0); i< td1*d2*d3-twotd1; ++i) {
1837  (*v)[i] -= (*v)[i+twotd1];
1838  }
1839  for(long i(td1*d2*d3-twotd1-1); i>-1; --i) {
1840  (*v)[i+td1] = (*v)[i];
1841  }
1842  return *this;
1843 }
1844 
1845 // (minus) Central difference in the d3 direction
1847  long twotd1d2 = 2*td1d2;
1848  for(long i(0); i< long(td1*d2*d3)-twotd1d2; ++i) {
1849  (*v)[i] -= (*v)[i+twotd1d2];
1850  }
1851  for(long i(td1*d2*d3-twotd1d2-1); i>-1; --i) {
1852  (*v)[i+td1d2] = (*v)[i];
1853  }
1854  return *this;
1855 }
1856 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1857 
1858 // Remove data for N cells from dimension 1
1859 template<class T> Array3D_cmplx<T>& Array3D_cmplx<T>::Filterd1(size_t N) {
1860  for (size_t j(0); j < d2*d3; ++j ){
1861  for (size_t i(j*td1); i< j*td1+2*N; ++i ){
1862  (*v)[i] = 0.0;
1863  }
1864  }
1865  return *this;
1866 }
1867 
1868 
1869 
1870 /**************************************************************
1871 * 4D Array Class
1872 ***************************************************************
1873 * Using Stroustrup's matrices p672-p673
1874 * This container is similar to Fortran-style arrays.
1875 * Custom operations, no standard Matrix algebra.
1876 * No error-checking
1877 * Compile with -ftree-vectorize
1878 */
1879 template<class T> class Array4D {
1880 //--------------------------------------------------------------
1881 // 4D Array decleration
1882 //--------------------------------------------------------------
1883 
1884 private:
1885  valarray<T> *v;
1886  size_t d1, d2, d3, d4; // For 3d VFP: p, x, y, z
1887  size_t d1d2;
1888  size_t d1d2d3;
1889 
1890 public:
1891 // Constructors/Destructors
1892  Array4D(size_t x, size_t y, size_t z, size_t w);
1893  Array4D(const Array4D& other);
1894  ~Array4D();
1895 
1896 // Basic Info
1897  size_t dim() const {return d1*d2*d3*d4;}
1898  size_t dim1() const {return d1;}
1899  size_t dim2() const {return d2;}
1900  size_t dim3() const {return d3;}
1901  size_t dim4() const {return d4;}
1902  valarray<T>& array() const {return *v;};
1903 
1904 // Access
1905  T& operator()(size_t i, size_t j, size_t k, size_t l); // Fortran-style
1906  T operator()(size_t i, size_t j, size_t k, size_t l) const;
1907  T& operator()(size_t i); // 1D-style
1908  T operator()(size_t i) const;
1909 
1910 //TODO vector<T> d2d3d4c(size_t j);
1911 
1912 // Slice iterators
1913  GSlice_iter<T> d1c(size_t b, size_t e);
1914  GSlice_iter<T> d2c(size_t b, size_t e);
1915  GSlice_iter<T> d3c(size_t b, size_t e);
1916  GSlice_iter<T> d4c(size_t b, size_t e);
1917  GSlice_iter<T> SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw);
1918 
1919 // Constant slice iterators
1920  CGSlice_iter<T> d1c(size_t b, size_t e) const;
1921  CGSlice_iter<T> d2c(size_t b, size_t e) const;
1922  CGSlice_iter<T> d3c(size_t b, size_t e) const;
1923  CGSlice_iter<T> d4c(size_t b, size_t e) const;
1924  CGSlice_iter<T> SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw) const;
1925 
1926 // Operators
1927  Array4D& operator=(const T& d);
1928  Array4D& operator=(const Array4D& other);
1929  Array4D& operator*=(const T& d);
1930  Array4D& operator*=(const Array4D& vmulti);
1931  Array4D& operator+=(const T& d);
1932  Array4D& operator+=(const Array4D& vadd);
1933  Array4D& operator-=(const T& d);
1934  Array4D& operator-=(const Array4D& vmin);
1935 
1936 // Array * Vector
1937  Array4D& multid1(const valarray<T>& vmulti);// M*valarray(d1)
1938  Array4D& multid2(const valarray<T>& vmulti);// M*valarray(d2)
1939  Array4D& multid3(const valarray<T>& vmulti);// M*valarray(d3)
1940  Array4D& multid4(const valarray<T>& vmulti);// M*valarray(d3)
1941 
1942 // Array4D * Array3D
1943  Array4D& multid2d3d4(const Array3D<T>& vd2d3d4);
1944 
1945 // Central difference
1946  Array4D& Dd1(); // in the direction d1
1947  Array4D& Dd2(); // in the direction d2
1948  Array4D& Dd3(); // in the direction d3
1949  Array4D& Dd4(); // in the direction d3
1950 
1951 // Filter first N-cells in d1 direction
1952  Array4D& Filterd1(size_t N);
1953 };
1954 //--------------------------------------------------------------
1955 
1956 //--------------------------------------------------------------
1957 // Constructor and Destructor
1958 //--------------------------------------------------------------
1959 
1960 // Constructor
1961 template<class T> Array4D<T>::
1962 Array4D(size_t x, size_t y, size_t z, size_t w) : d1(x), d2(y), d3(z), d4(w) {
1963  v = new valarray<T>(d1*d2*d3*d4);
1964  d1d2 = d1*d2;
1965  d1d2d3 = d1*d2*d3;
1966 }
1967 // Copy constructor
1968 template<class T> Array4D<T>:: Array4D(const Array4D& other){
1969  d1 = other.dim1();
1970  d2 = other.dim2();
1971  d3 = other.dim3();
1972  d4 = other.dim4();
1973  d1d2 = d1*d2;
1974  d1d2d3 = d1*d2*d3;
1975  v = new valarray<T>(d1*d2*d3*d4);
1976  (*v) = other.array();
1977 }
1978 // Destructor
1979 template<class T> Array4D<T>:: ~Array4D(){
1980  delete v;
1981 }
1982 
1983 //--------------------------------------------------------------
1984 // Access
1985 //--------------------------------------------------------------
1986 
1987 // Access Fortan-style
1988 template<class T>
1989 inline T& Array4D<T>:: operator()(size_t i, size_t j, size_t k, size_t l){
1990  return (*v)[i+j*d1+k*d1d2+l*d1d2d3];
1991 }
1992 
1993 // Access Fortan-style
1994 template<class T>
1995 inline T Array4D<T>:: operator()(size_t i, size_t j, size_t k, size_t l) const {
1996  return (*v)[i+j*d1+k*d1d2+l*d1d2d3];
1997 }
1998 
1999 // 1D style access
2000 template<class T>
2001 inline T& Array4D<T>:: operator()(size_t i){
2002  return (*v)[i];
2003 }
2004 
2005 // 1D style access
2006 template<class T>
2007 inline T Array4D<T>:: operator()(size_t i) const {
2008  return (*v)[i];
2009 }
2010 //--------------------------------------------------------------
2011 
2012 // slices (cubes) for given d1 value range
2013 template<class T>
2014 inline GSlice_iter<T> Array4D<T>::d1c(size_t b, size_t e){
2015  valarray<size_t> sz(4), str(4);
2016  str[3] = d1; str[2] = d1d2; str[1] = d1d2d3; str[0] = 1;
2017  sz[3] = d2; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2018  return GSlice_iter<T>(v,gslice(b,sz,str));
2019 }
2020 // const slices (cubes) for given d1 value range
2021 template<class T>
2022 inline CGSlice_iter<T> Array4D<T>::d1c(size_t b, size_t e) const{
2023  valarray<size_t> sz(4), str(4);
2024  str[3] = d1; str[2] = d1d2; str[1] = d1d2d3; str[0] = 1;
2025  sz[3] = d2; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2026  return CGSlice_iter<T>(v,gslice(b,sz,str));
2027 }
2028 // slices (cubes) for given d2 value range
2029 template<class T>
2030 inline GSlice_iter<T> Array4D<T>::d2c(size_t b, size_t e){
2031  valarray<size_t> sz(4), str(4);
2032  str[3] = 1; str[2] = d1d2; str[1] = d1d2d3; str[0] = d1;
2033  sz[3] = d1; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2034  return GSlice_iter<T>(v,gslice(b*d1,sz,str));
2035 }
2036 // const slices (cubes) for given d2 value range
2037 template<class T>
2038 inline CGSlice_iter<T> Array4D<T>::d2c(size_t b, size_t e) const{
2039  valarray<size_t> sz(4), str(4);
2040  str[3] = 1; str[2] = d1d2; str[1] = d1d2d3; str[0] = d1;
2041  sz[3] = d1; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2042  return CGSlice_iter<T>(v,gslice(b*d1,sz,str));
2043 }
2044 // slices (cubes) for given d3 value range
2045 template<class T>
2046 inline GSlice_iter<T> Array4D<T>::d3c(size_t b, size_t e){
2047  valarray<size_t> sz(3), str(3);
2048  str[2] = 1; str[1] = d1d2d3; str[0] = d1d2;
2049  sz[2] = d1d2; sz[1] = d4; sz[0] = e-b+1;
2050  return GSlice_iter<T>(v,gslice(b*d1d2,sz,str));
2051 }
2052 // const slices (cubes) for given d3 value range
2053 template<class T>
2054 inline CGSlice_iter<T> Array4D<T>::d3c(size_t b, size_t e) const{
2055  valarray<size_t> sz(3), str(3);
2056  str[2] = 1; str[1] = d1d2d3; str[0] = d1d2;
2057  sz[2] = d1d2; sz[1] = d4; sz[0] = e-b+1;
2058  return CGSlice_iter<T>(v,gslice(b*d1d2,sz,str));
2059 }
2060 // slices (cubes) for given d4 value range
2061 template<class T>
2062 inline GSlice_iter<T> Array4D<T>::d4c(size_t b, size_t e) {
2063  valarray<size_t> sz(2), str(2);
2064  str[1] = 1; str[0] = d1d2d3;
2065  sz[1] = d1d2d3; sz[0] = e-b+1;
2066  return GSlice_iter<T>(v,gslice(b*d1d2d3,sz,str));
2067 }
2068 // const slices (cubes) for given d4 value range
2069 template<class T>
2070 inline CGSlice_iter<T> Array4D<T>::d4c(size_t b, size_t e) const {
2071  valarray<size_t> sz(2), str(2);
2072  str[1] = 1; str[0] = d1d2d3;
2073  sz[1] = d1d2d3; sz[0] = e-b+1;
2074  return CGSlice_iter<T>(v,gslice(b*d1d2d3,sz,str));
2075 }
2076 
2077 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------
2078 
2079 // Generate Subarray
2080 template<class T>
2081 inline GSlice_iter<T> Array4D<T>::SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw){
2082  valarray<size_t> sz(4), str(4);
2083  str[3] = 1; str[2] = d1; str[1] = d1d2; str[0] = d1d2d3;
2084  sz[3] = nx; sz[2] = ny; sz[1] = nz; sz[0] = nw;
2085  return GSlice_iter<T>(v,gslice(st,sz,str));
2086 }
2087 
2088 // Generate Subarray
2089 template<class T>
2090 inline CGSlice_iter<T> Array4D<T>::SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw) const{
2091  valarray<size_t> sz(3), str(3);
2092  str[3] = 1; str[2] = d1; str[1] = d1d2; str[0] = d1d2d3;
2093  sz[3] = nx; sz[2] = ny; sz[1] = nz; sz[0] = nw;
2094  return CGSlice_iter<T>(v,gslice(st,sz,str));
2095 }
2096 
2097 //--------------------------------------------------------------
2098 // Operators
2099 //--------------------------------------------------------------
2100 
2101 // Copy assignment operator
2102 template<class T> Array4D<T>& Array4D<T>::operator=(const T& d){
2103  (*v) = d;
2104  return *this;
2105 }
2106 // Copy assignment operator
2107 template<class T> Array4D<T>& Array4D<T>::operator=(const Array4D& other){
2108  if (this != &other) { //self-assignment
2109  (*v) = other.array();
2110  }
2111  return *this;
2112 }
2113 
2114 // *=
2115 template<class T> Array4D<T>& Array4D<T>::operator*=(const T& d){
2116  (*v) *=d;
2117  return *this;
2118 }
2119 template<class T> Array4D<T>& Array4D<T>::operator*=(const Array4D& vmulti){
2120  (*v) *= vmulti.array();
2121  return *this;
2122 }
2123 
2124 // +=
2125 template<class T> Array4D<T>& Array4D<T>::operator+=(const T& d){
2126  (*v) +=d;
2127  return *this;
2128 }
2129 template<class T> Array4D<T>& Array4D<T>::operator+=(const Array4D& vadd){
2130  (*v) += vadd.array();
2131  return *this;
2132 }
2133 
2134 // -=
2135 template<class T> Array4D<T>& Array4D<T>::operator-=(const T& d){
2136  (*v) -=d;
2137  return *this;
2138 }
2139 template<class T> Array4D<T>& Array4D<T>::operator-=(const Array4D& vmin){
2140  (*v) -= vmin.array();
2141  return *this;
2142 }
2143 
2144 //--------------------------------------------------------------
2145 // Array4D * Vector
2146 //--------------------------------------------------------------
2147 // Vector multiplies every d1-length of Array4D
2148 template<class T> Array4D<T>& Array4D<T>::multid1(const valarray<T>& vmulti){
2149  for (size_t j(0); j< dim(); j+=d1 ){
2150  for (size_t i(0); i< d1; ++i ){
2151  (*v)[i+j] *= vmulti[i];
2152  }
2153  }
2154  //for(size_t i(0); i< d1; ++i) {
2155  // for(GSlice_iter<T> it(d1c(i,i)); it!=it.end(); ++it) *it *= vmulti[i];
2156  // }
2157  return *this;
2158 }
2159 
2160 // Vector multiplies every d2-length of Array4D
2161 template<class T> Array4D<T>& Array4D<T>::multid2(const valarray<T>& vmulti){
2162  for (size_t k(0); k< dim(); k+=d1*d2 ) {
2163  for (size_t j(0); j< d2; ++j ) {
2164  for (size_t i(j*d1); i< (j+1)*d1; ++i ){
2165  (*v)[i+k] *= vmulti[j];
2166  }
2167  }
2168  }
2169  /*for(size_t j(0); j< d2; ++j) {
2170  for(GSlice_iter<T> it(d2c(j,j)); it!=it.end(); ++it) *it *= vmulti[j];
2171  }*/
2172  return *this;
2173 }
2174 
2175 // Vector multiplies every d3-length of Array4D
2176 template<class T> Array4D<T>& Array4D<T>::multid3(const valarray<T>& vmulti){
2177  for (size_t l(0); l< dim(); l+=d1*d2*d3) {
2178  for (size_t k(0); k< d3; ++k) {
2179  for (size_t i(k*d1*d2); i< (k+1)*d1*d2; ++i ){
2180  (*v)[i+l] *= vmulti[k];
2181  }
2182  }
2183  }
2184  //for(size_t k(0); k< d3; ++k) {
2185  // for(GSlice_iter<T> it(d3c(k,k)); it!=it.end(); ++it) *it *= vmulti[k];
2186  //}
2187  return *this;
2188 }
2189 
2190 // Vector multiplies every d3-length of Array4D
2191 template<class T> Array4D<T>& Array4D<T>::multid4(const valarray<T>& vmulti){
2192  for (size_t k(0); k< d4; ++k) {
2193  for (size_t i(k*d1*d2*d3); i< (k+1)*d1*d2*d3; ++i ){
2194  (*v)[i] *= vmulti[k];
2195  }
2196  }
2197  //for(size_t l(0); l< d4; ++l) {
2198  // for(GSlice_iter<T> it(d4c(l,l)); it!=it.end(); ++it) *it *= vmulti[l];
2199  //}
2200  return *this;
2201 }
2202 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2203 
2204 // B(j,k,l) multiplies every A(i,j,k,l)
2205 template<class T> Array4D<T>& Array4D<T>::multid2d3d4(const Array3D<T>& vd2d3d4){
2206  for (size_t j(0); j < d2*d3*d4; ++j ){
2207  for (size_t i(j*d1); i< (j+1)*d1; ++i ){
2208  (*v)[i] *= vd2d3d4.array()[j];
2209  }
2210  }
2211  return *this;
2212 }
2213 
2214 //--------------------------------------------------------------
2215 // Central difference
2216 //--------------------------------------------------------------
2217 // (minus) Central difference for contiguous elements
2218 template<class T> Array4D<T>& Array4D<T>::Dd1(){
2219  for(long i(0); i< dim()-2; ++i) {
2220  (*v)[i] -= (*v)[i+2];
2221  }
2222  for(long i(dim()-3); i>-1; --i) {
2223  (*v)[i+1] = (*v)[i];
2224  }
2225  return *this;
2226 }
2227 
2228 // (minus) Central difference in the d2 direction
2229 template<class T> Array4D<T>& Array4D<T>::Dd2(){
2230  long twod1 = 2*d1;
2231  for(long i(0); i< dim()-twod1; ++i) {
2232  (*v)[i] -= (*v)[i+twod1];
2233  }
2234  for(long i(dim()-twod1-1); i>-1; --i) {
2235  (*v)[i+d1] = (*v)[i];
2236  }
2237  return *this;
2238 }
2239 
2240 // (minus) Central difference in the d3 direction
2241 template<class T> Array4D<T>& Array4D<T>::Dd3() {
2242  long twod1d2 = 2*d1d2;
2243  for(long i(0); i< dim()-twod1d2; ++i) {
2244  (*v)[i] -= (*v)[i+twod1d2];
2245  }
2246  for(long i(dim()-twod1d2-1); i>-1; --i) {
2247  (*v)[i+d1d2] = (*v)[i];
2248  }
2249  return *this;
2250 }
2251 
2252 // (minus) Central difference in the d4 direction
2253 template<class T> Array4D<T>& Array4D<T>::Dd4() {
2254  long twod1d2d3 = 2*d1d2d3;
2255  for(long i(0); i< dim()-twod1d2d3; ++i) {
2256  (*v)[i] -= (*v)[i+twod1d2d3];
2257  }
2258  for(long i(dim()-twod1d2d3-1); i>-1; --i) {
2259  (*v)[i+d1d2d3] = (*v)[i];
2260  }
2261  return *this;
2262 }
2263 
2264 
2265 // Remove data for N cells from dimension 1
2266 template<class T> Array4D<T>& Array4D<T>::Filterd1(size_t N) {
2267  for (size_t j(0); j < d2*d3*d4; ++j ){
2268  for (size_t i(j*d1); i< j*d1+N; ++i ){
2269  (*v)[i] = 0.0;
2270  }
2271  }
2272  return *this;
2273 }
2274 //--------------------------------------------------------------
2275 //**************************************************************
2276 
2277 
2278 
2279 //**************************************************************
2280 // 4D Array Class
2281 //**************************************************************
2282 // Using Stroustrup's matrices p672-p673
2283 // This container is similar to Fortran-style arrays.
2284 // Custom operations, no standard Matrix algebra.
2285 // No error-checking
2286 // Compile with -ftree-vectorize
2287 //--------------------------------------------------------------
2288 template<class T> class Array4D_cmplx {
2289 //--------------------------------------------------------------
2290 // 4D Array decleration
2291 //--------------------------------------------------------------
2292 
2293 private:
2294  valarray<T> *v;
2295  size_t d1, d2, d3, d4; // For 3d VFP: p, x, y, z
2296  size_t td1;
2297  size_t td1d2;
2298  size_t td1d2d3;
2299 
2300 public:
2301 // Constructors/Destructors
2302  Array4D_cmplx(size_t x, size_t y, size_t z, size_t w);
2303  Array4D_cmplx(const Array4D_cmplx& other);
2304  ~Array4D_cmplx();
2305 
2306 // Basic Info
2307  size_t dim() const {return d1*d2*d3*d4;}
2308  size_t dim1() const {return d1;}
2309  size_t dim2() const {return d2;}
2310  size_t dim3() const {return d3;}
2311  size_t dim4() const {return d4;}
2312  valarray<T>& array() const {return *v;};
2313 
2314 // Access
2315  T& operator[](size_t i); // 1D-style
2316  T operator[](size_t i) const;
2317 
2318  T& real(size_t i,size_t j,size_t k,size_t l); // 1D-style
2319  T real(size_t i,size_t j,size_t k,size_t l) const;
2320  T& imag(size_t i,size_t j,size_t k,size_t l); // 1D-style
2321  T imag(size_t i,size_t j,size_t k,size_t l) const;
2322 
2323 //TODO vector<T> d2d3d4c(size_t j);
2324 
2325 // Slice iterators
2326  GSlice_iter<T> d1c(size_t b, size_t e);
2327  GSlice_iter<T> d2c(size_t b, size_t e);
2328  GSlice_iter<T> d3c(size_t b, size_t e);
2329  GSlice_iter<T> d4c(size_t b, size_t e);
2330  GSlice_iter<T> SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw);
2331 
2332 // Constant slice iterators
2333  CGSlice_iter<T> d1c(size_t b, size_t e) const;
2334  CGSlice_iter<T> d2c(size_t b, size_t e) const;
2335  CGSlice_iter<T> d3c(size_t b, size_t e) const;
2336  CGSlice_iter<T> d4c(size_t b, size_t e) const;
2337  CGSlice_iter<T> SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw) const;
2338 
2339 // Operators
2340  Array4D_cmplx& operator=(const T& d);
2341  Array4D_cmplx& operator=(const complex<T>& c);
2342  Array4D_cmplx& operator=(const Array4D<T>& other);
2343  Array4D_cmplx& operator=(const Array4D_cmplx& other);
2344  Array4D_cmplx& operator*=(const T& d);
2345  Array4D_cmplx& operator*=(const complex<T>& c);
2346  Array4D_cmplx& operator*=(const Array4D<T>& vmulti);
2347  Array4D_cmplx& operator*=(const Array4D_cmplx& vmulti);
2348  Array4D_cmplx& operator+=(const T& d);
2349  Array4D_cmplx& operator+=(const complex<T>& c);
2350  Array4D_cmplx& operator+=(const Array4D<T>& vadd);
2351  Array4D_cmplx& operator+=(const Array4D_cmplx& vadd);
2352  Array4D_cmplx& operator-=(const T& d);
2353  Array4D_cmplx& operator-=(const complex<T>& c);
2354  Array4D_cmplx& operator-=(const Array4D<T>& vmin);
2355  Array4D_cmplx& operator-=(const Array4D_cmplx& vmin);
2356 
2357 // Array * Vector
2358  Array4D_cmplx& multid1(const valarray<T>& vmulti); // M*valarray(d1)
2359  Array4D_cmplx& multid1(const valarray< complex<T> >& vmulti); // M*valarray(d1)
2360  Array4D_cmplx& multid2(const valarray<T>& vmulti); // M*valarray(d2)
2361  Array4D_cmplx& multid2(const valarray< complex<T> >& vmulti); // M*valarray(d2)
2362  Array4D_cmplx& multid3(const valarray<T>& vmulti); // M*valarray(d3)
2363  Array4D_cmplx& multid3(const valarray< complex<T> >& vmulti);// M*valarray(d3)
2364  Array4D_cmplx& multid4(const valarray<T>& vmulti); // M*valarray(d4)
2365  Array4D_cmplx& multid4(const valarray< complex<T> >& vmulti);// M*valarray(d4)
2366 
2367 // Array4D * Array3D
2368  Array4D_cmplx& multid2d3d4(const Array3D<T>& vd2d3d4);
2369  Array4D_cmplx& multid2d3d4(const Array3D_cmplx<T>& vd2d3d4);
2370 
2371 // Central difference
2372  Array4D_cmplx& Dd1(); // in the direction d1
2373  Array4D_cmplx& Dd2(); // in the direction d2
2374  Array4D_cmplx& Dd3(); // in the direction d3
2375  Array4D_cmplx& Dd4(); // in the direction d3
2376 
2377 // Filter first N-cells in d1 direction
2378  Array4D_cmplx& Filterd1(size_t N);
2379 };
2380 //--------------------------------------------------------------
2381 
2382 //--------------------------------------------------------------
2383 // Constructor and Destructor
2384 //--------------------------------------------------------------
2385 // Constructor
2386 template<class T> Array4D_cmplx<T>::
2387 Array4D_cmplx(size_t x,size_t y,size_t z,size_t w) : d1(x), d2(y), d3(z), d4(w) {
2388  v = new valarray<T>(2*d1*d2*d3*d4);
2389  td1 = 2*d1;
2390  td1d2 = 2*d1*d2;
2391  td1d2d3 = 2*d1*d2*d3;
2392 }
2393 // Copy constructor
2394 template<class T> Array4D_cmplx<T>:: Array4D_cmplx(const Array4D_cmplx& other){
2395  d1 = other.dim1();
2396  d2 = other.dim2();
2397  d3 = other.dim3();
2398  d4 = other.dim4();
2399  td1 = 2*d1;
2400  td1d2 = 2*d1*d2;
2401  td1d2d3 = 2*d1*d2*d3;
2402  v = new valarray<T>(2*d1*d2*d3*d4);
2403  (*v) = other.array();
2404 }
2405 // Destructor
2407  delete v;
2408 }
2409 
2410 //--------------------------------------------------------------
2411 // Access
2412 //--------------------------------------------------------------
2413 // 1D style access
2414 template<class T> inline T& Array4D_cmplx<T>::operator[] (size_t i){
2415  return (*v)[i];
2416 }
2417 // 1D style const access
2418 template<class T> inline T Array4D_cmplx<T>::operator[] (size_t i) const {
2419  return (*v)[i];
2420 }
2421 // Access real part by reference
2422 template<class T> inline T& Array4D_cmplx<T>::real(size_t i,size_t j,size_t k,size_t l){
2423  return (*v)[2*i+j*td1+k*td1d2+l*td1d2d3];
2424 }
2425 // Const access of real part
2426 template<class T> inline T Array4D_cmplx<T>::real(size_t i,size_t j,size_t k,size_t l) const{
2427  return (*v)[2*i+j*td1+k*td1d2+l*td1d2d3];
2428 }
2429 // access of imag part
2430 template<class T> inline T& Array4D_cmplx<T>::imag(size_t i,size_t j,size_t k,size_t l){
2431  return (*v)[2*i+1+j*td1+k*td1d2+l*td1d2d3];
2432 }
2433 // Const access of imag part
2434 template<class T> inline T Array4D_cmplx<T>::imag(size_t i,size_t j,size_t k,size_t l) const{
2435  return (*v)[2*i+1+j*td1+k*td1d2+l*td1d2d3];
2436 }
2437 //--------------------------------------------------------------
2438 // Slicers
2439 //--------------------------------------------------------------
2440 
2441 // slices (cubes) for given d1 value range
2442 template<class T>
2443 inline GSlice_iter<T> Array4D_cmplx<T>::d1c(size_t b, size_t e){
2444  valarray<size_t> sz(5), str(5);
2445  str[4] = 1, str[3] = td1; str[2] = td1d2; str[1] = td1d2d3; str[0] = 2;
2446  sz[4] = 2, sz[3] = d2; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2447  return GSlice_iter<T>(v,gslice(2*b,sz,str));
2448 }
2449 // const slices (cubes) for given d1 value range
2450 template<class T>
2451 inline CGSlice_iter<T> Array4D_cmplx<T>::d1c(size_t b, size_t e) const{
2452  valarray<size_t> sz(5), str(5);
2453  str[4] = 1, str[3] = td1; str[2] = td1d2; str[1] = td1d2d3; str[0] = 2;
2454  sz[4] = 2, sz[3] = d2; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2455  return CGSlice_iter<T>(v,gslice(2*b,sz,str));
2456 }
2457 // slices (cubes) for given d2 value range
2458 template<class T>
2459 inline GSlice_iter<T> Array4D_cmplx<T>::d2c(size_t b, size_t e){
2460  valarray<size_t> sz(4), str(4);
2461  str[3] = 1; str[2] = td1d2; str[1] = td1d2d3; str[0] = td1;
2462  sz[3] = td1; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2463  return GSlice_iter<T>(v,gslice(b*td1,sz,str));
2464 }
2465 // const slices (cubes) for given d2 value range
2466 template<class T>
2467 inline CGSlice_iter<T> Array4D_cmplx<T>::d2c(size_t b, size_t e) const{
2468  valarray<size_t> sz(4), str(4);
2469  str[3] = 1; str[2] = td1d2; str[1] = td1d2d3; str[0] = td1;
2470  sz[3] = td1; sz[2] = d3; sz[1] = d4; sz[0] = e-b+1;
2471  return CGSlice_iter<T>(v,gslice(b*td1,sz,str));
2472 }
2473 // slices (cubes) for given d3 value range
2474 template<class T>
2475 inline GSlice_iter<T> Array4D_cmplx<T>::d3c(size_t b, size_t e){
2476  valarray<size_t> sz(3), str(3);
2477  str[2] = 1; str[1] = td1d2d3; str[0] = td1d2;
2478  sz[2] = td1d2; sz[1] = d4; sz[0] = e-b+1;
2479  return GSlice_iter<T>(v,gslice(b*td1d2,sz,str));
2480 }
2481 // const slices (cubes) for given d3 value range
2482 template<class T>
2483 inline CGSlice_iter<T> Array4D_cmplx<T>::d3c(size_t b, size_t e) const{
2484  valarray<size_t> sz(3), str(3);
2485  str[2] = 1; str[1] = td1d2d3; str[0] = td1d2;
2486  sz[2] = td1d2; sz[1] = d4; sz[0] = e-b+1;
2487  return CGSlice_iter<T>(v,gslice(b*td1d2,sz,str));
2488 }
2489 // slices (cubes) for given d4 value range
2490 template<class T>
2491 inline GSlice_iter<T> Array4D_cmplx<T>::d4c(size_t b, size_t e) {
2492  valarray<size_t> sz(2), str(2);
2493  str[1] = 1; str[0] = td1d2d3;
2494  sz[1] = td1d2d3; sz[0] = e-b+1;
2495  return GSlice_iter<T>(v,gslice(b*td1d2d3,sz,str));
2496 }
2497 // const slices (cubes) for given d4 value range
2498 template<class T>
2499 inline CGSlice_iter<T> Array4D_cmplx<T>::d4c(size_t b, size_t e) const {
2500  valarray<size_t> sz(2), str(2);
2501  str[1] = 1; str[0] = td1d2d3;
2502  sz[1] = td1d2d3; sz[0] = e-b+1;
2503  return CGSlice_iter<T>(v,gslice(b*td1d2d3,sz,str));
2504 }
2505 
2506 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------
2507 
2508 // Generate Subarray
2509 template<class T>
2511 SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw){
2512  valarray<size_t> sz(4), str(4);
2513  str[3] = 1; str[2] = td1; str[1] = td1d2; str[0] = td1d2d3;
2514  sz[3] = 2*nx; sz[2] = ny; sz[1] = nz; sz[0] = nw;
2515  return GSlice_iter<T>(v,gslice(2*st,sz,str));
2516 }
2517 
2518 // Generate Subarray
2519 template<class T>
2521 SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw) const{
2522  valarray<size_t> sz(4), str(4);
2523  str[3] = 1; str[2] = td1; str[1] = td1d2; str[0] = td1d2d3;
2524  sz[3] = 2*nx; sz[2] = ny; sz[1] = nz; sz[0] = nw;
2525  return CGSlice_iter<T>(v,gslice(2*st,sz,str));
2526 }
2527 
2528 //--------------------------------------------------------------
2529 // Operators
2530 //--------------------------------------------------------------
2531 // Copy assignment operator
2532 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator=(const T& d){
2533  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2534  (*v)[i] = d;
2535  (*v)[i+1] = 0.0;
2536  }
2537  return *this;
2538 }
2539 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator=(const complex<T>& c){
2540  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2541  (*v)[i] =c.real();
2542  (*v)[i+1] =c.imag();
2543  }
2544  return *this;
2545 }
2547  for (size_t i(0); i< d1*d2*d3*d4; ++i) {
2548  (*v)[2*i] = other.array()[i];
2549  (*v)[2*i+1] = 0.0;
2550  }
2551  return *this;
2552 }
2554  if (this != &other) { //self-assignment
2555  (*v) = other.array();
2556  }
2557  return *this;
2558 }
2559 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2560 
2561 // *=
2562 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator*=(const T& d){
2563  (*v) *=d;
2564  return *this;
2565 }
2566 // *=
2567 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator*=(const complex<T>& c){
2568  for (size_t i(0); i< td1*d2*d3*d4; i+=2) { // suppose v[i]+iv[i+1]=A+iB, c=a+ib
2569  T vi((*v)[i]*c.imag());
2570  (*v)[i] *= c.real(); // v[i] = Aa
2571  (*v)[i] -= (*v)[i+1]*c.imag(); // v[i] = Aa - Bb
2572  (*v)[i+1] *= c.real(); // v[i+1] = Ba
2573  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
2574  }
2575  return *this;
2576 }
2577 // *=
2579  for (size_t i(0); i< d1*d2*d3*d4; ++i) {
2580  (*v)[2*i] *= vmulti.array()[i];
2581  (*v)[2*i+1] *= vmulti.array()[i];
2582  }
2583  return *this;
2584 }
2585 // *=
2587  for (size_t i(0); i< td1*d2*d3*d4; i+=2) { // suppose v[i]+iv[i+1]=A+iB, vmulti[i] + ivmulti[i+1] = a+ib
2588  T vi((*v)[i] * vmulti.array()[i+1]);
2589  (*v)[i] *= vmulti.array()[i]; // v[i] = Aa
2590  (*v)[i] -= (*v)[i+1]*vmulti.array()[i+1]; // v[i] = Aa - Bb
2591  (*v)[i+1] *= vmulti.array()[i]; // v[i+1] = Ba
2592  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
2593  }
2594  return *this;
2595 }
2596 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2597 
2598 // +=
2599 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator+=(const T& d){
2600  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2601  (*v)[i] +=d;
2602  }
2603  return *this;
2604 }
2605 // +=
2606 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator+=(const complex<T>& c){
2607  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2608  (*v)[i] +=c.real();
2609  (*v)[i+1] +=c.imag();
2610  }
2611  return *this;
2612 }
2613 // +=
2615  for (size_t i(0); i< d1*d2*d3*d4; ++i) {
2616  (*v)[2*i] += vadd.array()[i];
2617  }
2618  return *this;
2619 }
2620 // +=
2622  (*v) += vadd.array();
2623  return *this;
2624 }
2625 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2626 
2627 // -=
2628 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator-=(const T& d){
2629  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2630  (*v)[i] -=d;
2631  }
2632  return *this;
2633 }
2634 // -=
2635 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::operator-=(const complex<T>& c){
2636  for (size_t i(0); i< td1*d2*d3*d4; i+=2) {
2637  (*v)[i] -=c.real();
2638  (*v)[i+1] -=c.imag();
2639  }
2640  return *this;
2641 }
2642 // -=
2644  for (size_t i(0); i< d1*d2*d3*d4; ++i) {
2645  (*v)[2*i] -= vmin.array()[i];
2646  }
2647  return *this;
2648 }
2649 // -=
2651  (*v) -= vmin.array();
2652  return *this;
2653 }
2654 
2655 //--------------------------------------------------------------
2656 // Array4D * Vector
2657 //--------------------------------------------------------------
2658 // Vector multiplies every d1-length of Array4D
2659 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid1(const valarray<T>& vmulti){
2660  for (size_t j(0); j< 2*dim(); j+= td1 ){
2661  for (size_t i(0); i< d1; ++i ){
2662  (*v)[2*i+j] *= vmulti[i];
2663  (*v)[2*i+1+j] *= vmulti[i];
2664  }
2665  }
2666  return *this;
2667 }
2668 // Vector multiplies every d1-length of Array4D
2669 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid1(const valarray< complex<T> >& vmulti){
2670  for (size_t j(0); j< 2*dim(); j+=td1 ){
2671  for (size_t i(0); i< d1; ++i ){
2672  T vi((*v)[2*i+j]*vmulti[i].imag());
2673  (*v)[2*i+j] *= vmulti[i].real(); // v[i] = Aa
2674  (*v)[2*i+j] -= (*v)[2*i+1+j] * vmulti[i].imag(); // v[i] = Aa - Bb
2675  (*v)[2*i+1+j] *= vmulti[i].real(); // v[i+1] = Ba
2676  (*v)[2*i+1+j] += vi; // v[i+1] = Ba + Ab
2677  }
2678  }
2679  return *this;
2680 }
2681 
2682 // Vector multiplies every d2-length of Array4D
2683 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid2(const valarray<T>& vmulti){
2684  for (size_t k(0); k< 2*dim(); k+=td1*d2 ) {
2685  for (size_t j(0); j< d2; ++j ) {
2686  for (size_t i(j*td1); i< (j+1)*td1; ++i ){
2687  (*v)[i+k] *= vmulti[j];
2688  }
2689  }
2690  }
2691  return *this;
2692 }
2693 // Vector multiplies every d2-length of Array4D
2694 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid2(const valarray< complex<T> >& vmulti){
2695  for (size_t k(0); k< 2*dim(); k+=td1*d2 ) {
2696  for (size_t j(0); j< d2; ++j ) {
2697  for (size_t i(j*td1); i< (j+1)*td1; i+=2 ){
2698  T vi((*v)[i+k]* vmulti[j].imag());
2699  (*v)[i+k] *= vmulti[j].real(); // v[i] = Aa
2700  (*v)[i+k] -= (*v)[i+k+1] * vmulti[j].imag(); // v[i] = Aa - Bb
2701  (*v)[i+k+1] *= vmulti[j].real(); // v[i+1] = Ba
2702  (*v)[i+k+1] += vi; // v[i+1] = Ba + Ab
2703  }
2704  }
2705  }
2706  return *this;
2707 }
2708 
2709 // Vector multiplies every d3-length of Array4D
2710 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid3(const valarray<T>& vmulti){
2711  for (size_t l(0); l< 2*dim(); l+=td1*d2*d3) {
2712  for (size_t k(0); k< d3; ++k) {
2713  for (size_t i(k*td1*d2); i< (k+1)*td1*d2; ++i ){
2714  (*v)[i+l] *= vmulti[k];
2715  }
2716  }
2717  }
2718  return *this;
2719 }
2720 // Vector multiplies every d3-length of Array4D
2721 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid3(const valarray< complex<T> >& vmulti){
2722  for (size_t l(0); l< 2*dim(); l+=td1*d2*d3) {
2723  for (size_t k(0); k< d3; ++k) {
2724  for (size_t i(k*td1*d2); i< (k+1)*td1*d2; i+=2 ){
2725  T vi((*v)[i+l]* vmulti[k].imag());
2726  (*v)[i+l] *= vmulti[k].real(); // v[i] = Aa
2727  (*v)[i+l] -= (*v)[i+l+1] * vmulti[k].imag(); // v[i] = Aa - Bb
2728  (*v)[i+l+1] *= vmulti[k].real(); // v[i+1] = Ba
2729  (*v)[i+l+1] += vi; // v[i+1] = Ba + Ab
2730  }
2731  }
2732  }
2733  return *this;
2734 }
2735 
2736 // Vector multiplies every d4-length of Array4D
2737 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid4(const valarray<T>& vmulti){
2738  for (size_t k(0); k< d4; ++k) {
2739  for (size_t i(k*td1*d2*d3); i< (k+1)*td1*d2*d3; ++i ){
2740  (*v)[i] *= vmulti[k];
2741  }
2742  }
2743  return *this;
2744 }
2745 // Vector multiplies every d4-length of Array4D
2746 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid4(const valarray< complex<T> >& vmulti){
2747  for (size_t k(0); k< d4; ++k) {
2748  for (size_t i(k*td1*d2*d3); i< (k+1)*td1*d2*d3; i+=2 ){
2749  T vi((*v)[i]* vmulti[k].imag());
2750  (*v)[i] *= vmulti[k].real(); // v[i] = Aa
2751  (*v)[i] -= (*v)[i+1] * vmulti[k].imag(); // v[i] = Aa - Bb
2752  (*v)[i+1] *= vmulti[k].real(); // v[i+1] = Ba
2753  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
2754  }
2755  }
2756  return *this;
2757 }
2758 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2759 
2760 // B(j,k) multiplies every A(i,j,k)
2761 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::multid2d3d4(const Array3D<T>& vd2d3d4){
2762  for (size_t j(0); j < d2*d3*d4; ++j ){
2763  for (size_t i(j*td1); i< (j+1)*td1; ++i ){
2764  (*v)[i] *= vd2d3d4.array()[j];
2765  }
2766  }
2767  return *this;
2768 }
2769 
2770 
2771 // B(j,k) multiplies every A(i,j,k)
2773  for (size_t j(0); j < d2*d3*d4; ++j ){
2774  for (size_t i(j*td1); i< (j+1)*td1; i+=2 ){
2775  T vi((*v)[i]*vd2d3d4.array()[2*j+1]);
2776  (*v)[i] *= vd2d3d4.array()[2*j]; // v[i] = Aa
2777  (*v)[i] -= (*v)[i+1]*vd2d3d4.array()[2*j+1]; // v[i] = Aa - Bb
2778  (*v)[i+1] *= vd2d3d4.array()[2*j]; // v[i+1] = Ba
2779  (*v)[i+1] += vi; // v[i+1] = Ba + Ab
2780  }
2781  }
2782  return *this;
2783 }
2784 
2785 //--------------------------------------------------------------
2786 // Central difference
2787 //--------------------------------------------------------------
2788 // (minus) Central difference for contiguous elements
2790  for(long i(0); i< 2*dim()-4; ++i) {
2791  (*v)[i] -= (*v)[i+4];
2792  }
2793  for(long i(2*dim()-5); i>-1; --i) {
2794  (*v)[i+2] = (*v)[i];
2795  }
2796  return *this;
2797 }
2798 
2799 // (minus) Central difference in the d2 direction
2801  long twotd1 = 2*td1;
2802  for(long i(0); i< 2*dim()-twotd1; ++i) {
2803  (*v)[i] -= (*v)[i+twotd1];
2804  }
2805  for(long i(2*dim()-twotd1-1); i>-1; --i) {
2806  (*v)[i+td1] = (*v)[i];
2807  }
2808  return *this;
2809 }
2810 
2811 // (minus) Central difference in the d3 direction
2813  long twotd1d2 = 2*td1d2;
2814  for(long i(0); i< 2*dim()-twotd1d2; ++i) {
2815  (*v)[i] -= (*v)[i+twotd1d2];
2816  }
2817  for(long i(2*dim()-twotd1d2-1); i>-1; --i) {
2818  (*v)[i+td1d2] = (*v)[i];
2819  }
2820  return *this;
2821 }
2822 
2823 // (minus) Central difference in the d3 direction
2825  long twotd1d2d3 = 2*td1d2d3;
2826  for(long i(0); i< long(2*dim())-twotd1d2d3; ++i) {
2827  (*v)[i] -= (*v)[i+twotd1d2d3];
2828  }
2829  for(long i(2*dim()-twotd1d2d3-1); i>-1; --i) {
2830  (*v)[i+td1d2d3] = (*v)[i];
2831  }
2832  return *this;
2833 }
2834 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2835 
2836 // Remove data for N cells from dimension 1
2837 template<class T> Array4D_cmplx<T>& Array4D_cmplx<T>::Filterd1(size_t N) {
2838  for (size_t j(0); j < d2*d3*d4; ++j ){
2839  for (size_t i(j*td1); i< j*td1+2*N; ++i ){
2840  (*v)[i] = 0.0;
2841  }
2842  }
2843  return *this;
2844 }
2845 //--------------------------------------------------------------
2846 //**************************************************************
2847 
2848 
2849 #endif
valarray< T > * v
Definition: lib-array.h:629
Array3D & Dd2()
Definition: lib-array.h:1336
Array4D_cmplx & multid4(const valarray< T > &vmulti)
Definition: lib-array.h:2737
Array4D & multid4(const valarray< T > &vmulti)
Definition: lib-array.h:2191
size_t dim() const
Definition: lib-array.h:1897
size_t dim() const
Definition: lib-array.h:288
Array3D_cmplx & operator+=(const T &d)
Definition: lib-array.h:1658
friend bool operator!=(const CGSlice_iter &p, const CGSlice_iter &q)
Definition: lib-array.h:248
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:1162
GSlice_iter< T > d4c(size_t b, size_t e)
Definition: lib-array.h:2062
valarray< T > & array() const
Definition: lib-array.h:1056
size_t curr
Definition: lib-array.h:182
Array3D_cmplx & operator*=(const T &d)
Definition: lib-array.h:1621
Array2D_cmplx & Dd1()
Definition: lib-array.h:987
CGSlice_iter & operator++()
Definition: lib-array.h:197
Array4D & operator+=(const T &d)
Definition: lib-array.h:2125
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:2014
size_t d2
Definition: lib-array.h:279
Array2D & operator-=(const T &d)
Definition: lib-array.h:467
Array4D_cmplx & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:2683
size_t dim1() const
Definition: lib-array.h:2308
Array3D_cmplx & Filterd1(size_t N)
Definition: lib-array.h:1859
~Array3D()
Definition: lib-array.h:1126
GSlice_iter< T > SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw)
Definition: lib-array.h:2081
valarray< T > * v
Definition: lib-array.h:1384
Array4D & Filterd1(size_t N)
Definition: lib-array.h:2266
bool operator==(const GSlice_iter< T > &, const GSlice_iter< T > &)
Definition: lib-array.h:136
size_t dim() const
Definition: lib-array.h:1052
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:752
GSlice_iter< T > SubArray4D(size_t st, size_t nx, size_t ny, size_t nz, size_t nw)
Definition: lib-array.h:2511
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:384
size_t dim3() const
Definition: lib-array.h:1900
size_t dim1() const
Definition: lib-array.h:641
valarray< size_t > gsizes
Definition: lib-array.h:183
Array4D & Dd2()
Definition: lib-array.h:2229
Array2D & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:490
Array2D & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:480
GSlice_iter< T > d3c(size_t b, size_t e)
Definition: lib-array.h:1194
size_t td1
Definition: lib-array.h:631
Array2D_cmplx & Dd2()
Definition: lib-array.h:1003
Array2D & operator*=(const T &d)
Definition: lib-array.h:447
Array3D_cmplx(size_t x, size_t y, size_t z)
Definition: lib-array.h:1469
friend bool operator==(const GSlice_iter &p, const GSlice_iter &q)
Definition: lib-array.h:136
GSlice_iter< T > d2c(size_t b, size_t e)
Definition: lib-array.h:2030
valarray< T > * v
Definition: lib-array.h:1885
size_t d1
Definition: lib-array.h:1886
CGSlice_iter(valarray< T > *vv, gslice gss)
Definition: lib-array.h:227
Array3D & Dd1()
Definition: lib-array.h:1325
size_t dim3() const
Definition: lib-array.h:1055
GSlice_iter< T > d2c(size_t b, size_t e)
Definition: lib-array.h:2459
GSlice_iter operator++(int)
Definition: lib-array.h:96
Array4D_cmplx & operator=(const T &d)
Definition: lib-array.h:2532
Array4D & Dd1()
Definition: lib-array.h:2218
Array4D & operator=(const T &d)
Definition: lib-array.h:2102
size_t dim1() const
Definition: lib-array.h:289
size_t d1d2d3
Definition: lib-array.h:1888
CGSlice_iter operator++(int)
Definition: lib-array.h:198
Array4D_cmplx & Dd3()
Definition: lib-array.h:2812
Array3D_cmplx & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:1743
size_t dim() const
Definition: lib-array.h:2307
size_t dim() const
Definition: lib-array.h:640
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:1521
size_t d3
Definition: lib-array.h:1042
size_t dim3() const
Definition: lib-array.h:2310
Array2D & Dd2()
Definition: lib-array.h:556
size_t dim2() const
Definition: lib-array.h:290
Array4D & multid2d3d4(const Array3D< T > &vd2d3d4)
Definition: lib-array.h:2205
valarray< T > * v
Definition: lib-array.h:2294
size_t curr
Definition: lib-array.h:80
size_t dim2() const
Definition: lib-array.h:1054
GSlice_iter< T > d3c(size_t b, size_t e)
Definition: lib-array.h:2475
size_t dim2() const
Definition: lib-array.h:2309
Array4D_cmplx(size_t x, size_t y, size_t z, size_t w)
Definition: lib-array.h:2387
Array3D & operator-=(const T &d)
Definition: lib-array.h:1266
Array4D & multid3(const valarray< T > &vmulti)
Definition: lib-array.h:2176
size_t dim1() const
Definition: lib-array.h:1053
~Array4D()
Definition: lib-array.h:1979
T & operator*()
Definition: lib-array.h:100
T & operator[](size_t i)
Definition: lib-array.h:1493
valarray< size_t > gsizes
Definition: lib-array.h:81
Array4D_cmplx & Dd4()
Definition: lib-array.h:2824
size_t dim() const
Definition: lib-array.h:1396
size_t dim2() const
Definition: lib-array.h:1899
Array4D & operator*=(const T &d)
Definition: lib-array.h:2115
Array4D & operator-=(const T &d)
Definition: lib-array.h:2135
T & imag(size_t i, size_t j)
Definition: lib-array.h:740
Array2D(size_t x, size_t y)
Definition: lib-array.h:337
Array3D & Dd3()
Definition: lib-array.h:1348
const T & operator[](size_t i) const
Definition: lib-array.h:200
size_t d2
Definition: lib-array.h:1886
T & operator()(size_t i)
Definition: lib-array.h:99
valarray< T > & array() const
Definition: lib-array.h:643
size_t dim4() const
Definition: lib-array.h:2311
size_t d1
Definition: lib-array.h:279
GSlice_iter< T > d2c(size_t b, size_t e)
Definition: lib-array.h:1537
Array4D & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:2161
size_t d1
Definition: lib-array.h:1042
bool operator!=(const GSlice_iter< T > &, const GSlice_iter< T > &)
Definition: lib-array.h:146
~Array2D()
Definition: lib-array.h:348
size_t dim2() const
Definition: lib-array.h:642
Array2D_cmplx & operator=(const T &d)
Definition: lib-array.h:804
T & operator[](size_t i)
Definition: lib-array.h:98
valarray< T > & array() const
Definition: lib-array.h:1902
valarray< T > & array() const
Definition: lib-array.h:291
Array3D & multid2d3(const Array2D< T > &vd2d3)
Definition: lib-array.h:1311
size_t d3
Definition: lib-array.h:1886
Array4D(size_t x, size_t y, size_t z, size_t w)
Definition: lib-array.h:1962
T & operator()(size_t i, size_t j, size_t k, size_t l)
Definition: lib-array.h:1989
size_t dim4() const
Definition: lib-array.h:1901
size_t dim1() const
Definition: lib-array.h:1898
T & real(size_t i, size_t j, size_t k, size_t l)
Definition: lib-array.h:2422
Array4D & Dd3()
Definition: lib-array.h:2241
T & operator[](size_t i)
Definition: lib-array.h:724
valarray< T > & array() const
Definition: lib-array.h:1400
GSlice_iter< T > d3c(size_t b, size_t e)
Definition: lib-array.h:2046
Array3D_cmplx & Dd1()
Definition: lib-array.h:1823
Array3D_cmplx & operator=(const T &d)
Definition: lib-array.h:1591
size_t dim2() const
Definition: lib-array.h:1398
Array2D_cmplx & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:931
Array4D_cmplx & operator+=(const T &d)
Definition: lib-array.h:2599
GSlice_iter< T > d2c(size_t b, size_t e)
Definition: lib-array.h:768
GSlice_iter< T > SubArray3D(size_t st, size_t nx, size_t ny, size_t nz)
Definition: lib-array.h:1212
valarray< T > * v
Definition: lib-array.h:180
const T & operator()(size_t i) const
Definition: lib-array.h:201
Array3D & multid3(const valarray< T > &vmulti)
Definition: lib-array.h:1300
T & operator()(size_t i, size_t j, size_t k)
Definition: lib-array.h:1136
Array4D_cmplx & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:2659
Array4D_cmplx & Dd1()
Definition: lib-array.h:2789
friend bool operator!=(const GSlice_iter &p, const GSlice_iter &q)
Definition: lib-array.h:146
size_t td1d2
Definition: lib-array.h:2297
Array3D_cmplx & multid2d3(const Array2D< T > &vd2d3)
Definition: lib-array.h:1796
Array3D & operator*=(const T &d)
Definition: lib-array.h:1246
Array2D_cmplx(size_t x, size_t y)
Definition: lib-array.h:703
Array2D_cmplx & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:955
Array4D_cmplx & Filterd1(size_t N)
Definition: lib-array.h:2837
GSlice_iter< T > d3c(size_t b, size_t e)
Definition: lib-array.h:1553
valarray< T > & array() const
Definition: lib-array.h:2312
Array4D & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:2148
valarray< T > * v
Definition: lib-array.h:78
gslice gs
Definition: lib-array.h:181
GSlice_iter< T > SubArray2D(size_t st, size_t nx, size_t ny)
Definition: lib-array.h:784
valarray< T > * v
Definition: lib-array.h:278
size_t d2
Definition: lib-array.h:1042
Array3D_cmplx & operator-=(const T &d)
Definition: lib-array.h:1687
Array2D_cmplx & Filterd1(size_t N)
Definition: lib-array.h:1016
Array3D_cmplx & Dd3()
Definition: lib-array.h:1846
Array2D_cmplx & operator*=(const T &d)
Definition: lib-array.h:834
Array4D_cmplx & operator-=(const T &d)
Definition: lib-array.h:2628
GSlice_iter< T > SubArray2D(size_t st, size_t nx, size_t ny)
Definition: lib-array.h:416
Array2D & Dd1()
Definition: lib-array.h:507
GSlice_iter end() const
Definition: lib-array.h:89
T & real(size_t i, size_t j)
Definition: lib-array.h:732
size_t td1d2
Definition: lib-array.h:1387
GSlice_iter(valarray< T > *vv, gslice gss)
Definition: lib-array.h:125
Array3D_cmplx & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:1718
Array3D(size_t x, size_t y, size_t z)
Definition: lib-array.h:1112
friend bool operator==(const CGSlice_iter &p, const CGSlice_iter &q)
Definition: lib-array.h:238
GSlice_iter< T > d4c(size_t b, size_t e)
Definition: lib-array.h:2491
Array3D & multid1(const valarray< T > &vmulti)
Definition: lib-array.h:1278
Array2D & Filterd1(size_t N)
Definition: lib-array.h:604
Array4D_cmplx & multid3(const valarray< T > &vmulti)
Definition: lib-array.h:2710
Array4D_cmplx & multid2d3d4(const Array3D< T > &vd2d3d4)
Definition: lib-array.h:2761
size_t td1d2d3
Definition: lib-array.h:2298
const T & operator*() const
Definition: lib-array.h:202
Array3D & multid2(const valarray< T > &vmulti)
Definition: lib-array.h:1288
size_t dim1() const
Definition: lib-array.h:1397
Array3D_cmplx & multid3(const valarray< T > &vmulti)
Definition: lib-array.h:1771
const T & ref(size_t i) const
Definition: lib-array.h:213
T & ref(size_t i) const
Definition: lib-array.h:111
size_t dim3() const
Definition: lib-array.h:1399
Array2D_cmplx & operator-=(const T &d)
Definition: lib-array.h:900
valarray< T > * v
Definition: lib-array.h:1041
GSlice_iter< T > SubArray3D(size_t st, size_t nx, size_t ny, size_t nz)
Definition: lib-array.h:1571
gslice gs
Definition: lib-array.h:79
T & real(size_t i, size_t j, size_t k)
Definition: lib-array.h:1501
GSlice_iter< T > d2c(size_t b, size_t e)
Definition: lib-array.h:1178
T & operator()(size_t i, size_t j)
Definition: lib-array.h:356
T & imag(size_t i, size_t j, size_t k, size_t l)
Definition: lib-array.h:2430
size_t d1d2
Definition: lib-array.h:1043
Array3D & operator=(const T &d)
Definition: lib-array.h:1233
GSlice_iter & operator++()
Definition: lib-array.h:95
Array3D & operator+=(const T &d)
Definition: lib-array.h:1256
GSlice_iter< T > d1c(size_t b, size_t e)
Definition: lib-array.h:2443
Array4D_cmplx & operator*=(const T &d)
Definition: lib-array.h:2562
T & operator[](size_t i)
Definition: lib-array.h:2414
CGSlice_iter end() const
Definition: lib-array.h:191
T & imag(size_t i, size_t j, size_t k)
Definition: lib-array.h:1509
size_t d4
Definition: lib-array.h:1886
size_t d1d2
Definition: lib-array.h:1887
Array4D_cmplx & Dd2()
Definition: lib-array.h:2800
Array2D & operator=(const T &d)
Definition: lib-array.h:435
vector< T > d2c(size_t j)
Definition: lib-array.h:372
Array3D & Filterd1(size_t N)
Definition: lib-array.h:1361
Array2D & operator+=(const T &d)
Definition: lib-array.h:457
Array3D_cmplx & Dd2()
Definition: lib-array.h:1834
Array2D_cmplx & operator+=(const T &d)
Definition: lib-array.h:871
Array4D & Dd4()
Definition: lib-array.h:2253