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

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 24.7 KB
Line 
1// -*- C++ -*-
2/***************************************************************************
3 * blitz/array/map.h      Declaration of the ArrayIndexMapping class
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
32/*
33 * ArrayIndexMapping is used to implement tensor array notation.  For
34 * example:
35 *
36 * Array<float, 2> A, B;
37 * firstIndex i;
38 * secondIndex j;
39 * thirdIndex k;
40 * Array<float, 3> C = A(i,j) * B(j,k);
41 *
42 * For expression templates purposes, something like B(j,k) is represented
43 * by an instance of class ArrayIndexMapping.  This class maps an array onto
44 * the destination array coordinate system, e.g. B(j,k) -> C(i,j,k)
45 */
46
47#ifndef BZ_ARRAYMAP_H
48#define BZ_ARRAYMAP_H
49
50#include <blitz/blitz.h>
51#include <blitz/prettyprint.h>
52#include <blitz/et-forward.h>
53#include <blitz/tinyvec2.h>
54#include <blitz/array/domain.h>
55
56BZ_NAMESPACE(blitz)
57
58/*
59 * _bz_doArrayIndexMapping is a helper class that does the index
60 * remapping.  It is specialized for ranks 1, 2, 3, ..., 11.
61 */
62
63template<int N_rank>
64struct _bz_doArrayIndexMapping {
65  static const int rank=N_rank;
66  template<typename T_expr, int N_inputRank>
67  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
68        const TinyVector<int,N_inputRank>&, int, int, int, int, int, int,
69        int, int, int, int, int)
70    {
71        // If you try to use an array index mapping on an array with
72        // rank greater than 11, then you'll get a precondition failure
73        // here.
74      BZPRECHECK(0,"Index mappings for containers of rank>11 not implemented");
75      return T_expr::T_numtype();
76    }
77};
78
79template<>
80struct _bz_doArrayIndexMapping<1> {
81  static const int rank=1;
82  template<typename T_expr, int N_inputRank>
83  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
84        const TinyVector<int,N_inputRank>& index, int i0, int, int, int, int, 
85        int, int, int, int, int, int)
86    {
87      // this was the case when it took an array. is it necessary?
88      BZPRECHECK(T_expr::rank_==rank,
89                 "Rank confusion in _bz_doArrayIndexMapping"); 
90      return expr.unwrap()(index[i0]);
91    }
92
93  template<int N_inputRank>
94  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
95                         int i0, int, int, int, int, 
96                         int, int, int, int, int, int)
97    {
98      // this might be slower but unlike Array, FAI doesn't have 11
99      // overloaded moveTo methods.
100      const TinyVector<int,rank> newindex(index[i0]);
101      return newindex;
102    }
103};
104
105
106template<>
107struct _bz_doArrayIndexMapping<2> {
108  static const int rank=2;
109
110  template<typename T_expr, int N_inputRank>
111  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
112        const TinyVector<int,N_inputRank>& index, int i0, int i1, int, 
113        int, int, int, int, int, int, int, int)
114    {
115      // this was the case when it took an array. is it necessary?
116      BZPRECHECK(T_expr::rank_==rank,
117                 "Rank confusion in _bz_doArrayIndexMapping"); 
118      return expr.unwrap()(index[i0], index[i1]);
119    }
120
121  template<int N_inputRank>
122  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
123                         int i0, int i1, int, int, int, 
124                         int, int, int, int, int, int)
125    {
126      return TinyVector<int,rank>(index[i0], index[i1]);
127    }
128};
129
130template<>
131struct _bz_doArrayIndexMapping<3> {
132  static const int rank=3;
133
134  template<typename T_expr, int N_inputRank>
135  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
136        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
137        int, int, int, int, int, int, int, int)
138    {
139      // this was the case when it took an array. is it necessary?
140      BZPRECHECK(T_expr::rank_==rank,
141                 "Rank confusion in _bz_doArrayIndexMapping"); 
142      return expr.unwrap()(index[i0], index[i1], index[i2]);
143    }
144
145  template<int N_inputRank>
146  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
147                         int i0, int i1, int i2, int, int, 
148                         int, int, int, int, int, int)
149    {
150      return TinyVector<int,rank>(index[i0], index[i1], index[i2]);
151    }
152};
153
154template<>
155struct _bz_doArrayIndexMapping<4> {
156  static const int rank=4;
157
158  template<typename T_expr, int N_inputRank>
159  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
160        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
161        int i3, int, int, int, int, int, int, int)
162    {
163      // this was the case when it took an array. is it necessary?
164      BZPRECHECK(T_expr::rank_==rank,
165                 "Rank confusion in _bz_doArrayIndexMapping"); 
166        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3]);
167    }
168
169  template<int N_inputRank>
170  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
171                         int i0, int i1, int i2, int i3, int, 
172                         int, int, int, int, int, int)
173    {
174      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
175                                  index[i3]);
176    }
177};
178
179template<>
180struct _bz_doArrayIndexMapping<5> {
181  static const int rank=5;
182
183  template<typename T_expr, int N_inputRank>
184  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
185        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
186        int i3, int i4, int, int, int, int, int, int)
187    {
188      // this was the case when it took an array. is it necessary?
189      BZPRECHECK(T_expr::rank_==rank,
190                 "Rank confusion in _bz_doArrayIndexMapping"); 
191        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], index[i4]);
192    }
193
194  template<int N_inputRank>
195  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
196                         int i0, int i1, int i2, int i3, int i4, 
197                         int, int, int, int, int, int)
198    {
199      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
200                                  index[i3], index[i4]);
201    }
202};
203
204template<>
205struct _bz_doArrayIndexMapping<6> {
206  static const int rank=6;
207
208  template<typename T_expr, int N_inputRank>
209  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
210        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
211        int i3, int i4, int i5, int, int, int, int, int)
212    {
213      // this was the case when it took an array. is it necessary?
214      BZPRECHECK(T_expr::rank_==rank,
215                 "Rank confusion in _bz_doArrayIndexMapping"); 
216        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], index[i4],
217            index[i5]);
218    }
219
220  template<int N_inputRank>
221  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
222                         int i0, int i1, int i2, int i3, int i4, 
223                         int i5, int, int, int, int, int)
224    {
225      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
226                                  index[i3], index[i4], index[i5]);
227    }
228};
229
230template<>
231struct _bz_doArrayIndexMapping<7> {
232  static const int rank=7;
233
234  template<typename T_expr, int N_inputRank>
235  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
236        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
237        int i3, int i4, int i5, int i6, int, int, int, int)
238    {
239      // this was the case when it took an array. is it necessary?
240      BZPRECHECK(T_expr::rank_==rank,
241                 "Rank confusion in _bz_doArrayIndexMapping"); 
242        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], 
243                             index[i4], index[i5], index[i6]);
244    }
245
246  template<int N_inputRank>
247  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
248                         int i0, int i1, int i2, int i3, int i4, 
249                         int i5, int i6, int, int, int, int)
250    {
251      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
252                                  index[i3], index[i4], index[i5],
253                                  index[i6]);
254    }
255};
256
257template<>
258struct _bz_doArrayIndexMapping<8> {
259  static const int rank=8;
260
261  template<typename T_expr, int N_inputRank>
262  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
263        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
264        int i3, int i4, int i5, int i6, int i7, int, int, int)
265    {
266      // this was the case when it took an array. is it necessary?
267      BZPRECHECK(T_expr::rank_==rank,
268                 "Rank confusion in _bz_doArrayIndexMapping"); 
269        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], 
270                             index[i4], index[i5], index[i6], index[i7]);
271    }
272
273  template<int N_inputRank>
274  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
275                         int i0, int i1, int i2, int i3, int i4, 
276                         int i5, int i6, int i7, int, int, int)
277    {
278      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
279                                  index[i3], index[i4], index[i5],
280                                  index[i6], index[i7]);
281    }
282};
283
284template<>
285struct _bz_doArrayIndexMapping<9> {
286  static const int rank=9;
287
288  template<typename T_expr, int N_inputRank>
289  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
290        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
291        int i3, int i4, int i5, int i6, int i7, int i8, int, int)
292    {
293      // this was the case when it took an array. is it necessary?
294      BZPRECHECK(T_expr::rank_==rank,
295                 "Rank confusion in _bz_doArrayIndexMapping"); 
296        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], 
297                             index[i4], index[i5], index[i6], index[i7], 
298                             index[i8]);
299    }
300
301  template<int N_inputRank>
302  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
303                         int i0, int i1, int i2, int i3, int i4, 
304                         int i5, int i6, int i7, int i8, int, int)
305    {
306      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
307                                  index[i3], index[i4], index[i5],
308                                  index[i6], index[i7], index[i8]);
309    }
310};
311
312template<>
313struct _bz_doArrayIndexMapping<10> {
314  static const int rank=10;
315
316  template<typename T_expr, int N_inputRank>
317  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
318        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
319        int i3, int i4, int i5, int i6, int i7, int i8, int i9, int)
320    {
321      // this was the case when it took an array. is it necessary?
322      BZPRECHECK(T_expr::rank_==rank,
323                 "Rank confusion in _bz_doArrayIndexMapping"); 
324        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], 
325                             index[i4], index[i5], index[i6], index[i7], 
326                             index[i8], index[i9]);
327    }
328
329  template<int N_inputRank>
330  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
331                         int i0, int i1, int i2, int i3, int i4, 
332                         int i5, int i6, int i7, int i8, int i9, int)
333    {
334      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
335                                  index[i3], index[i4], index[i5],
336                                  index[i6], index[i7], index[i8],
337                                  index[i9]);
338    }
339};
340
341template<>
342struct _bz_doArrayIndexMapping<11> {
343  static const int rank=11;
344
345  template<typename T_expr, int N_inputRank>
346  static typename T_expr::T_numtype map(const ETBase<T_expr>& expr,
347        const TinyVector<int,N_inputRank>& index, int i0, int i1, int i2,
348        int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10)
349    {
350      // this was the case when it took an array. is it necessary?
351      BZPRECHECK(T_expr::rank_==rank,
352                 "Rank confusion in _bz_doArrayIndexMapping"); 
353        return expr.unwrap()(index[i0], index[i1], index[i2], index[i3], 
354                             index[i4], index[i5], index[i6], index[i7], 
355                             index[i8], index[i9], index[i10]);
356    }
357
358  template<int N_inputRank>
359  static TinyVector<int,rank> map_dims(const TinyVector<int,N_inputRank>& index, 
360                         int i0, int i1, int i2, int i3, int i4, 
361                         int i5, int i6, int i7, int i8, int i9, int i10)
362    {
363      return TinyVector<int,rank>(index[i0], index[i1], index[i2],
364                                  index[i3], index[i4], index[i5],
365                                  index[i6], index[i7], index[i8],
366                                  index[i9], index[i10]);
367    }
368};
369
370
371// default arguments are defined in the fwd header
372template<typename P_expr, int N_map0, int N_map1, int N_map2,
373    int N_map3, int N_map4, int N_map5, int N_map6, int N_map7, 
374    int N_map8, int N_map9, int N_map10>
375class ArrayIndexMapping {
376public:
377  typedef P_expr T_expr;
378  typedef typename T_expr::T_numtype T_numtype;
379
380  typedef T_numtype T_optype;
381  typedef typename asET<T_numtype>::T_wrapped T_typeprop;
382  typedef typename unwrapET<T_typeprop>::T_unwrapped T_result;
383
384  typedef T_expr T_ctorArg1;
385    typedef int                            T_ctorArg2;    // dummy
386  typedef ArrayIndexMapping<typename T_expr::T_range_result,N_map0,N_map1,N_map2,N_map3,N_map4,N_map5,N_map6,N_map7,N_map8,N_map9,N_map10> T_range_result;
387
388    /*
389     * This enum block finds the maximum of the N_map0, N_map1, ..., N_map10
390     * parameters and stores it in maxRank10.  The rank of the expression is
391     * then maxRank10 + 1, since the IndexPlaceholders start at 0 rather than
392     * 1. 
393     */
394    static const int
395        maxRank1 = (N_map0 > N_map1) ? N_map0 : N_map1,
396        maxRank2 = (N_map2 > maxRank1) ? N_map2 : maxRank1,
397        maxRank3 = (N_map3 > maxRank2) ? N_map3 : maxRank2,
398        maxRank4 = (N_map4 > maxRank3) ? N_map4 : maxRank3,
399        maxRank5 = (N_map5 > maxRank4) ? N_map5 : maxRank4,
400        maxRank6 = (N_map6 > maxRank5) ? N_map6 : maxRank5,
401        maxRank7 = (N_map7 > maxRank6) ? N_map7 : maxRank6,
402        maxRank8 = (N_map8 > maxRank7) ? N_map8 : maxRank7,
403        maxRank9 = (N_map9 > maxRank8) ? N_map9 : maxRank8,
404        maxRank10 = (N_map10 > maxRank9) ? N_map10 : maxRank9;
405
406    static const int 
407    numArrayOperands = T_expr::numArrayOperands, 
408      numTVOperands = T_expr::numTVOperands,
409      numTMOperands = T_expr::numTMOperands,
410        numIndexPlaceholders = 1,
411      minWidth = simdTypes<T_numtype>::vecWidth,
412      maxWidth = simdTypes<T_numtype>::vecWidth,
413        rank_ = maxRank10 + 1,
414        exprRank = T_expr::rank_;
415
416  template<int N> struct tvresult {
417    typedef FastTV2Iterator<T_numtype, N> Type;
418  };
419
420  /*
421    ArrayIndexMapping(const Array<T_numtype, rank>& array)
422        : iter_(array)
423    {
424    }
425  */
426
427    ArrayIndexMapping(const ArrayIndexMapping<T_expr,N_map0,
428        N_map1,N_map2,N_map3,N_map4,N_map5,N_map6,N_map7,N_map8,N_map9,
429        N_map10>& z)
430        : iter_(z.iter_)
431    { 
432    }
433
434  ArrayIndexMapping(BZ_ETPARM(T_expr) a)
435        : iter_(a)
436    { }
437
438  // this is ambiguous with the above
439  // ArrayIndexMapping(_bz_typename T_expr::T_ctorArg1 a)
440  //       : iter_(a)
441  //   { }
442
443  // these bypass the FAI and go directly to the array. That should
444  // prevent any performance impact of using the FAI instead of an
445  // array directly.
446
447  /* Functions for reading. Because they must depend on the result
448   * type, they utilize a helper class.
449   */
450
451  // For numtypes, apply operator
452  template<typename T> struct readHelper {
453    static T_result first_value(const T_expr& iter)  {
454      // is the correct thing to do here to return the index zero value?
455      return indexop(iter, TinyVector<int,1>(0)); }
456    template<int N_rank>
457#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
458    static T_result indexop(const T_expr& iter, 
459                            const TinyVector<int, N_rank> i) {
460#else
461      static T_result indexop(const T_expr& iter,
462                              const TinyVector<int, N_rank>& i) {
463#endif
464        return _bz_doArrayIndexMapping<exprRank>::map(iter/*.array()*/, i,
465            N_map0, N_map1, N_map2, N_map3, N_map4, N_map5, N_map6,
466            N_map7, N_map8, N_map9, N_map10);
467  };
468    };
469
470  // For ET types, bypass operator and create expression
471    template<typename T> struct readHelper<ETBase<T> > {
472      template<int N_rank>
473#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
474      static T_result indexop(const T_expr& iter,
475                              const TinyVector<int, N_rank> i) {
476#else
477    static T_result indexop(const T_expr& iter,
478                            const TinyVector<int, N_rank>& i) {
479#endif
480      return iter(i); }
481    static T_result first_value(const T_expr& iter)  {
482      // is the correct thing to do here to return the index zero value?
483      return indexop(iter, TinyVector<int,1>(0)); }
484    };
485
486    template<int N_rank>
487#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
488    T_result operator()(const TinyVector<int, N_rank> i) const {
489#else
490      T_result operator()(const TinyVector<int, N_rank>& i) const {
491#endif
492      return readHelper<T_typeprop>::indexop(iter_,i); }
493
494    T_result first_value() const {
495      // unclear how to define "first" value for index expressions.
496      BZPRECHECK(0,"Minmax reductions of index expressions not implemented");
497      return readHelper<T_typeprop>::first_value(iter_); }
498
499  // find which dimension in mapped expression that corresponds to
500  // dimension dim. This works such that dimension dim in this
501  // expression corresponds to dimension map_dim(dim) in iter_.
502    int map_dim(const int dim) const
503    { 
504        if (N_map0 == dim)   
505          return 0;
506        else if ((N_map1 == dim) && (exprRank > 1))
507          return 1;
508        else if ((N_map2 == dim) && (exprRank > 2))
509          return 2;
510        else if ((N_map3 == dim) && (exprRank > 3))
511          return 3;
512        else if ((N_map4 == dim) && (exprRank > 4))
513          return 4;
514        else if ((N_map5 == dim) && (exprRank > 5))
515          return 5;
516        else if ((N_map6 == dim) && (exprRank > 6))
517          return 6;
518        else if ((N_map7 == dim) && (exprRank > 7))
519          return 7;
520        else if ((N_map8 == dim) && (exprRank > 8))
521          return 8;
522        else if ((N_map9 == dim) && (exprRank > 9))
523          return 9;
524        else if ((N_map10 == dim) && (exprRank > 10))
525          return 10;
526        else
527          // means dimension is not in this operand
528          return -1;
529    }
530
531  // remaps the dimensions of an index vector so it can be applied to
532  // iter_, using the _bz_doArrayIndexMapping helper class.
533  template<int N> 
534  TinyVector<int, exprRank> map_dims(const TinyVector<int, N>& i) const {
535    return _bz_doArrayIndexMapping<exprRank>::map_dims
536      (i, N_map0, N_map1, N_map2, N_map3, N_map4, N_map5,
537       N_map6, N_map7, N_map8, N_map9, N_map10);
538  }
539
540  int ascending(const int dim) const
541  {
542    const int d=map_dim(dim);
543    const int o = d>=0 ? iter_.ascending(d) : INT_MIN ;
544    return o;
545  }
546
547  int ordering(const int dim) const
548  {
549    // JCC: ignore ordering result from 1d Array
550    if (exprRank == 1)
551      return INT_MIN;  // tiny(int());
552
553    const int d=map_dim(dim);
554    const int o = d>=0 ? iter_.ordering(d) : INT_MIN ;
555    return o;
556  }
557
558  int lbound(const int dim) const
559  {
560    const int d=map_dim(dim);
561    const int o = d>=0 ? iter_.lbound(d) : INT_MIN ;
562    return o;
563  }
564
565  int ubound(const int dim) const
566  {
567    const int d=map_dim(dim);
568    const int o = d>=0 ? iter_.ubound(d) : INT_MAX ;
569    return o;
570  }
571
572  // defer calculation to lbound/ubound
573  RectDomain<rank_> domain() const 
574  { 
575    TinyVector<int, rank_> lb, ub;
576    for(int r=0; r<rank_; ++r) {
577      lb[r]=lbound(r); ub[r]=ubound(r); 
578    }
579    return RectDomain<rank_>(lb,ub);
580  }
581
582    // If you have a precondition failure on this routine, it means
583    // you are trying to use stack iteration mode on an expression
584    // which contains an index placeholder.  You must use index
585    // iteration mode instead.
586  // (no -- added to support stencils /PJ)
587    T_result operator*() const
588    {
589      return *iter_;
590    }
591
592    // See operator*() note
593    void push(int)
594    {
595        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
596    }
597
598    // See operator*() note
599    void pop(int)
600    {
601        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
602    }
603
604    // See operator*() note
605    void advance()
606    {
607        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
608    }
609
610    // See operator*() note
611    void advance(int)
612    {
613        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
614    }
615
616    // See operator*() note
617    void loadStride(int)
618    {
619        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
620    }
621
622    bool isUnitStride(int) const
623    {
624        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
625        return false;
626    }
627
628    bool isUnitStride() const
629    {
630        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
631        return false;
632    }
633
634    void advanceUnitStride()
635    {
636        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
637    }
638
639    bool canCollapse(int,int) const
640    {   BZPRECHECK(0,"Can't use stack iteration on an index mapping.");  return false; }
641
642    T_result operator[](int)
643    {   
644        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
645        return T_result();
646    }
647
648    T_result fastRead(int) const
649    {
650        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
651        return T_result();
652    }
653
654  template<int N>
655  typename tvresult<N>::Type fastRead_tv(int) const {
656    BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
657    return TinyVector<T_numtype, N>();
658    }
659
660    /** Determining whether the resulting expression is aligned is
661        difficult, so to be safe we say no. It shouldn't be attempted
662        anyway, though. */
663    bool isVectorAligned(diffType offset) const {
664      return false; }
665
666    int suggestStride(int) const
667    {
668        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
669        return 0;
670    }
671
672    bool isStride(int,int) const
673    {
674        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
675        return true;
676    }
677
678#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
679    template<int N_destrank>
680    void moveTo(const TinyVector<int,N_destrank> i)
681    {
682      iter_.moveTo(map_dims(i));
683    }
684#else
685    template<int N_destrank>
686    void moveTo(const TinyVector<int,N_destrank>& i)
687    {
688      iter_.moveTo(map_dims(i));
689    }
690#endif
691
692  T_result shift(int offset, int dim) const { 
693    // need to check if dim is mapped into this expression
694    const int d=map_dim(dim);
695    if (d<0)
696      return *iter_;
697    else
698      return iter_.shift(offset, d);
699  }
700
701  T_result shift(int offset1, int dim1,int offset2, int dim2) const {
702    // need to check if dims are mapped into this expression
703    int d1=map_dim(dim1);
704    int d2=map_dim(dim2);
705    if (d1<0) //disable offset
706      {d1=0;offset1=0;}
707    if (d2<0) //disable offset
708      {d2=0;offset2=0;}
709    return iter_.shift(offset1, d1, offset2, d2);
710  }
711
712  void _bz_offsetData(sizeType i) {
713        BZPRECHECK(0,"Can't use stack iteration on an index mapping.");
714  }
715
716  template<int N>
717  T_range_result operator()(RectDomain<N> d) const
718  { // need to reorder dimensions here
719    TinyVector<int, exprRank> lb(map_dims(d.lbound())), ub(map_dims(d.ubound()));
720    RectDomain<exprRank> newd(lb,ub);
721    return T_range_result(iter_(newd));
722  }
723
724    void prettyPrint(BZ_STD_SCOPE(string) &str, prettyPrintFormat&) const
725    {
726        // NEEDS_WORK-- do real formatting for reductions
727        str += "map[NEEDS_WORK]";
728    }
729
730    template<typename T_shape>
731    bool shapeCheck(const T_shape&) const
732    { 
733        // NEEDS_WORK-- do a real shape check (tricky)
734        return true; 
735    }
736
737  // sliceinfo for expressions
738  template<typename T1, typename T2 = nilArraySection, 
739           class T3 = nilArraySection, typename T4 = nilArraySection, 
740           class T5 = nilArraySection, typename T6 = nilArraySection, 
741           class T7 = nilArraySection, typename T8 = nilArraySection, 
742           class T9 = nilArraySection, typename T10 = nilArraySection, 
743           class T11 = nilArraySection>
744  class SliceInfo {
745  public:
746    typedef typename T_expr::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice1;
747    typedef ArrayIndexMapping<T_slice1, N_map0, N_map1, N_map2,
748                              N_map3, N_map4, N_map5, N_map6, N_map7, 
749                              N_map8, N_map9, N_map10> T_slice;
750};
751
752    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
753        typename T7, typename T8, typename T9, typename T10, typename T11>
754    typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
755    operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
756    {
757      /* Slicing for remapped expressions doesn't work. Because of the
758         potential different types (Range vs int) in the expression,
759         it would be very awkward to implement. As far as I can see,
760         it would require manual coding of the 3^11 calling
761         possibilities. /PJ */
762      BZPRECONDITION(0);
763    }
764
765private:
766    ArrayIndexMapping() : iter_( Array<T_numtype, exprRank>() ) { }
767
768    T_expr iter_;
769};
770
771BZ_NAMESPACE_END
772
773#endif // BZ_ARRAYMAP_H
774
Note: See TracBrowser for help on using the repository browser.