source: XIOS/dev/dev_olga/src/extern/blitz/include/blitz/array/fastiter.h @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 13.8 KB
Line 
1// -*- C++ -*-
2/***************************************************************************
3 * blitz/array/fastiter.h  Declaration of FastArrayIterator<P_numtype,N_rank>
4 *
5 * $Id$
6 *
7 * Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
8 *
9 * This file is a part of Blitz.
10 *
11 * Blitz is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation, either version 3
14 * of the License, or (at your option) any later version.
15 *
16 * Blitz is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with Blitz.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 * Suggestions:          blitz-devel@lists.sourceforge.net
25 * Bugs:                 blitz-support@lists.sourceforge.net   
26 *
27 * For more information, please see the Blitz++ Home Page:
28 *    https://sourceforge.net/projects/blitz/
29 *
30 ****************************************************************************/
31#ifndef BZ_ARRAY_FASTITER_H
32#define BZ_ARRAY_FASTITER_H
33
34#include <blitz/blitz.h>
35#include <blitz/array/slice.h>
36#include <blitz/constpointerstack.h>
37#include <blitz/prettyprint.h>
38#include <blitz/simdtypes.h>
39#include <blitz/et-forward.h>
40#include <blitz/array/domain.h>
41#include <blitz/array/asexpr.h>
42
43#ifdef BZ_HAVE_STD
44 #include <sstream>
45#else
46 #include <strstream.h>
47#endif
48
49BZ_NAMESPACE(blitz)
50
51// Wrapper to turn expressions with FAIs to FACIs so they can be
52// returned from a function.
53template<typename T>
54typename T::T_range_result safeToReturn(const T& expr) {
55  return expr(expr.domain());
56}
57
58
59// forward declaration
60template<typename, int> class FastArrayIterator;
61template<typename, int> class FastArrayCopyIterator;
62
63
64template<typename P_numtype, int N_rank, typename P_arraytype>
65class FastArrayIteratorBase {
66public:
67  typedef P_numtype                T_numtype;
68  typedef typename opType<T_numtype>::T_optype T_optype;
69  // if T_numtype is POD, then T_result is T_numtype, but if T_numtype
70  // is an ET class, T_result will be the array class for that class.
71  typedef typename asET<T_numtype>::T_wrapped T_typeprop;
72  typedef typename unwrapET<T_typeprop>::T_unwrapped T_result;
73
74  /// Result type for fastRead_tv is a FastTVIterator.
75  typedef ETBase<FastTV2Iterator<T_numtype, 
76                                 simdTypes<T_numtype>::vecWidth> > T_tvtypeprop;
77  typedef typename unwrapET<T_tvtypeprop>::T_unwrapped T_tvresult;
78
79  typedef Array<T_numtype, N_rank> T_array;
80  typedef FastArrayIteratorBase<T_numtype, N_rank, P_arraytype> T_iterator;
81    typedef const T_array& T_ctorArg1;
82    typedef int            T_ctorArg2;    // dummy
83  typedef FastArrayCopyIterator<T_numtype, N_rank> T_range_result;
84
85    static const int 
86        numArrayOperands = 1, 
87        numTVOperands = 0, 
88        numTMOperands = 0,
89        numIndexPlaceholders = 0,
90      minWidth = simdTypes<T_numtype>::vecWidth,
91      maxWidth = simdTypes<T_numtype>::vecWidth,
92        rank_ = N_rank;
93
94  /** For an iterator, the vectorized result for width N is always a
95      TinyVector<T_numtype, N>. */
96  template<int N> struct tvresult {
97    typedef FastTV2Iterator<T_numtype, N> Type;
98  };
99
100    // NB: this ctor does NOT preserve stack and stride
101    // parameters.  This is for speed purposes.
102    FastArrayIteratorBase(const T_iterator& x)
103        : data_(x.data_), array_(x.array_)
104    { }
105
106    void operator=(const T_iterator& x)
107    {
108      // doesn't this copy the data in x.array_ and then make data_
109      // point to x's array? doesn't seem right
110        array_ = x.array_;
111        data_ = x.data_;
112        stack_ = x.stack_;
113        stride_ = x.stride_;
114    }
115
116    FastArrayIteratorBase(const T_array& array)
117        : array_(array)
118    {
119        data_   = array_.data();
120    }
121
122    ~FastArrayIteratorBase()
123    { }
124
125#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
126    T_result operator()(TinyVector<int, N_rank> i) const
127    { return array_(i); }
128#else
129    T_result operator()(const TinyVector<int, N_rank>& i) const
130    { return array_(i); }
131#endif
132
133    int ascending(const int rank) const
134    {
135        if (rank < N_rank)
136            return array_.isRankStoredAscending(rank);
137        else
138            return INT_MIN;   // tiny(int());
139    }
140
141    int ordering(const int rank) const
142    {
143        if (rank < N_rank)
144            return array_.ordering(rank);
145        else
146            return INT_MIN;   // tiny(int());
147    }
148
149    int lbound(const int rank) const
150    { 
151        if (rank < N_rank)
152            return array_.lbound(rank); 
153        else
154            return INT_MIN;   // tiny(int());
155    }
156
157    int ubound(const int rank) const
158    { 
159        if (rank < N_rank)
160            return array_.ubound(rank); 
161        else
162            return INT_MAX;   // huge(int());
163    }
164   
165    RectDomain<rank_> domain() const { return array_.domain(); };
166
167    T_result first_value() const { return *data_; }
168
169    T_result operator*() const
170    { return *data_; }
171
172  template<int N>
173  T_range_result operator()(const RectDomain<N>& d) const
174  {
175    return T_range_result(array_(d));
176  }
177
178    T_result operator[](int i) const
179    { return data_[i * stride_]; }
180
181    T_result fastRead(diffType i) const
182    { return data_[i]; }
183
184  /** Returns a TinyVector "view" of the data at i, with a vector
185      length specified by the template parameter N. This makes it
186      possible to convert a small part of an arbitrary expression into
187      a TinyVector expression, which is efficiently vectorized. */ 
188  template<int N>
189  typename tvresult<N>::Type fastRead_tv(diffType i) const
190  {
191    return typename tvresult<N>::Type(*reinterpret_cast<const TinyVector<T_numtype,N>*>(&data_[i])); }
192
193  /** Returns true if the iterator data is aligned on a simd
194      vector. */
195  bool isVectorAligned(diffType offset) const
196  { return simdTypes<T_numtype>::isVectorAligned(data_ + offset); };
197
198    int suggestStride(int rank) const
199    { return array_.stride(rank); }
200
201    bool isStride(int rank, diffType stride) const
202    { return array_.stride(rank) == stride; }
203
204    void push(int position)
205    {
206        stack_[position] = data_;
207    }
208 
209    void pop(int position)
210    { 
211        data_ = stack_[position];
212    }
213
214    void advance()
215    {
216      data_ += stride_;
217    }
218
219    void advance(int n)
220    {
221      data_ += n * stride_;
222    }
223
224    void loadStride(int rank)
225    {
226        stride_ = array_.stride(rank);
227    }
228
229  // returns the lvalue, ie a pointer to the data
230    const T_numtype * restrict data() const
231    { return data_; }
232
233  const T_array& array() const
234  { return array_; }
235
236    void _bz_setData(const T_numtype* ptr)
237    { data_ = ptr; }
238
239    // this is needed for the stencil expression fastRead to work
240    void _bz_offsetData(sizeType i)
241    { data_ += i;}
242
243    // and these are needed for stencil expression shift to work
244    void _bz_offsetData(sizeType offset, int dim)
245    { data_ += offset*array_.stride(dim); }
246 
247    void _bz_offsetData(sizeType offset1, int dim1, sizeType offset2, int dim2)
248    { data_ += offset1*array_.stride(dim1); 
249      data_ += offset2*array_.stride(dim2); }
250
251    int stride() const
252    { return stride_; }
253
254  /** Returns true if the Array has unit stride in the rank. */
255    bool isUnitStride(int rank) const
256    { return array_.stride(rank) == 1; }
257
258  /** Returns true if the loaded iterator stride is 1. */
259    bool isUnitStride() const
260    { return stride() == 1; }
261
262    void advanceUnitStride()
263    { ++data_; }
264
265    bool canCollapse(int outerLoopRank, int innerLoopRank) const
266    { return array_.canCollapse(outerLoopRank, innerLoopRank); }
267
268    void prettyPrint(BZ_STD_SCOPE(string) &str, 
269        prettyPrintFormat& format) const
270    {
271        if (format.tersePrintingSelected())
272            str += format.nextArrayOperandSymbol();
273        else if (format.dumpArrayShapesMode())
274        {
275#ifdef BZ_HAVE_STD
276            BZ_STD_SCOPE(ostringstream) ostr;
277#else
278            ostrstream ostr;
279#endif
280            ostr << array_.shape();
281            str += ostr.str();
282        }
283        else {
284            str += "Array<";
285            str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_numtype);
286            str += ",";
287
288            char tmpBuf[10];
289            sprintf(tmpBuf, "%d", N_rank);
290
291            str += tmpBuf;
292            str += ">";
293        }
294    }
295
296    template<typename T_shape>
297    bool shapeCheck(const T_shape& shape) const
298    { return areShapesConformable(shape, array_.length()); }
299
300
301    // Experimental
302    T_numtype& operator()(int i) const
303    {
304      return (T_numtype&)data_[i*array_.stride(0)];
305    }
306
307    // Experimental
308    T_numtype& operator()(int i, int j) const
309    {
310      return (T_numtype&)data_[i*array_.stride(0) + j*array_.stride(1)];
311    }
312
313    // Experimental
314    T_numtype& operator()(int i, int j, int k) const
315    {
316      return (T_numtype&)data_[i*array_.stride(0)
317                               + j*array_.stride(1)
318                               + k*array_.stride(2)];
319    }
320
321    // Experimental
322
323    void moveTo(int i)
324    {
325        data_ = &const_cast<T_array&>(array_)(i);
326    }
327
328    void moveTo(int i, int j)
329    {
330        data_ = &const_cast<T_array&>(array_)(i,j);
331    }
332
333    void moveTo(int i, int j, int k)
334    {
335        data_ = &const_cast<T_array&>(array_)(i,j,k);
336    }
337
338    template<int N_rank2>
339    void moveTo(const TinyVector<int,N_rank2>& i)
340    {
341        data_ = &const_cast<T_array&>(array_)(i);
342    }
343
344    // Experimental
345    void operator=(T_numtype x)
346    {   *const_cast<T_numtype*>(data_) = x; }
347
348    // Experimental
349    template<typename T_value>
350    void operator=(T_value x)
351    {   *const_cast<T_numtype*>(data_) = x; }
352
353    // Experimental
354    template<typename T_value>
355    void operator+=(T_value x)
356    { *const_cast<P_numtype*>(data_) += x; }
357
358    // NEEDS_WORK: other operators
359 
360    // Experimental
361    operator T_numtype() const
362    { return *data_; }
363
364    // Experimental
365    T_result shift(int offset, int dim) const
366    {
367      return data_[offset*array_.stride(dim)];
368    }
369
370    // Experimental
371    T_result shift(int offset1, int dim1, int offset2, int dim2) const
372    {
373      return data_[offset1*array_.stride(dim1) 
374                   + offset2*array_.stride(dim2)];
375    }
376
377  // sliceinfo for expressions
378  template<typename T1, typename T2 = nilArraySection, 
379           class T3 = nilArraySection, typename T4 = nilArraySection, 
380           class T5 = nilArraySection, typename T6 = nilArraySection, 
381           class T7 = nilArraySection, typename T8 = nilArraySection, 
382           class T9 = nilArraySection, typename T10 = nilArraySection, 
383           class T11 = nilArraySection>
384  class SliceInfo {
385  public:   
386    typedef FastArrayCopyIterator<P_numtype, blitz::SliceInfo<P_numtype, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::rank> T_slice;
387  };
388
389  template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
390           typename T7, typename T8, typename T9, typename T10, typename T11>
391  typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
392  operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
393  {
394    return typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice(array_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
395  }
396
397protected:
398  const P_numtype * restrict           data_;
399  P_arraytype                          array_;
400  ConstPointerStack<P_numtype,N_rank>  stack_;
401  diffType                             stride_;
402};
403
404
405template<typename P_numtype, int N_rank> class FastArrayCopyIterator;
406
407template<typename P_numtype, int N_rank>
408class FastArrayIterator : 
409  public FastArrayIteratorBase<P_numtype, N_rank, const Array<P_numtype, N_rank>&> 
410{
411public:
412  typedef FastArrayIteratorBase<P_numtype, N_rank, 
413                                const Array<P_numtype, N_rank>&> T_base;
414  typedef typename T_base::T_numtype T_numtype;
415  typedef typename T_base::T_array T_array;
416  typedef typename T_base::T_iterator T_iterator;
417  typedef typename T_base::T_ctorArg1 T_ctorArg1;
418  typedef typename T_base::T_ctorArg2 T_ctorArg2;
419  typedef typename T_base::T_range_result T_range_result;
420 
421  using T_base::rank_;
422  using T_base::numArrayOperands;
423  using T_base::numTVOperands;
424  using T_base::numTMOperands;
425  using T_base::numIndexPlaceholders;
426
427  // NB: this ctor does NOT preserve stack and stride
428  // parameters.  This is for speed purposes.
429  FastArrayIterator(const FastArrayIterator<P_numtype, N_rank>& x) 
430    : T_base(x)
431  { }
432
433  FastArrayIterator(const T_array& array) : T_base(array) {}
434 
435  using T_base::operator=;
436  void operator=(const FastArrayIterator<P_numtype, N_rank>& x)
437  {
438    T_base::operator=(x);
439  }
440 
441  using T_base::operator();
442};
443
444/* This version of the FastArrayIterator makes a COPY of the array
445   it's pointing to. This makes it possible to return expressions of
446   arrays that have gone out of scope, or to slice expressions. */
447template<typename P_numtype, int N_rank>
448class FastArrayCopyIterator : 
449  public FastArrayIteratorBase<P_numtype, N_rank, const Array<P_numtype, N_rank> >
450{
451public:
452  typedef FastArrayIteratorBase<P_numtype, N_rank, 
453                                const Array<P_numtype, N_rank> > T_base;
454  typedef typename T_base::T_numtype T_numtype;
455  typedef typename T_base::T_array T_array;
456  typedef typename T_base::T_iterator T_iterator;
457  typedef typename T_base::T_ctorArg1 T_ctorArg1;
458  typedef typename T_base::T_ctorArg2 T_ctorArg2;
459  typedef typename T_base::T_range_result T_range_result;
460
461  using T_base::rank_;
462  using T_base::numArrayOperands;
463  using T_base::numTVOperands;
464  using T_base::numTMOperands;
465  using T_base::numIndexPlaceholders;
466
467
468  // NB: this ctor does NOT preserve stack and stride
469  // parameters.  This is for speed purposes.
470  FastArrayCopyIterator(const FastArrayCopyIterator<P_numtype, N_rank>& x) 
471    : T_base(x)
472  { }
473
474  FastArrayCopyIterator(const T_array& array) : T_base(array) { }
475 
476  using T_base::operator=;
477  void operator=(const FastArrayCopyIterator& x)
478  {
479    T_base::operator=(x);
480  }
481 
482  using T_base::operator();
483
484};
485
486
487BZ_NAMESPACE_END
488
489#endif // BZ_ARRAY_FASTITER_H
Note: See TracBrowser for help on using the repository browser.