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

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 64.5 KB
Line 
1// -*- C++ -*-
2/***************************************************************************
3 * blitz/array/functorExpr.h   User-defined functors for arrays
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/* This header file is designed to allow the use of Blitz++ with
32   functors (classes defining an operator()) and more general member
33   functions. It works best if you have access to the class source code;
34   there is limited support for classes that cannot be modified. The best
35   approach in that case is usually to write an adapter class.
36
37   This works with class methods that take one, two or three arguments.
38
39   If you have a functor, add the following to your (public) class declaration:
40
41   BZ_DECLARE_FUNCTOR(classname)   // for one argument functors
42   BZ_DECLARE_FUNCTOR2(classname)  // for two argument functors
43   BZ_DECLARE_FUNCTOR3(classname)  // for three argument functors
44   
45   or
46
47   BZ_DECLARE_FUNCTOR_RET(classname, returnType)
48   BZ_DECLARE_FUNCTOR2_RET(classname, returnType)
49   BZ_DECLARE_FUNCTOR3_RET(classname, returnType)
50
51   for classes whose operator() has a return type that is not what you would
52   deduce from the usual C++ promotion rules (e.g., takes two doubles and
53   returns a bool).
54
55   You can then use your class in Blitz++ expressions and no temporaries will
56   be generated. For example, assuming that your class is named T, and that
57   A, B and C are Arrays, you can write
58
59   T classInstance( ... );
60   A = C + classInstance(B * tensor::i);
61   A = C + classInstance(tensor::i, tensor::j)
62
63   It also works for member functions:
64   
65   BZ_DECLARE_MEMBER_FUNCTION(classname, funcname)
66   BZ_DECLARE_MEMBER_FUNCTION2(classname, funcname)
67   BZ_DECLARE_MEMBER_FUNCTION3(classname, funcname)
68   
69   or
70   
71   BZ_DECLARE_MEMBER_FUNCTION_RET(classname, funcname, returnType)
72   BZ_DECLARE_MEMBER_FUNCTION2_RET(classname, funcname, returnType)
73   BZ_DECLARE_MEMBER_FUNCTION3_RET(classname, funcname, returnType)
74
75   allows you to write stuff like
76   
77   A = C + classInstance.funcname(B * tensor::i);
78   A = C + classInstance.funcname(tensor::i, tensor::j)
79   
80   All the member functions to be applied must be declared const.
81     
82   There is also some support for classes where the source code is not
83   available or not to be tampered with.  For example,
84     
85   A = C + applyFunctor(classInstance, B * tensor::i);
86   A = C + applyFunctor(classInstance, tensor::i, tensor::j);
87   
88   This approach does not work for arbitrary s.  The
89   class must be a proper functor with an operator(). 
90
91*/
92
93#ifndef BZ_ARRAY_FUNCTOREXPR_H
94#define BZ_ARRAY_FUNCTOREXPR_H
95
96#ifndef BZ_ARRAY_H
97 #error <blitz/array/functorExpr.h> must be included via <blitz/array.h>
98#endif
99
100#include <blitz/prettyprint.h>
101#include <blitz/shapecheck.h>
102#include <blitz/tinyvec2.h>
103
104BZ_NAMESPACE(blitz)
105
106template<typename P_functor, typename P_expr, typename P_result>
107class _bz_FunctorExpr {
108public:
109    typedef P_functor T_functor;
110    typedef P_expr T_expr;
111    typedef _bz_typename T_expr::T_numtype T_numtype1;
112    typedef P_result T_numtype;
113
114  // select return type
115  typedef typename unwrapET<typename T_expr::T_result>::T_unwrapped test;
116  typedef typename selectET<typename T_expr::T_typeprop, 
117                            T_numtype, 
118                            _bz_FunctorExpr<T_functor, 
119                                            test, 
120                                            P_result> >::T_selected T_typeprop;
121  typedef typename unwrapET<T_typeprop>::T_unwrapped T_result;
122  typedef T_numtype T_optype;
123
124    typedef T_expr    T_ctorArg1;
125    typedef int       T_ctorArg2;    // dummy
126    typedef int       T_ctorArg3;    // dummy
127  typedef _bz_FunctorExpr<P_functor, _bz_typename P_expr::T_range_result, 
128                          P_result> T_range_result;
129
130    static const int 
131        numArrayOperands = T_expr::numArrayOperands,
132        numTVOperands = T_expr::numTVOperands,
133        numTMOperands = T_expr::numTMOperands,
134        numIndexPlaceholders = T_expr::numIndexPlaceholders,
135      minWidth = T_expr::minWidth,
136      maxWidth = T_expr::maxWidth,
137        rank_ = T_expr::rank_;
138   
139  template<int N> struct tvresult {
140    typedef _bz_FunctorExpr<
141      T_functor,
142      typename T_expr::template tvresult<N>::Type,
143      T_numtype> Type; 
144  };
145
146    _bz_FunctorExpr(const _bz_FunctorExpr<P_functor,P_expr,P_result>& a)
147        : f_(a.f_), iter_(a.iter_)
148    { }
149   
150    _bz_FunctorExpr(BZ_ETPARM(T_functor) f, BZ_ETPARM(T_expr) a)
151        : f_(f), iter_(a)
152    { }
153
154  // this is identical to the above constructor
155  //_bz_FunctorExpr(BZ_ETPARM(T_functor) f, _bz_typename T_expr::T_ctorArg1 a)
156  //: f_(f), iter_(a)  { }
157
158#if BZ_TEMPLATE_CTOR_DOESNT_CAUSE_HAVOC
159    template<typename T1>
160    explicit _bz_FunctorExpr(BZ_ETPARM(T_functor) f, BZ_ETPARM(T1) a)
161        : f_(f), iter_(a)
162    { }
163#endif
164
165  /* Functions for reading data. Because they must depend on the
166   * result type, they utilize a helper class.
167   */
168
169  // For numtypes, apply operator
170  template<typename T> struct readHelper {
171    static T_result fastRead(const T_functor& f, const T_expr& iter, 
172                             diffType i) {
173      return f(iter.fastRead(i)); };
174    static T_result indexop(const T_functor& f, const T_expr& iter, int i) {
175      return f(iter[i]); };
176    static T_result deref(const T_functor& f, const T_expr& iter) {
177      return f(*iter); }
178    static T_result first_value(const T_functor& f, const T_expr& iter)  {
179      return f(iter.first_value()); }
180    static T_result shift(const T_functor& f, const T_expr& iter,
181                          int offset, int dim) {
182      return f(iter.shift(offset, dim)); }
183    static T_result shift(const T_functor& f, const T_expr& iter,
184                          int offset1, int dim1,int offset2, int dim2) {
185      return f(iter.shift(offset1, dim1, offset2, dim2)); }
186    template<int N_rank>
187#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
188    static T_result indexop(const T_functor& f, const T_expr& iter, 
189                            const TinyVector<int, N_rank> i) {
190#else
191      static T_result indexop(const T_functor& f, const T_expr& iter,
192                              const TinyVector<int, N_rank>& i) {
193#endif
194      return f(iter(i)); }
195  };
196
197  // For ET types, bypass operator and create expression
198    template<typename T> struct readHelper<ETBase<T> > {
199      static T_result fastRead(const T_functor& f, const T_expr& iter, 
200                               diffType i) {
201        return T_result(f,iter.fastRead(i)); };
202      static T_result indexop(const T_functor& f, const T_expr& iter, int i) {
203        return T_result(f,iter[i]); };
204      static T_result deref(const T_functor& f, const T_expr& iter) {
205        return T_result(f,*iter); }
206    static T_result first_value(const T_functor& f, const T_expr& iter)  {
207      return iter.first_value(); }
208    static T_result shift(const T_functor& f, const T_expr& iter,
209                          int offset, int dim) {
210      return T_result(f,iter.shift(offset, dim)); }
211    static T_result shift(const T_functor& f, const T_expr& iter,
212                          int offset1, int dim1,int offset2, int dim2) {
213      return T_result(f,iter.shift(offset1, dim1, offset2, dim2)); }
214      template<int N_rank>
215#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
216      static T_result indexop(const T_functor& f, const T_expr& iter,
217                              const TinyVector<int, N_rank> i) {
218#else
219    static T_result indexop(const T_functor& f, const T_expr& iter,
220                            const TinyVector<int, N_rank>& i) {
221#endif
222      return T_result(f,iter(i)); }
223    };
224
225    T_result fastRead(diffType i) const { 
226      return readHelper<T_typeprop>::fastRead(f_, iter_, i); }
227
228  template<int N>
229  typename tvresult<N>::Type fastRead_tv(diffType i) const
230      { return typename tvresult<N>::Type(f_,iter_.template fastRead_tv<N>(i)); }
231
232    T_result operator[](int i) const { 
233      return readHelper<T_typeprop>::indexop(f_, iter_, i); }
234
235    template<int N_rank>
236#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
237    T_result operator()(const TinyVector<int, N_rank> i) const {
238#else
239      T_result operator()(const TinyVector<int, N_rank>& i) const {
240#endif
241        return readHelper<T_typeprop>::indexop(f_, iter_,i); }
242
243      T_result operator*() const {
244        return readHelper<T_typeprop>::deref(f_, iter_); }
245
246      T_result first_value() const { 
247        return readHelper<T_typeprop>::first_value(f_, iter_); }
248
249    T_result shift(int offset, int dim) const {
250      return readHelper<T_typeprop>::shift(f_,iter_,offset, dim); }
251
252    T_result shift(int offset1, int dim1,int offset2, int dim2) const {
253      return readHelper<T_typeprop>::shift(f_,iter_,offset1, dim1,
254                                           offset2, dim2); }
255
256      // ****** end reading
257
258  bool isVectorAligned(diffType offset) const 
259  { return iter_.isVectorAligned(offset); }
260
261  T_range_result operator()(RectDomain<rank_> d) const
262  {
263    return T_range_result(f_, iter_(d));
264  }
265
266    int ascending(const int rank) const { return iter_.ascending(rank); }
267    int ordering(const int rank)  const { return iter_.ordering(rank);  }
268    int lbound(const int rank)    const { return iter_.lbound(rank);    }
269    int ubound(const int rank)    const { return iter_.ubound(rank);    }
270    RectDomain<rank_> domain() const { return iter_.domain(); }
271
272    void push(const int position) { iter_.push(position); }
273
274    void pop(const int position)  { iter_.pop(position); }
275
276    void advance() { iter_.advance(); }
277
278    void advance(const int n) { iter_.advance(n); }
279
280    void loadStride(const int rank) { iter_.loadStride(rank); }
281
282    bool isUnitStride(const int rank) const { return iter_.isUnitStride(rank); }
283
284    bool isUnitStride() const { return iter_.isUnitStride(); }
285
286    void advanceUnitStride() { iter_.advanceUnitStride(); }
287 
288    bool canCollapse(const int outerLoopRank, const int innerLoopRank) const
289    { 
290        return iter_.canCollapse(outerLoopRank, innerLoopRank); 
291    }
292
293    // this is needed for the stencil expression fastRead to work
294    void _bz_offsetData(sizeType i)
295    { iter_._bz_offsetData(i); }
296
297    // and these are needed for stencil expression shift to work
298    void _bz_offsetData(sizeType offset, int dim)
299    { iter_._bz_offsetData(offset, dim);}
300 
301    void _bz_offsetData(sizeType offset1, int dim1, sizeType offset2, int dim2)
302    { iter_._bz_offsetData(offset1, dim1, offset2, dim2);}
303
304    diffType suggestStride(const int rank) const
305    { return iter_.suggestStride(rank); }
306
307    bool isStride(const int rank,const diffType stride) const
308    { return iter_.isStride(rank,stride); }
309
310    void prettyPrint(BZ_STD_SCOPE(string) &str, 
311        prettyPrintFormat& format) const
312    {
313        str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_functor);
314        str += "(";
315        iter_.prettyPrint(str, format);
316        str += ")";
317    }
318
319    template<typename T_shape>
320    bool shapeCheck(const T_shape& shape) const
321    { return iter_.shapeCheck(shape); }
322
323    template<int N_rank>
324    void moveTo(const TinyVector<int,N_rank>& i)
325    {
326        iter_.moveTo(i);
327    }
328
329  // sliceinfo for expressions
330  template<typename T1, typename T2 = nilArraySection, 
331           class T3 = nilArraySection, typename T4 = nilArraySection, 
332           class T5 = nilArraySection, typename T6 = nilArraySection, 
333           class T7 = nilArraySection, typename T8 = nilArraySection, 
334           class T9 = nilArraySection, typename T10 = nilArraySection, 
335           class T11 = nilArraySection>
336  class SliceInfo {
337  public:
338    typedef typename T_expr::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice1;
339    typedef _bz_FunctorExpr<T_functor, T_slice1, T_numtype> T_slice;
340};
341
342    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
343        typename T7, typename T8, typename T9, typename T10, typename T11>
344    typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
345    operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
346    {
347      return typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
348        (f_,iter_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
349    }
350
351protected:
352    _bz_FunctorExpr() { }
353
354    T_functor f_;
355    T_expr iter_;
356};
357
358template<typename P_functor, typename P_expr1, typename P_expr2, typename P_result>
359class _bz_FunctorExpr2
360{
361public:
362    typedef P_functor T_functor;
363    typedef P_expr1 T_expr1;
364    typedef P_expr2 T_expr2;
365    typedef _bz_typename T_expr1::T_numtype T_numtype1;
366    typedef _bz_typename T_expr2::T_numtype T_numtype2;
367    typedef P_result T_numtype;
368
369  // select return type
370  typedef typename unwrapET<typename T_expr1::T_result>::T_unwrapped T_unwrapped1;
371  typedef typename unwrapET<typename T_expr2::T_result>::T_unwrapped T_unwrapped2;
372  typedef typename selectET2<typename T_expr1::T_typeprop, 
373                             typename T_expr2::T_typeprop, 
374                             T_numtype, 
375                             _bz_FunctorExpr2<T_functor,
376                                              typename asExpr<T_unwrapped1>::T_expr, 
377                                              typename asExpr<T_unwrapped2>::T_expr, 
378                                              T_numtype> >::T_selected T_typeprop;
379  typedef typename unwrapET<T_typeprop>::T_unwrapped T_result;
380  typedef T_numtype T_optype;
381
382    typedef T_expr1 T_ctorArg1;
383    typedef T_expr1 T_ctorArg2;
384    typedef int T_ctorArg3;  // dummy
385  typedef _bz_FunctorExpr2<P_functor, 
386                          _bz_typename P_expr1::T_range_result, 
387                          _bz_typename P_expr2::T_range_result, 
388                          P_result> T_range_result;
389
390    static const int 
391        numArrayOperands = T_expr1::numArrayOperands
392                         + T_expr2::numArrayOperands,
393        numTVOperands = T_expr1::numTVOperands + T_expr2::numTVOperands,
394        numTMOperands = T_expr1::numTMOperands + T_expr2::numTMOperands,
395        numIndexPlaceholders = T_expr1::numIndexPlaceholders
396                             + T_expr2::numIndexPlaceholders,
397      minWidth = BZ_MIN(T_expr1::minWidth, T_expr2::minWidth),
398      maxWidth = BZ_MAX(T_expr1::maxWidth, T_expr2::maxWidth),
399      rank_ = BZ_MAX(T_expr1::rank_, T_expr2::rank_);
400
401  template<int N> struct tvresult {
402    typedef _bz_FunctorExpr2<
403      T_functor,
404      typename T_expr1::template tvresult<N>::Type,
405      typename T_expr2::template tvresult<N>::Type,
406      T_numtype> Type; 
407  };
408 
409    _bz_FunctorExpr2(const _bz_FunctorExpr2<P_functor, P_expr1, P_expr2,
410        P_result>& a) 
411        : f_(a.f_), iter1_(a.iter1_), iter2_(a.iter2_)
412    { }
413
414    _bz_FunctorExpr2(BZ_ETPARM(T_functor) f, BZ_ETPARM(T_expr1) a,
415        BZ_ETPARM(T_expr2) b)
416        : f_(f), iter1_(a), iter2_(b)
417    { }
418
419    template<typename T1, typename T2>
420    _bz_FunctorExpr2(BZ_ETPARM(T_functor) f, BZ_ETPARM(T1) a, BZ_ETPARM(T2) b) 
421        : f_(f), iter1_(a), iter2_(b)
422    { }
423
424  /* Functions for reading. Because they must depend on the result
425   * type, they utilize a helper class.
426   */
427
428  // For numtypes, apply operator
429  template<typename T> struct readHelper {
430    static T_result fastRead(const T_functor& f, const T_expr1& iter1, 
431                             const T_expr2& iter2, diffType i) {
432      return f(iter1.fastRead(i), iter2.fastRead(i)); }
433    static T_result indexop(const T_functor& f, const T_expr1& iter1, 
434                            const T_expr2& iter2, int i) {
435      return f(iter1[i], iter2[i]); };
436    static T_result deref(const T_functor& f, const T_expr1& iter1, 
437                          const T_expr2& iter2) {
438      return f(*iter1, *iter2); }
439    static T_result first_value(const T_functor& f, const T_expr1& iter1, 
440                                const T_expr2& iter2)  {
441      return f(iter1.first_value(), iter2.first_value()); }
442    static T_result shift(const T_functor& f, const T_expr1& iter1, 
443                          const T_expr2& iter2,
444                          int offset, int dim) {
445      return f(iter1.shift(offset, dim),iter2.shift(offset, dim)); }
446    static T_result shift(const T_functor& f, const T_expr1& iter1, 
447                          const T_expr2& iter2,
448                          int offset1, int dim1,int offset2, int dim2) {
449      return f(iter1.shift(offset1, dim1, offset2, dim2),
450               iter2.shift(offset1, dim1, offset2, dim2)); }
451    template<int N_rank>
452#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
453    static T_result indexop(const T_functor& f, const T_expr& iter, 
454                            const T_expr2& iter2,
455                            const TinyVector<int, N_rank> i) {
456#else
457      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
458                              const T_expr2& iter2,
459                              const TinyVector<int, N_rank>& i) {
460#endif
461        return f(iter1(i), iter2(i)); };
462    };
463   
464  // For ET types, bypass operator and create expression
465    template<typename T> struct readHelper<ETBase<T> > {
466      static T_result fastRead(const T_functor& f, const T_expr1& iter1, 
467                               const T_expr2& iter2, diffType i) {
468        return T_result(f,iter1.fastRead(i), iter2.fastRead(i)); }
469    static T_result indexop(const T_functor& f, const T_expr1& iter1, 
470                            const T_expr2& iter2, int i) {
471      return T_result(f,iter1[i], iter2[i]); };
472    static T_result deref(const T_functor& f, const T_expr1& iter1, 
473                          const T_expr2& iter2) {
474      return T_result(f,*iter1, *iter2); }
475    static T_result first_value(const T_functor& f, const T_expr1& iter1, 
476                                const T_expr2& iter2)  {
477      return T_result(f,iter1.first_value(), iter2.first_value()); }
478    static T_result shift(const T_functor& f, const T_expr1& iter1, 
479                          const T_expr2& iter2,
480                          int offset, int dim) {
481      return T_result(f,iter1.shift(offset, dim),iter2.shift(offset, dim)); }
482    static T_result shift(const T_functor& f, const T_expr1& iter1, 
483                          const T_expr2& iter2,
484                          int offset1, int dim1,int offset2, int dim2) {
485      return T_result(f,iter1.shift(offset1, dim1, offset2, dim2),
486                      iter2.shift(offset1, dim1, offset2, dim2)); }
487      template<int N_rank>
488#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
489      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
490                              const T_expr2& iter2,
491                              const TinyVector<int, N_rank> i) {
492#else
493        static T_result indexop(const T_functor& f, const T_expr1& iter1, 
494                                const T_expr2& iter2,
495                                const TinyVector<int, N_rank>& i) {
496#endif
497          return T_result(f,iter1(i), iter2(i)); }
498      };
499
500    T_result fastRead(diffType i) const { 
501      return readHelper<T_typeprop>::fastRead(f_, iter1_, iter2_, i); }
502
503  template<int N>
504  typename tvresult<N>::Type fastRead_tv(diffType i) const
505      { return typename tvresult<N>::Type(f_,
506                                          iter1_.template fastRead_tv<N>(i),
507                                          iter2_.template fastRead_tv<N>(i)); }
508
509    T_result operator[](int i) const { 
510      return readHelper<T_typeprop>::indexop(f_, iter1_, iter2_, i); }
511
512    template<int N_rank>
513#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
514    T_result operator()(const TinyVector<int, N_rank> i) const {
515#else
516      T_result operator()(const TinyVector<int, N_rank>& i) const {
517#endif
518        return readHelper<T_typeprop>::indexop(f_, iter1_, iter2_, i); }
519
520      T_result operator*() const {
521        return readHelper<T_typeprop>::deref(f_, iter1_, iter2_); }
522
523      T_result first_value() const { 
524        return readHelper<T_typeprop>::first_value(f_, iter1_, iter2_); }
525
526    T_result shift(int offset, int dim) const {
527      return readHelper<T_typeprop>::shift(f_,iter1_,iter2_,offset, dim); }
528
529    T_result shift(int offset1, int dim1,int offset2, int dim2) const
530    {
531      return readHelper<T_typeprop>::shift(f_,iter1_,iter2_,
532                                           offset1, dim1, offset2, dim2); }
533   
534      // ****** end reading 
535
536  T_range_result operator()(RectDomain<rank_> d) const
537  {
538    return T_range_result(f_, iter1_(d), iter2_(d));
539  }
540
541  bool isVectorAligned(diffType offset) const 
542  { return iter1_.isVectorAligned(offset) && 
543      iter2_.isVectorAligned(offset); }
544
545    int ascending(const int rank) const {
546        return bounds::compute_ascending(rank, iter1_.ascending(rank),
547            iter2_.ascending(rank));
548    }
549
550    int ordering(const int rank) const {
551        return bounds::compute_ordering(rank, iter1_.ordering(rank),
552            iter2_.ordering(rank));
553    }
554 
555    int lbound(const int rank) const { 
556        return bounds::compute_lbound(rank, iter1_.lbound(rank),
557            iter2_.lbound(rank));
558    }
559 
560    int ubound(const int rank) const {
561        return bounds::compute_ubound(rank, iter1_.ubound(rank),
562            iter2_.ubound(rank));
563    }
564
565  // defer calculation to lbound/ubound
566  RectDomain<rank_> domain() const 
567  { 
568    TinyVector<int, rank_> lb, ub;
569    for(int r=0; r<rank_; ++r) {
570      lb[r]=lbound(r); ub[r]=ubound(r); 
571    }
572    return RectDomain<rank_>(lb,ub);
573  }
574 
575    void push(const int position) { 
576        iter1_.push(position); 
577        iter2_.push(position);
578    }
579 
580    void pop(const int position) { 
581        iter1_.pop(position); 
582        iter2_.pop(position);
583    }
584 
585    void advance() { 
586        iter1_.advance(); 
587        iter2_.advance();
588    }
589 
590    void advance(const int n) {
591        iter1_.advance(n);
592        iter2_.advance(n);
593    }
594 
595    void loadStride(const int rank) {
596        iter1_.loadStride(rank); 
597        iter2_.loadStride(rank);
598    }
599 
600    bool isUnitStride(const int rank) const
601    { return iter1_.isUnitStride(rank) && iter2_.isUnitStride(rank); }
602 
603    bool isUnitStride() const
604    { return iter1_.isUnitStride() && iter2_.isUnitStride(); }
605 
606    void advanceUnitStride() { 
607        iter1_.advanceUnitStride(); 
608        iter2_.advanceUnitStride();
609    }
610 
611    bool canCollapse(const int outerLoopRank,const int innerLoopRank) const
612    { 
613        return iter1_.canCollapse(outerLoopRank, innerLoopRank)
614            && iter2_.canCollapse(outerLoopRank, innerLoopRank);
615    }
616
617    // this is needed for the stencil expression fastRead to work
618    void _bz_offsetData(sizeType i)
619    { iter1_._bz_offsetData(i); iter2_._bz_offsetData(i); }
620
621    // and these are needed for stencil expression shift to work
622    void _bz_offsetData(sizeType offset, int dim)
623    { 
624      iter1_._bz_offsetData(offset, dim);
625      iter2_._bz_offsetData(offset, dim);
626    }
627 
628    void _bz_offsetData(sizeType offset1, int dim1, sizeType offset2, int dim2)
629    { 
630      iter1_._bz_offsetData(offset1, dim1, offset2, dim2);
631      iter2_._bz_offsetData(offset1, dim1, offset2, dim2);
632    }
633
634    diffType suggestStride(const int rank) const
635    {
636        diffType stride1 = iter1_.suggestStride(rank);
637        diffType stride2 = iter2_.suggestStride(rank);
638        return ( stride1>stride2 ? stride1 : stride2 );
639    }
640 
641    bool isStride(const int rank,const diffType stride) const
642    {
643        return iter1_.isStride(rank,stride) && iter2_.isStride(rank,stride);
644    }
645 
646    void prettyPrint(BZ_STD_SCOPE(string) &str, 
647        prettyPrintFormat& format) const
648    {
649        str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_functor);
650        str += "(";
651        iter1_.prettyPrint(str, format);
652        str += ",";
653        iter2_.prettyPrint(str, format);
654        str += ")";
655    }
656
657    template<int N_rank>
658    void moveTo(const TinyVector<int,N_rank>& i)
659    {
660        iter1_.moveTo(i);
661        iter2_.moveTo(i);
662    }
663 
664    template<typename T_shape>
665    bool shapeCheck(const T_shape& shape) const
666    { return iter1_.shapeCheck(shape) && iter2_.shapeCheck(shape); }
667 
668  // sliceinfo for expressions
669  template<typename T1, typename T2 = nilArraySection, 
670           class T3 = nilArraySection, typename T4 = nilArraySection, 
671           class T5 = nilArraySection, typename T6 = nilArraySection, 
672           class T7 = nilArraySection, typename T8 = nilArraySection, 
673           class T9 = nilArraySection, typename T10 = nilArraySection, 
674           class T11 = nilArraySection>
675  class SliceInfo {
676  public:
677    typedef typename T_expr1::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice1;
678    typedef typename T_expr2::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice2;
679    typedef _bz_FunctorExpr2<T_functor, T_slice1, T_slice2, T_numtype> T_slice;
680};
681
682    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
683        typename T7, typename T8, typename T9, typename T10, typename T11>
684    typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
685    operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
686    {
687      return typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
688        (f_,iter1_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11),
689         iter2_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
690    }
691
692protected:
693    _bz_FunctorExpr2() { }
694
695    T_functor f_;
696    T_expr1 iter1_;
697    T_expr2 iter2_;
698};
699
700template<typename P_functor, typename P_expr1, typename P_expr2, typename P_expr3,
701    class P_result>
702class _bz_FunctorExpr3
703{
704public:
705    typedef P_functor T_functor;
706    typedef P_expr1 T_expr1;
707    typedef P_expr2 T_expr2;
708    typedef P_expr3 T_expr3;
709    typedef _bz_typename T_expr1::T_numtype T_numtype1;
710    typedef _bz_typename T_expr2::T_numtype T_numtype2;
711    typedef _bz_typename T_expr3::T_numtype T_numtype3;
712    typedef P_result T_numtype;
713
714  // select return type
715  typedef typename unwrapET<typename T_expr1::T_result>::T_unwrapped T_unwrapped1;
716  typedef typename unwrapET<typename T_expr2::T_result>::T_unwrapped T_unwrapped2;
717  typedef typename unwrapET<typename T_expr3::T_result>::T_unwrapped T_unwrapped3;
718  typedef typename selectET2<typename T_expr1::T_typeprop, 
719                             typename T_expr2::T_typeprop, 
720                             T_numtype, 
721                             char>::T_selected T_intermediary;
722
723  typedef typename selectET2<T_intermediary,
724                             typename T_expr3::T_typeprop, 
725                             T_numtype, 
726                             _bz_FunctorExpr3<P_functor,
727                                              typename asExpr<T_unwrapped1>::T_expr, 
728                                              typename asExpr<T_unwrapped2>::T_expr, 
729                                              typename asExpr<T_unwrapped3>::T_expr, 
730                                              T_numtype> >::T_selected T_typeprop;
731  typedef typename unwrapET<T_typeprop>::T_unwrapped T_result;
732  typedef T_numtype T_optype;
733
734    typedef T_expr1 T_ctorArg1;
735    typedef T_expr2 T_ctorArg2;
736    typedef T_expr3 T_ctorArg3;
737  typedef _bz_FunctorExpr3<P_functor, 
738                          _bz_typename P_expr1::T_range_result, 
739                          _bz_typename P_expr2::T_range_result, 
740                          _bz_typename P_expr3::T_range_result, 
741                          P_result> T_range_result;
742
743    static const int 
744        numArrayOperands = T_expr1::numArrayOperands
745                         + T_expr2::numArrayOperands
746                         + T_expr3::numArrayOperands,
747        numTVOperands = T_expr1::numTVOperands +
748      T_expr2::numTVOperands + 
749      T_expr3::numTVOperands,
750        numTMOperands = T_expr1::numTMOperands + 
751      T_expr2::numTMOperands + 
752      T_expr3::numTMOperands,
753        numIndexPlaceholders = T_expr1::numIndexPlaceholders
754                             + T_expr2::numIndexPlaceholders
755                             + T_expr3::numIndexPlaceholders,
756      minWidth = BZ_MIN(BZ_MIN(T_expr1::minWidth, T_expr2::minWidth),
757                        T_expr3::minWidth),
758      maxWidth = BZ_MAX(BZ_MAX(T_expr1::maxWidth, T_expr2::maxWidth), 
759                        T_expr3::maxWidth),
760      rank_ = BZ_MAX(BZ_MAX(T_expr1::rank_, T_expr2::rank_),
761                     T_expr3::rank_);
762
763  template<int N> struct tvresult {
764    typedef _bz_FunctorExpr3<
765      T_functor,
766      typename T_expr1::template tvresult<N>::Type,
767      typename T_expr2::template tvresult<N>::Type,
768      typename T_expr3::template tvresult<N>::Type,
769      T_numtype> Type; 
770  };
771 
772    _bz_FunctorExpr3(const _bz_FunctorExpr3<P_functor, P_expr1, P_expr2,
773        P_expr3, P_result>& a) 
774        : f_(a.f_), iter1_(a.iter1_), iter2_(a.iter2_), iter3_(a.iter3_)
775    { }
776
777    _bz_FunctorExpr3(BZ_ETPARM(T_functor) f, BZ_ETPARM(T_expr1) a,
778        BZ_ETPARM(T_expr2) b, BZ_ETPARM(T_expr3) c)
779        : f_(f), iter1_(a), iter2_(b), iter3_(c)
780    { }
781
782    template<typename T1, typename T2, typename T3>
783    _bz_FunctorExpr3(BZ_ETPARM(T_functor) f, BZ_ETPARM(T1) a, BZ_ETPARM(T2) b,
784        BZ_ETPARM(T3) c) 
785        : f_(f), iter1_(a), iter2_(b), iter3_(c)
786    { }
787
788  /* Functions for reading. Because they must depend on the result
789   * type, they utilize a helper class.
790   */
791
792  // For numtypes, apply operator
793  template<typename T> struct readHelper {
794    static T_result fastRead(const T_functor& f, const T_expr1& iter1, 
795                             const T_expr2& iter2, const T_expr3& iter3, 
796                             diffType i) {
797      return f(iter1.fastRead(i), iter2.fastRead(i), 
798               iter3.fastRead(i)); }
799    static T_result indexop(const T_functor& f, const T_expr1& iter1, 
800                            const T_expr2& iter2, const T_expr3& iter3, 
801                            int i) {
802      return f(iter1[i], iter2[i], iter3[i]); }
803    static T_result deref(const T_functor& f, const T_expr1& iter1, 
804                          const T_expr2& iter2, const T_expr3& iter3) {
805      return f(*iter1, *iter2, *iter3); };
806    static T_result first_value(const T_functor& f, const T_expr1& iter1, 
807                                const T_expr2& iter2, const T_expr3& iter3)  {
808      return f(iter1.first_value(), iter2.first_value(),
809                         iter3.first_value()); }
810    static T_result shift(const T_functor& f, const T_expr1& iter1, 
811                          const T_expr2& iter2, const T_expr3& iter3,
812                          int offset, int dim) {
813      return f(iter1.shift(offset, dim),iter2.shift(offset, dim),
814               iter3.shift(offset, dim)); }
815    static T_result shift(const T_functor& f, const T_expr1& iter1, 
816                          const T_expr2& iter2, const T_expr3& iter3,
817                          int offset1, int dim1,int offset2, int dim2) {
818      return f(iter1.shift(offset1, dim1, offset2, dim2),
819               iter2.shift(offset1, dim1, offset2, dim2),
820               iter2.shift(offset1, dim1, offset2, dim2)); }
821    template<int N_rank>
822#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
823      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
824                              const T_expr2& iter2, const T_expr3& iter3, 
825                              const TinyVector<int, N_rank> i) {
826#else
827      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
828                              const T_expr2& iter2, const T_expr3& iter3, 
829                              const TinyVector<int, N_rank>& i) {
830#endif
831        return f(iter1(i), iter2(i), iter3(i) ); };
832    };
833   
834    // For ET types, bypass operator and create expression
835    template<typename T> struct readHelper<ETBase<T> > {
836    static T_result fastRead(const T_functor& f, const T_expr1& iter1, 
837                             const T_expr2& iter2, const T_expr3& iter3, 
838                             diffType i) {
839      return T_result(f, iter1.fastRead(i), iter2.fastRead(i), 
840                      iter3.fastRead(i)); }
841    static T_result indexop(const T_functor& f, const T_expr1& iter1, 
842                            const T_expr2& iter2, const T_expr3& iter3, 
843                            int i) {
844      return T_result(f, iter1[i], iter2[i], iter3[i]); };
845    static T_result deref(const T_functor& f, const T_expr1& iter1, 
846                          const T_expr2& iter2, const T_expr3& iter3) {
847      return T_result(f, *iter1, *iter2, *iter3); };
848    static T_result first_value(const T_functor& f, const T_expr1& iter1, 
849                                const T_expr2& iter2, const T_expr3& iter3)  {
850      return T_result(f, iter1.first_value(), iter2.first_value(),
851                      iter3.first_value()); }
852    static T_result shift(const T_functor& f, const T_expr1& iter1, 
853                          const T_expr2& iter2, const T_expr3& iter3,
854                          int offset, int dim) {
855      return T_result(f,iter1.shift(offset, dim),iter2.shift(offset, dim),
856                      iter3.shift(offset, dim)); }
857    static T_result shift(const T_functor& f, const T_expr1& iter1, 
858                          const T_expr2& iter2, const T_expr3& iter3,
859                          int offset1, int dim1,int offset2, int dim2) {
860      return T_result(f, iter1.shift(offset1, dim1, offset2, dim2),
861                      iter2.shift(offset1, dim1, offset2, dim2),
862                      iter2.shift(offset1, dim1, offset2, dim2)); }
863      template<int N_rank>
864#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
865      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
866                              const T_expr2& iter2, const T_expr3& iter3, 
867                              const TinyVector<int, N_rank> i) {
868#else
869      static T_result indexop(const T_functor& f, const T_expr1& iter1, 
870                              const T_expr2& iter2, const T_expr3& iter3, 
871                              const TinyVector<int, N_rank>& i) {
872#endif
873        return T_result(f, iter1(i), iter2(i), iter3(i) ); }
874      };
875
876    T_result fastRead(diffType i) const { 
877      return readHelper<T_typeprop>::fastRead(f_, iter1_, iter2_, iter3_, i); }
878
879      template<int N>
880      typename tvresult<N>::Type fastRead_tv(diffType i) const
881      { return typename tvresult<N>::Type(f_,
882                                          iter1_.template fastRead_tv<N>(i),
883                                          iter2_.template fastRead_tv<N>(i),
884                                          iter3_.template fastRead_tv<N>(i)); }
885
886    T_result operator[](int i) const { 
887      return readHelper<T_typeprop>::indexop(f_, iter1_, iter2_, iter3_, i); }
888
889    template<int N_rank>
890#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
891    T_result operator()(const TinyVector<int, N_rank> i) const {
892#else
893      T_result operator()(const TinyVector<int, N_rank>& i) const {
894#endif
895        return readHelper<T_typeprop>::indexop(f_, iter1_, iter2_, iter3_, i); }
896
897      T_result operator*() const {
898        return readHelper<T_typeprop>::deref(f_, iter1_, iter2_, iter3_); }
899   
900      T_result first_value() const { 
901        return readHelper<T_typeprop>::first_value(f_, iter1_, iter2_, iter3_); }
902
903      T_result shift(int offset, int dim) const {
904        return readHelper<T_typeprop>::shift(f_,iter1_,iter2_, 
905                                             iter3_, offset, dim); }
906
907    T_result shift(int offset1, int dim1,int offset2, int dim2) const {
908      return readHelper<T_typeprop>::shift(f_,iter1_,iter2_,iter3_,
909                                           offset1, dim1, offset2, dim2); }
910
911      // ****** end reading
912 
913  bool isVectorAligned(diffType offset) const 
914  { return iter1_.isVectorAligned(offset) &&
915      iter2_.isVectorAligned(offset) &&
916      iter3_.isVectorAligned(offset); }
917
918  T_range_result operator()(RectDomain<rank_> d) const
919  {
920    return T_range_result(f_, iter1_(d), iter2_(d), iter3_(d));
921  }
922
923    int ascending(const int rank) const {
924        return bounds::compute_ascending(rank, iter1_.ascending(rank),
925            bounds::compute_ascending(rank, iter2_.ascending(rank),
926            iter3_.ascending(rank)));
927    }
928
929    int ordering(const int rank) const {
930        return bounds::compute_ordering(rank, iter1_.ordering(rank),
931            bounds::compute_ordering(rank, iter2_.ordering(rank),
932            iter3_.ordering(rank)));
933    }
934 
935    int lbound(const int rank) const {
936        return bounds::compute_lbound(rank, iter1_.lbound(rank),
937            bounds::compute_lbound(rank, iter2_.lbound(rank),
938            iter3_.lbound(rank)));
939    }
940 
941    int ubound(const int rank) const {
942        return bounds::compute_ubound(rank, iter1_.ubound(rank),
943            bounds::compute_ubound(rank, iter2_.ubound(rank),
944            iter3_.ubound(rank)));
945    }
946 
947  // defer calculation to lbound/ubound
948  RectDomain<rank_> domain() const 
949  { 
950    TinyVector<int, rank_> lb, ub;
951    for(int r=0; r<rank_; ++r) {
952      lb[r]=lbound(r); ub[r]=ubound(r); 
953    }
954    return RectDomain<rank_>(lb,ub);
955  }
956 
957    void push(const int position) { 
958        iter1_.push(position); 
959        iter2_.push(position);
960        iter3_.push(position);
961    }
962 
963    void pop(const int position) { 
964        iter1_.pop(position); 
965        iter2_.pop(position);
966        iter3_.pop(position);
967    }
968 
969    void advance() { 
970        iter1_.advance(); 
971        iter2_.advance();
972        iter3_.advance();
973    }
974 
975    void advance(const int n) {
976        iter1_.advance(n);
977        iter2_.advance(n);
978        iter3_.advance(n);
979    }
980 
981    void loadStride(const int rank) { 
982        iter1_.loadStride(rank); 
983        iter2_.loadStride(rank);
984        iter3_.loadStride(rank);
985    }
986 
987    bool isUnitStride(const int rank) const {
988        return iter1_.isUnitStride(rank) && iter2_.isUnitStride(rank)
989            && iter3_.isUnitStride(rank);
990    }
991 
992    bool isUnitStride() const {
993        return iter1_.isUnitStride() && iter2_.isUnitStride()
994            && iter3_.isUnitStride();
995    }
996 
997    void advanceUnitStride() { 
998        iter1_.advanceUnitStride(); 
999        iter2_.advanceUnitStride();
1000        iter3_.advanceUnitStride();
1001    }
1002 
1003    bool canCollapse(const int outerLoopRank,const int innerLoopRank) const { 
1004        return iter1_.canCollapse(outerLoopRank, innerLoopRank)
1005            && iter2_.canCollapse(outerLoopRank, innerLoopRank)
1006            && iter3_.canCollapse(outerLoopRank, innerLoopRank);
1007    }
1008
1009    // this is needed for the stencil expression fastRead to work
1010    void _bz_offsetData(sizeType i)
1011    { iter1_._bz_offsetData(i); iter2_._bz_offsetData(i); 
1012      iter3_._bz_offsetData(i); }
1013
1014    // and these are needed for stencil expression shift to work
1015    void _bz_offsetData(sizeType offset, int dim)
1016    { 
1017      iter1_._bz_offsetData(offset, dim);
1018      iter2_._bz_offsetData(offset, dim);
1019      iter3_._bz_offsetData(offset, dim);
1020    }
1021 
1022    void _bz_offsetData(sizeType offset1, int dim1, sizeType offset2, int dim2)
1023    {
1024      iter1_._bz_offsetData(offset1, dim1, offset2, dim2);
1025      iter2_._bz_offsetData(offset1, dim1, offset2, dim2);
1026      iter3_._bz_offsetData(offset1, dim1, offset2, dim2);
1027    }
1028
1029    diffType suggestStride(const int rank) const {
1030        diffType stride1 = iter1_.suggestStride(rank);
1031        diffType stride2 = iter2_.suggestStride(rank);
1032        diffType stride3 = iter3_.suggestStride(rank);
1033        return ( stride1 > (stride2 = (stride2>stride3 ? stride2 : stride3)) ?
1034            stride1 : stride2 );
1035    }
1036 
1037    bool isStride(const int rank,const diffType stride) const {
1038        return iter1_.isStride(rank,stride) && iter2_.isStride(rank,stride)
1039            && iter3_.isStride(rank,stride);
1040    }
1041 
1042    void prettyPrint(BZ_STD_SCOPE(string) &str, 
1043        prettyPrintFormat& format) const
1044    {
1045        str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_functor);
1046        str += "(";
1047        iter1_.prettyPrint(str, format);
1048        str += ",";
1049        iter2_.prettyPrint(str, format);
1050        str += ",";
1051        iter3_.prettyPrint(str, format);
1052        str += ")";
1053    }
1054
1055    template<int N_rank>
1056    void moveTo(const TinyVector<int,N_rank>& i)
1057    {
1058        iter1_.moveTo(i);
1059        iter2_.moveTo(i);
1060        iter3_.moveTo(i);
1061    } 
1062 
1063    template<typename T_shape>
1064    bool shapeCheck(const T_shape& shape) const
1065    {
1066        return iter1_.shapeCheck(shape) && iter2_.shapeCheck(shape)
1067            && iter3_.shapeCheck(shape);
1068    }
1069
1070  // sliceinfo for expressions
1071  template<typename T1, typename T2 = nilArraySection, 
1072           class T3 = nilArraySection, typename T4 = nilArraySection, 
1073           class T5 = nilArraySection, typename T6 = nilArraySection, 
1074           class T7 = nilArraySection, typename T8 = nilArraySection, 
1075           class T9 = nilArraySection, typename T10 = nilArraySection, 
1076           class T11 = nilArraySection>
1077  class SliceInfo {
1078  public:
1079    typedef typename T_expr1::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice1;
1080    typedef typename T_expr2::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice2;
1081    typedef typename T_expr3::template SliceInfo<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::T_slice T_slice3;
1082    typedef _bz_FunctorExpr3<T_functor, T_slice1, T_slice2, T_slice3, T_numtype> T_slice;
1083};
1084
1085    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
1086        typename T7, typename T8, typename T9, typename T10, typename T11>
1087    typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
1088    operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
1089    {
1090      return typename SliceInfo<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
1091        (f_,iter1_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11),
1092         iter2_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11),
1093         iter3_(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
1094    }
1095 
1096protected:
1097    _bz_FunctorExpr3() { }
1098
1099    T_functor f_;
1100    T_expr1 iter1_;
1101    T_expr2 iter2_;
1102    T_expr3 iter3_;
1103};
1104
1105template<typename P_functor, typename P_expr>
1106_bz_inline_et
1107_bz_ArrayExpr<_bz_FunctorExpr<P_functor, _bz_typename asExpr<P_expr>::T_expr,
1108    _bz_typename asExpr<P_expr>::T_expr::T_numtype> >
1109applyFunctor(const P_functor& f, const ETBase<P_expr>& a)
1110{
1111    typedef _bz_FunctorExpr<P_functor,
1112        _bz_typename asExpr<P_expr>::T_expr,
1113        _bz_typename asExpr<P_expr>::T_expr::T_numtype> f1;
1114    return _bz_ArrayExpr<f1>(f, a.unwrap());
1115}
1116
1117template<typename P_functor, typename P_expr1, typename P_expr2>
1118_bz_inline_et
1119_bz_ArrayExpr<_bz_FunctorExpr2<P_functor,
1120    _bz_typename asExpr<P_expr1>::T_expr,
1121    _bz_typename asExpr<P_expr2>::T_expr,
1122    BZ_PROMOTE(_bz_typename asExpr<P_expr1>::T_expr::T_numtype,
1123               _bz_typename asExpr<P_expr2>::T_expr::T_numtype)> >
1124applyFunctor(const P_functor& f,
1125    const ETBase<P_expr1>& a, const ETBase<P_expr2>& b)
1126{
1127    typedef _bz_FunctorExpr2<P_functor,
1128        _bz_typename asExpr<P_expr1>::T_expr,
1129        _bz_typename asExpr<P_expr2>::T_expr,
1130        BZ_PROMOTE(_bz_typename asExpr<P_expr1>::T_expr::T_numtype,
1131                   _bz_typename asExpr<P_expr2>::T_expr::T_numtype)> f2;
1132    return _bz_ArrayExpr<f2>(f, a.unwrap(), b.unwrap());
1133}
1134
1135template<typename P_functor, typename P_expr1, typename P_expr2, typename P_expr3>
1136_bz_inline_et
1137_bz_ArrayExpr<_bz_FunctorExpr3<P_functor,
1138    _bz_typename asExpr<P_expr1>::T_expr,
1139    _bz_typename asExpr<P_expr2>::T_expr, 
1140    _bz_typename asExpr<P_expr3>::T_expr,
1141    BZ_PROMOTE(_bz_typename asExpr<P_expr1>::T_expr::T_numtype,
1142               BZ_PROMOTE(_bz_typename asExpr<P_expr2>::T_expr::T_numtype,
1143                          _bz_typename asExpr<P_expr3>::T_expr::T_numtype))> >
1144applyFunctor(const P_functor& f, const ETBase<P_expr1>& a,
1145    const ETBase<P_expr2>& b, const ETBase<P_expr3>& c)
1146{
1147    typedef _bz_FunctorExpr3<P_functor,
1148        _bz_typename asExpr<P_expr1>::T_expr,
1149        _bz_typename asExpr<P_expr2>::T_expr,
1150        _bz_typename asExpr<P_expr3>::T_expr,
1151        BZ_PROMOTE(_bz_typename asExpr<P_expr1>::T_expr::T_numtype,
1152            BZ_PROMOTE(_bz_typename asExpr<P_expr2>::T_expr::T_numtype,
1153                       _bz_typename asExpr<P_expr3>::T_expr::T_numtype))> f3;
1154    return _bz_ArrayExpr<f3>(f, a.unwrap(), b.unwrap(), c.unwrap());
1155}
1156
1157BZ_NAMESPACE_END // End of stuff in namespace
1158
1159
1160#define _BZ_MAKE_FUNCTOR(classname, funcname)                             \
1161class _bz_Functor ## classname ## funcname                                \
1162{                                                                         \
1163public:                                                                   \
1164    _bz_Functor ## classname ## funcname (const classname& c)             \
1165        : c_(c)                                                           \
1166    { }                                                                   \
1167    template<typename T_numtype1>                                       \
1168    inline T_numtype1 operator()(T_numtype1 x) const                      \
1169    { return c_.funcname(x); }                                            \
1170private:                                                                  \
1171    const classname& c_;                                                  \
1172};
1173
1174#define _BZ_MAKE_FUNCTOR2(classname, funcname)                            \
1175class _bz_Functor ## classname ## funcname                                \
1176{                                                                         \
1177public:                                                                   \
1178    _bz_Functor ## classname ## funcname (const classname& c)             \
1179        : c_(c)                                                           \
1180    { }                                                                   \
1181    template<typename T_numtype1, typename T_numtype2>                          \
1182    inline BZ_PROMOTE(T_numtype1, T_numtype2)                             \
1183    operator()(T_numtype1 x, T_numtype2 y) const                          \
1184    { return c_.funcname(x,y); }                                          \
1185private:                                                                  \
1186    const classname& c_;                                                  \
1187};
1188
1189#define _BZ_MAKE_FUNCTOR3(classname, funcname)                            \
1190class _bz_Functor ## classname ## funcname                                \
1191{                                                                         \
1192public:                                                                   \
1193    _bz_Functor ## classname ## funcname (const classname& c)             \
1194        : c_(c)                                                           \
1195    { }                                                                   \
1196    template<typename T_numtype1, typename T_numtype2, typename T_numtype3>        \
1197    inline BZ_PROMOTE(BZ_PROMOTE(T_numtype1, T_numtype2), T_numtype3)     \
1198    operator()(T_numtype1 x, T_numtype2 y, T_numtype3 z) const            \
1199    { return c_.funcname(x,y,z); }                                        \
1200private:                                                                  \
1201    const classname& c_;                                                  \
1202};
1203
1204
1205#define _BZ_MAKE_FUNCTOR_RET(classname, funcname, ret)                    \
1206class _bz_Functor ## classname ## funcname                                \
1207{                                                                         \
1208public:                                                                   \
1209    _bz_Functor ## classname ## funcname (const classname& c)             \
1210        : c_(c)                                                           \
1211    { }                                                                   \
1212    template<typename T_numtype1>                                            \
1213    inline ret operator()(T_numtype1 x) const                             \
1214    { return c_.funcname(x); }                                            \
1215private:                                                                  \
1216    const classname& c_;                                                  \
1217};
1218
1219#define _BZ_MAKE_FUNCTOR2_RET(classname, funcname, ret)                   \
1220class _bz_Functor ## classname ## funcname                                \
1221{                                                                         \
1222public:                                                                   \
1223    _bz_Functor ## classname ## funcname (const classname& c)             \
1224        : c_(c)                                                           \
1225    { }                                                                   \
1226    template<typename T_numtype1, typename T_numtype2>                          \
1227    inline ret operator()(T_numtype1 x, T_numtype2 y) const               \
1228    { return c_.funcname(x,y); }                                          \
1229private:                                                                  \
1230    const classname& c_;                                                  \
1231};
1232
1233#define _BZ_MAKE_FUNCTOR3_RET(classname, funcname, ret)                   \
1234class _bz_Functor ## classname ## funcname                                \
1235{                                                                         \
1236public:                                                                   \
1237    _bz_Functor ## classname ## funcname (const classname& c)             \
1238        : c_(c)                                                           \
1239    { }                                                                   \
1240    template<typename T_numtype1, typename T_numtype2, typename T_numtype3>        \
1241    inline ret operator()(T_numtype1 x, T_numtype2 y, T_numtype3 z) const \
1242    { return c_.funcname(x,y,z); }                                        \
1243private:                                                                  \
1244    const classname& c_;                                                  \
1245};
1246
1247
1248#define BZ_DECLARE_FUNCTOR(classname)                                     \
1249template<typename P_expr>                                                 \
1250BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr)<            \
1251    classname,                                                            \
1252    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,                  \
1253  _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr::T_optype> >      \
1254operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr>& a) const                 \
1255{                                                                         \
1256    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1257        BZ_BLITZ_SCOPE(_bz_FunctorExpr)<classname,                        \
1258        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,              \
1259        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr::T_optype> > \
1260        (*this, a.unwrap());                                              \
1261}
1262
1263#define BZ_DECLARE_FUNCTOR2(classname)                                    \
1264template<typename P_expr1, typename P_expr2>                              \
1265BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<           \
1266    classname,                                                            \
1267    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1268    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1269    BZ_PROMOTE(_bz_typename                                               \
1270               BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,        \
1271               _bz_typename                                               \
1272               BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype)> >     \
1273operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                      \
1274           const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b) const                \
1275{                                                                         \
1276    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1277        BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<classname,                       \
1278        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1279        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1280        BZ_PROMOTE(_bz_typename                                           \
1281                   BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,    \
1282                   _bz_typename                                           \
1283                   BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype)> > \
1284        (*this, a.unwrap(), b.unwrap());                                  \
1285}
1286
1287#define BZ_DECLARE_FUNCTOR3(classname)                                    \
1288template<typename P_expr1, typename P_expr2, typename P_expr3>            \
1289BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<           \
1290    classname,                                                            \
1291    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1292    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1293    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,                 \
1294    BZ_PROMOTE(_bz_typename                                               \
1295               BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,        \
1296    BZ_PROMOTE(_bz_typename                                               \
1297               BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype,        \
1298               _bz_typename                                               \
1299               BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr::T_optype))> >    \
1300operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                      \
1301           const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b,                      \
1302           const BZ_BLITZ_SCOPE(ETBase)<P_expr3>& c) const                \
1303{                                                                         \
1304    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1305        BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<classname,                       \
1306        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1307        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1308        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,             \
1309        BZ_PROMOTE(_bz_typename                                           \
1310                   BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,    \
1311        BZ_PROMOTE(_bz_typename                                           \
1312                   BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype,    \
1313                   _bz_typename                                           \
1314                   BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr::T_optype))> >\
1315        (*this, a.unwrap(), b.unwrap(), c.unwrap());                      \
1316}
1317
1318
1319#define BZ_DECLARE_FUNCTOR_RET(classname, ret)                            \
1320template<typename P_expr>                                                 \
1321BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr)<            \
1322    classname,                                                            \
1323    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,                  \
1324    ret> >                                                                \
1325operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr>& a) const                 \
1326{                                                                         \
1327    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1328        BZ_BLITZ_SCOPE(_bz_FunctorExpr)<classname,                        \
1329        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,              \
1330        ret> >                                                            \
1331        (*this, a.unwrap());                                              \
1332}
1333
1334#define BZ_DECLARE_FUNCTOR2_RET(classname, ret)                           \
1335template<typename P_expr1, typename P_expr2>                              \
1336BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<           \
1337    classname,                                                            \
1338    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1339    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1340    ret> >                                                                \
1341operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                      \
1342           const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b) const                \
1343{                                                                         \
1344    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1345        BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<classname,                       \
1346        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1347        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1348        ret> >                                                            \
1349        (*this, a.unwrap(), b.unwrap());                                  \
1350}
1351
1352#define BZ_DECLARE_FUNCTOR3_RET(classname, ret)                           \
1353template<typename P_expr1, typename P_expr2, typename P_expr3>            \
1354BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<           \
1355    classname,                                                            \
1356    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1357    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1358    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,                 \
1359    ret> >                                                                \
1360operator()(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                      \
1361           const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b,                      \
1362           const BZ_BLITZ_SCOPE(ETBase)<P_expr3>& c) const                \
1363{                                                                         \
1364    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1365        BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<classname,                       \
1366        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1367        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1368        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,             \
1369        ret> >                                                            \
1370        (*this, a.unwrap(), b.unwrap(), c.unwrap());                      \
1371}
1372
1373
1374#define BZ_DECLARE_MEMBER_FUNCTION(classname, funcname)                   \
1375_BZ_MAKE_FUNCTOR(classname, funcname)                                     \
1376template<typename P_expr>                                                 \
1377BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr)<            \
1378    _bz_Functor ## classname ## funcname,                                 \
1379    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,                  \
1380    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr::T_optype> >     \
1381funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr>& a) const                   \
1382{                                                                         \
1383    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1384        BZ_BLITZ_SCOPE(_bz_FunctorExpr)<                                  \
1385        _bz_Functor ## classname ## funcname,                             \
1386        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,              \
1387        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr::T_optype> > \
1388      (_bz_Functor ## classname ## funcname(*this), a.unwrap());        \
1389}
1390
1391#define BZ_DECLARE_MEMBER_FUNCTION2(classname, funcname)                  \
1392_BZ_MAKE_FUNCTOR2(classname, funcname)                                    \
1393template<typename P_expr1, typename P_expr2>                              \
1394BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<           \
1395    _bz_Functor ## classname ## funcname,                                 \
1396    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1397    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1398    BZ_PROMOTE(_bz_typename                                               \
1399               BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,        \
1400               _bz_typename                                               \
1401               BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype)> >     \
1402funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                        \
1403         const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b) const                  \
1404{                                                                         \
1405    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1406        BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<                                 \
1407        _bz_Functor ## classname ## funcname,                             \
1408        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1409        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1410        BZ_PROMOTE(_bz_typename                                           \
1411                   BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,    \
1412                   _bz_typename                                           \
1413                   BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype)> > \
1414      (_bz_Functor ## classname ## funcname(*this), a.unwrap(), b.unwrap()); \
1415}
1416
1417#define BZ_DECLARE_MEMBER_FUNCTION3(classname, funcname)                  \
1418_BZ_MAKE_FUNCTOR3(classname, funcname)                                    \
1419template<typename P_expr1, typename P_expr2, typename P_expr3>            \
1420BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<           \
1421    _bz_Functor ## classname ## funcname,                                 \
1422    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1423    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1424    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,                 \
1425    BZ_PROMOTE(_bz_typename                                               \
1426               BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,        \
1427    BZ_PROMOTE(_bz_typename                                               \
1428               BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype,        \
1429               _bz_typename                                               \
1430               BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr::T_optype))> >    \
1431funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                        \
1432         const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b,                        \
1433         const BZ_BLITZ_SCOPE(ETBase)<P_expr3>& c) const                  \
1434{                                                                         \
1435    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1436        BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<                                 \
1437        _bz_Functor ## classname ## funcname,                             \
1438        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1439        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1440        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,             \
1441        BZ_PROMOTE(_bz_typename                                           \
1442                   BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr::T_optype,    \
1443        BZ_PROMOTE(_bz_typename                                           \
1444                   BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr::T_optype,    \
1445                   _bz_typename                                           \
1446                   BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr::T_optype))> >\
1447      (_bz_Functor ## classname ## funcname(*this),                     \
1448       a.unwrap(), b.unwrap(), c.unwrap());                             \
1449}
1450
1451
1452#define BZ_DECLARE_MEMBER_FUNCTION_RET(classname, funcname, ret)          \
1453_BZ_MAKE_FUNCTOR_RET(classname, funcname, ret)                            \
1454template<typename P_expr>                                                 \
1455BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr)<            \
1456    _bz_Functor ## classname ## funcname,                                 \
1457    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr,                  \
1458    ret> >                                                                \
1459funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr>& a) const                   \
1460{                                                                         \
1461    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1462        BZ_BLITZ_SCOPE(_bz_FunctorExpr)<                                  \
1463        _bz_Functor ## classname ## funcname,                             \
1464      _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr>::T_expr, ret> >       \
1465      (_bz_Functor ## classname ## funcname(*this), a.unwrap());        \
1466}
1467
1468#define BZ_DECLARE_MEMBER_FUNCTION2_RET(classname, funcname, ret)         \
1469_BZ_MAKE_FUNCTOR2_RET(classname, funcname, ret)                           \
1470template<typename P_expr1, typename P_expr2>                              \
1471BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<           \
1472    _bz_Functor ## classname ## funcname,                                 \
1473    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1474    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1475    ret> >                                                                \
1476funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                        \
1477         const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b) const                  \
1478{                                                                         \
1479    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1480        BZ_BLITZ_SCOPE(_bz_FunctorExpr2)<                                 \
1481        _bz_Functor ## classname ## funcname,                             \
1482        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1483        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1484        ret> >                                                            \
1485      (_bz_Functor ## classname ## funcname(*this), a.unwrap(), b.unwrap()); \
1486}
1487
1488#define BZ_DECLARE_MEMBER_FUNCTION3_RET(classname, funcname, ret)         \
1489_BZ_MAKE_FUNCTOR3_RET(classname, funcname, ret)                           \
1490template<typename P_expr1, typename P_expr2, typename P_expr3>            \
1491BZ_BLITZ_SCOPE(_bz_ArrayExpr)<BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<           \
1492    _bz_Functor ## classname ## funcname,                                 \
1493    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,                 \
1494    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,                 \
1495    _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,                 \
1496    ret> >                                                                \
1497funcname(const BZ_BLITZ_SCOPE(ETBase)<P_expr1>& a,                        \
1498         const BZ_BLITZ_SCOPE(ETBase)<P_expr2>& b,                        \
1499         const BZ_BLITZ_SCOPE(ETBase)<P_expr3>& c) const                  \
1500{                                                                         \
1501    return BZ_BLITZ_SCOPE(_bz_ArrayExpr)<                                 \
1502        BZ_BLITZ_SCOPE(_bz_FunctorExpr3)<                                 \
1503        _bz_Functor ## classname ## funcname,                             \
1504        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr1>::T_expr,             \
1505        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr2>::T_expr,             \
1506        _bz_typename BZ_BLITZ_SCOPE(asExpr)<P_expr3>::T_expr,             \
1507        ret> >                                                            \
1508      (_bz_Functor ## classname ## funcname(*this),                     \
1509       a.unwrap(), b.unwrap(), c.unwrap());                             \
1510}
1511
1512
1513
1514#endif // BZ_ARRAY_FUNCTOREXPR_H
1515
Note: See TracBrowser for help on using the repository browser.