| [221] | 1 | /***************************************************************************
 | 
|---|
 | 2 |  * blitz/arrayexpr.h     Array<T,N> expression templates
 | 
|---|
 | 3 |  *
 | 
|---|
 | 4 |  * $Id: expr.h,v 1.1.1.1 1999-04-09 17:59:03 ansari Exp $
 | 
|---|
 | 5 |  *
 | 
|---|
 | 6 |  * Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
 | 
|---|
 | 7 |  *
 | 
|---|
 | 8 |  * This program is free software; you can redistribute it and/or
 | 
|---|
 | 9 |  * modify it under the terms of the GNU General Public License
 | 
|---|
 | 10 |  * as published by the Free Software Foundation; either version 2
 | 
|---|
 | 11 |  * of the License, or (at your option) any later version.
 | 
|---|
 | 12 |  *
 | 
|---|
 | 13 |  * This program is distributed in the hope that it will be useful,
 | 
|---|
 | 14 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 15 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 16 |  * GNU General Public License for more details.
 | 
|---|
 | 17 |  *
 | 
|---|
 | 18 |  * Suggestions:          blitz-suggest@cybervision.com
 | 
|---|
 | 19 |  * Bugs:                 blitz-bugs@cybervision.com
 | 
|---|
 | 20 |  *
 | 
|---|
 | 21 |  * For more information, please see the Blitz++ Home Page:
 | 
|---|
 | 22 |  *    http://seurat.uwaterloo.ca/blitz/
 | 
|---|
 | 23 |  *
 | 
|---|
 | 24 |  ***************************************************************************
 | 
|---|
 | 25 |  * $Log: not supported by cvs2svn $
 | 
|---|
 | 26 |  * Revision 1.2  1998/03/14 00:04:47  tveldhui
 | 
|---|
 | 27 |  * 0.2-alpha-05
 | 
|---|
 | 28 |  *
 | 
|---|
 | 29 |  * Revision 1.1  1997/07/16 14:51:20  tveldhui
 | 
|---|
 | 30 |  * Update: Alpha release 0.2 (Arrays)
 | 
|---|
 | 31 |  *
 | 
|---|
 | 32 |  */
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #ifndef BZ_ARRAYEXPR_H
 | 
|---|
 | 35 | #define BZ_ARRAYEXPR_H
 | 
|---|
 | 36 | 
 | 
|---|
 | 37 | #ifndef BZ_ARRAY_H
 | 
|---|
 | 38 |  #error <blitz/array/expr.h> must be included via <blitz/array.h>
 | 
|---|
 | 39 | #endif
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 | #ifndef BZ_OPS_H
 | 
|---|
 | 42 |  #include <blitz/ops.h>
 | 
|---|
 | 43 | #endif
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | #ifndef BZ_PRETTYPRINT_H
 | 
|---|
 | 46 |  #include <blitz/prettyprint.h>
 | 
|---|
 | 47 | #endif
 | 
|---|
 | 48 | 
 | 
|---|
 | 49 | #ifndef BZ_SHAPECHECK_H
 | 
|---|
 | 50 |  #include <blitz/shapecheck.h>
 | 
|---|
 | 51 | #endif
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | #ifdef BZ_HAVE_NUMERIC_LIMITS
 | 
|---|
 | 54 | #ifndef BZ_NUMINQUIRE_H
 | 
|---|
 | 55 |  #include <blitz/numinquire.h>
 | 
|---|
 | 56 | #endif
 | 
|---|
 | 57 | #endif
 | 
|---|
 | 58 | 
 | 
|---|
 | 59 | /*
 | 
|---|
 | 60 |  * The array expression templates iterator interface is followed by
 | 
|---|
 | 61 |  * these classes:
 | 
|---|
 | 62 |  *
 | 
|---|
 | 63 |  * ArrayIterator              <blitz/arrayiter.h>
 | 
|---|
 | 64 |  * _bz_ArrayExpr              <blitz/arrayexpr.h>
 | 
|---|
 | 65 |  * _bz_ArrayExprOp                    "
 | 
|---|
 | 66 |  * _bz_ArrayExprUnaryOp               "
 | 
|---|
 | 67 |  * _bz_ArrayExprConstant              "
 | 
|---|
 | 68 |  * _bz_ArrayMap               <blitz/arraymap.h>
 | 
|---|
 | 69 |  * _bz_ArrayExprReduce        <blitz/arrayreduce.h>
 | 
|---|
 | 70 |  * IndexPlaceholder           <blitz/indexexpr.h>
 | 
|---|
 | 71 |  */
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | BZ_NAMESPACE(blitz)
 | 
|---|
 | 74 | 
 | 
|---|
 | 75 | template<class T1, class T2>
 | 
|---|
 | 76 | class _bz_ExprPair {
 | 
|---|
 | 77 | public:
 | 
|---|
 | 78 |     _bz_ExprPair(const T1& a, const T2& b)
 | 
|---|
 | 79 |         : first_(a), second_(b)
 | 
|---|
 | 80 |     { }
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 |     const T1& first() const
 | 
|---|
 | 83 |     { return first_; }
 | 
|---|
 | 84 | 
 | 
|---|
 | 85 |     const T2& second() const
 | 
|---|
 | 86 |     { return second_; }
 | 
|---|
 | 87 | 
 | 
|---|
 | 88 | protected:
 | 
|---|
 | 89 |     T1 first_;
 | 
|---|
 | 90 |     T2 second_;
 | 
|---|
 | 91 | };
 | 
|---|
 | 92 | 
 | 
|---|
 | 93 | template<class T1, class T2>
 | 
|---|
 | 94 | inline _bz_ExprPair<T1,T2> makeExprPair(const T1& a, const T2& b)
 | 
|---|
 | 95 | {
 | 
|---|
 | 96 |     return _bz_ExprPair<T1,T2>(a,b);
 | 
|---|
 | 97 | }
 | 
|---|
 | 98 | 
 | 
|---|
 | 99 | template<class P_expr>
 | 
|---|
 | 100 | class _bz_ArrayExpr 
 | 
|---|
 | 101 | #ifdef BZ_NEW_EXPRESSION_TEMPLATES
 | 
|---|
 | 102 |     : public ETBase<_bz_ArrayExpr<P_expr> >
 | 
|---|
 | 103 | #endif
 | 
|---|
 | 104 | {
 | 
|---|
 | 105 | 
 | 
|---|
 | 106 | public:
 | 
|---|
 | 107 |     typedef P_expr T_expr;
 | 
|---|
 | 108 |     typedef _bz_typename T_expr::T_numtype T_numtype;
 | 
|---|
 | 109 |     typedef T_expr T_ctorArg1;
 | 
|---|
 | 110 |     typedef int    T_ctorArg2;    // dummy
 | 
|---|
 | 111 | 
 | 
|---|
 | 112 |     enum { numArrayOperands = BZ_ENUM_CAST(P_expr::numArrayOperands),
 | 
|---|
 | 113 |         numIndexPlaceholders = BZ_ENUM_CAST(P_expr::numIndexPlaceholders),
 | 
|---|
 | 114 |         rank = BZ_ENUM_CAST(P_expr::rank) };
 | 
|---|
 | 115 | 
 | 
|---|
 | 116 |     _bz_ArrayExpr(const _bz_ArrayExpr<P_expr>& a)
 | 
|---|
 | 117 |         : iter_(a.iter_)
 | 
|---|
 | 118 |     { }
 | 
|---|
 | 119 | 
 | 
|---|
 | 120 |     _bz_ArrayExpr(T_expr a)
 | 
|---|
 | 121 |         : iter_(a)
 | 
|---|
 | 122 |     { }
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 |     _bz_ArrayExpr(_bz_typename T_expr::T_ctorArg1 a)
 | 
|---|
 | 125 |         : iter_(a)
 | 
|---|
 | 126 |     { }
 | 
|---|
 | 127 | 
 | 
|---|
 | 128 |     // This template is not possible because it masks the copy constructor,
 | 
|---|
 | 129 |     // wreaking havoc.
 | 
|---|
 | 130 | 
 | 
|---|
 | 131 | #if BZ_TEMPLATE_CTOR_DOESNT_CAUSE_HAVOC
 | 
|---|
 | 132 |     template<class T1>
 | 
|---|
 | 133 |     _bz_explicit _bz_ArrayExpr(T1 a)
 | 
|---|
 | 134 |        : iter_(a)
 | 
|---|
 | 135 |     { }
 | 
|---|
 | 136 | #endif
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 |     template<class T1, class T2>
 | 
|---|
 | 139 |     _bz_ArrayExpr(T1 a, T2 b)
 | 
|---|
 | 140 |         : iter_(a, b)
 | 
|---|
 | 141 |     { }
 | 
|---|
 | 142 | 
 | 
|---|
 | 143 |     template<class T1, class T2, class T3>
 | 
|---|
 | 144 |     _bz_ArrayExpr(T1 a, T2 b, T3 c)
 | 
|---|
 | 145 |         : iter_(a, b, c)
 | 
|---|
 | 146 |     { }
 | 
|---|
 | 147 | 
 | 
|---|
 | 148 |     template<class T1, class T2>
 | 
|---|
 | 149 |     _bz_ArrayExpr(_bz_ExprPair<T1,T2> pair)
 | 
|---|
 | 150 |         : iter_(pair.first(), pair.second())
 | 
|---|
 | 151 |     { }
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 |     T_numtype operator*()
 | 
|---|
 | 154 |     { return *iter_; }
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 | #ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
 | 
|---|
 | 157 |     template<int N_rank>
 | 
|---|
 | 158 |     T_numtype operator()(TinyVector<int, N_rank> i)
 | 
|---|
 | 159 |     { return iter_(i); }
 | 
|---|
 | 160 | #else
 | 
|---|
 | 161 |     template<int N_rank>
 | 
|---|
 | 162 |     T_numtype operator()(const TinyVector<int, N_rank>& i)
 | 
|---|
 | 163 |     { return iter_(i); }
 | 
|---|
 | 164 | #endif
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 |     int lbound(int rank)
 | 
|---|
 | 167 |     { return iter_.lbound(rank); }
 | 
|---|
 | 168 | 
 | 
|---|
 | 169 |     int ubound(int rank)
 | 
|---|
 | 170 |     { return iter_.ubound(rank); }
 | 
|---|
 | 171 | 
 | 
|---|
 | 172 |     void push(int position)
 | 
|---|
 | 173 |     { iter_.push(position); }
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 |     void pop(int position)
 | 
|---|
 | 176 |     { iter_.pop(position); }
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 |     void advance()
 | 
|---|
 | 179 |     { iter_.advance(); }
 | 
|---|
 | 180 | 
 | 
|---|
 | 181 |     void advance(int n)
 | 
|---|
 | 182 |     { iter_.advance(n); }
 | 
|---|
 | 183 | 
 | 
|---|
 | 184 |     void loadStride(int rank)
 | 
|---|
 | 185 |     { iter_.loadStride(rank); }
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 |     _bz_bool isUnitStride(int rank) const
 | 
|---|
 | 188 |     { return iter_.isUnitStride(rank); }
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 |     void advanceUnitStride()
 | 
|---|
 | 191 |     { iter_.advanceUnitStride(); }
 | 
|---|
 | 192 | 
 | 
|---|
 | 193 |     _bz_bool canCollapse(int outerLoopRank, int innerLoopRank) const
 | 
|---|
 | 194 |     { 
 | 
|---|
 | 195 |         // BZ_DEBUG_MESSAGE("_bz_ArrayExpr<>::canCollapse()");
 | 
|---|
 | 196 |         return iter_.canCollapse(outerLoopRank, innerLoopRank); 
 | 
|---|
 | 197 |     }
 | 
|---|
 | 198 | 
 | 
|---|
 | 199 |     T_numtype operator[](int i)
 | 
|---|
 | 200 |     { return iter_[i]; }
 | 
|---|
 | 201 | 
 | 
|---|
 | 202 |     T_numtype fastRead(int i)
 | 
|---|
 | 203 |     { return iter_.fastRead(i); }
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 |     int suggestStride(int rank) const
 | 
|---|
 | 206 |     { return iter_.suggestStride(rank); }
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |     _bz_bool isStride(int rank, int stride) const
 | 
|---|
 | 209 |     { return iter_.isStride(rank,stride); }
 | 
|---|
 | 210 | 
 | 
|---|
 | 211 |     void prettyPrint(string& str) const
 | 
|---|
 | 212 |     {
 | 
|---|
 | 213 |         prettyPrintFormat format(_bz_true);  // Terse formatting by default
 | 
|---|
 | 214 |         iter_.prettyPrint(str, format);
 | 
|---|
 | 215 |     }
 | 
|---|
 | 216 | 
 | 
|---|
 | 217 |     void prettyPrint(string& str, prettyPrintFormat& format) const
 | 
|---|
 | 218 |     { iter_.prettyPrint(str, format); }
 | 
|---|
 | 219 | 
 | 
|---|
 | 220 |     template<class T_shape>
 | 
|---|
 | 221 |     _bz_bool shapeCheck(const T_shape& shape)
 | 
|---|
 | 222 |     { return iter_.shapeCheck(shape); }
 | 
|---|
 | 223 | 
 | 
|---|
 | 224 |     template<int N_rank>
 | 
|---|
 | 225 |     void moveTo(const TinyVector<int,N_rank>& i)
 | 
|---|
 | 226 |     {
 | 
|---|
 | 227 |         iter_.moveTo(i);
 | 
|---|
 | 228 |     }
 | 
|---|
 | 229 | 
 | 
|---|
 | 230 | protected:
 | 
|---|
 | 231 |     _bz_ArrayExpr() { }
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 |     T_expr iter_;
 | 
|---|
 | 234 | };
 | 
|---|
 | 235 | 
 | 
|---|
 | 236 | struct bounds {
 | 
|---|
 | 237 |     static int compute_lbound(int rank, int lbound1, int lbound2)
 | 
|---|
 | 238 |     {
 | 
|---|
 | 239 |         // The value INT_MIN indicates that there are no arrays
 | 
|---|
 | 240 |         // in a subtree of the expression.  This logic returns
 | 
|---|
 | 241 |         // whichever lbound is available.  If there are two
 | 
|---|
 | 242 |         // conflicting lbound values, this is an error.
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |         if (lbound1 == lbound2)
 | 
|---|
 | 245 |             return lbound1;
 | 
|---|
 | 246 |         else if (lbound1 == INT_MIN)
 | 
|---|
 | 247 |             return lbound2;
 | 
|---|
 | 248 |         else if (lbound2 == INT_MIN)
 | 
|---|
 | 249 |             return lbound1;
 | 
|---|
 | 250 | 
 | 
|---|
 | 251 |         BZ_DEBUG_MESSAGE("Two array operands have different"
 | 
|---|
 | 252 |             << endl << "lower bounds: in rank " << rank << ", the bounds are "
 | 
|---|
 | 253 |             << lbound1 << " and " << lbound2 << endl);
 | 
|---|
 | 254 |         BZ_PRE_FAIL;
 | 
|---|
 | 255 |         return 0;
 | 
|---|
 | 256 |     }
 | 
|---|
 | 257 | 
 | 
|---|
 | 258 |     static int compute_ubound(int rank, int ubound1, int ubound2)
 | 
|---|
 | 259 |     {
 | 
|---|
 | 260 |         // The value INT_MAX indicates that there are no arrays
 | 
|---|
 | 261 |         // in a subtree of the expression.  This logic returns
 | 
|---|
 | 262 |         // whichever ubound is available.  If there are two
 | 
|---|
 | 263 |         // conflicting ubound values, this is an error.
 | 
|---|
 | 264 | 
 | 
|---|
 | 265 |         if (ubound1 == ubound2)
 | 
|---|
 | 266 |             return ubound1;
 | 
|---|
 | 267 |         else if (ubound1 == INT_MAX)
 | 
|---|
 | 268 |             return ubound2;
 | 
|---|
 | 269 |         else if (ubound2 == INT_MAX)
 | 
|---|
 | 270 |             return ubound1;
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 |         BZ_DEBUG_MESSAGE("Two array operands have different"
 | 
|---|
 | 273 |             << endl << "upper bounds: in rank " << rank << ", the bounds are "
 | 
|---|
 | 274 |             << ubound1 << " and " << ubound2 << endl);
 | 
|---|
 | 275 |         BZ_PRE_FAIL;
 | 
|---|
 | 276 |         return 0;
 | 
|---|
 | 277 |     }
 | 
|---|
 | 278 | 
 | 
|---|
 | 279 | };
 | 
|---|
 | 280 | 
 | 
|---|
 | 281 | template<class P_expr1, class P_expr2, class P_op>
 | 
|---|
 | 282 | class _bz_ArrayExprOp {
 | 
|---|
 | 283 | public:
 | 
|---|
 | 284 |     typedef P_expr1 T_expr1;
 | 
|---|
 | 285 |     typedef P_expr2 T_expr2;
 | 
|---|
 | 286 |     typedef _bz_typename T_expr1::T_numtype T_numtype1;
 | 
|---|
 | 287 |     typedef _bz_typename T_expr2::T_numtype T_numtype2;
 | 
|---|
 | 288 |     typedef _bz_typename P_op::T_numtype T_numtype;
 | 
|---|
 | 289 |     typedef P_op T_op;
 | 
|---|
 | 290 |     typedef T_expr1 T_ctorArg1;
 | 
|---|
 | 291 |     typedef T_expr2 T_ctorArg2;
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 |     enum { numArrayOperands = BZ_ENUM_CAST(P_expr1::numArrayOperands)
 | 
|---|
 | 294 |                             + BZ_ENUM_CAST(P_expr2::numArrayOperands),
 | 
|---|
 | 295 |            numIndexPlaceholders = BZ_ENUM_CAST(P_expr1::numIndexPlaceholders)
 | 
|---|
 | 296 |                             + BZ_ENUM_CAST(P_expr2::numIndexPlaceholders),
 | 
|---|
 | 297 |            rank = (BZ_ENUM_CAST(P_expr1::rank) > BZ_ENUM_CAST(P_expr2::rank)) 
 | 
|---|
 | 298 |                 ? BZ_ENUM_CAST(P_expr1::rank) : BZ_ENUM_CAST(P_expr2::rank)
 | 
|---|
 | 299 |     };
 | 
|---|
 | 300 | 
 | 
|---|
 | 301 |     _bz_ArrayExprOp(const _bz_ArrayExprOp<P_expr1, P_expr2, P_op>& a)
 | 
|---|
 | 302 |         : iter1_(a.iter1_), iter2_(a.iter2_)
 | 
|---|
 | 303 |     { }
 | 
|---|
 | 304 | 
 | 
|---|
 | 305 |     template<class T1, class T2>
 | 
|---|
 | 306 |     _bz_ArrayExprOp(T1 a, T2 b)
 | 
|---|
 | 307 |         : iter1_(a), iter2_(b)
 | 
|---|
 | 308 |     { }
 | 
|---|
 | 309 | 
 | 
|---|
 | 310 | //    _bz_ArrayExprOp(T_expr1 a, T_expr2 b)
 | 
|---|
 | 311 | //       : iter1_(a), iter2_(b)
 | 
|---|
 | 312 | //    { }
 | 
|---|
 | 313 | 
 | 
|---|
 | 314 |     T_numtype operator*()
 | 
|---|
 | 315 |     { return T_op::apply(*iter1_, *iter2_); }
 | 
|---|
 | 316 | 
 | 
|---|
 | 317 | #ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
 | 
|---|
 | 318 |     template<int N_rank>
 | 
|---|
 | 319 |     T_numtype operator()(TinyVector<int, N_rank> i)
 | 
|---|
 | 320 |     { return T_op::apply(iter1_(i), iter2_(i)); }
 | 
|---|
 | 321 | #else
 | 
|---|
 | 322 |     template<int N_rank>
 | 
|---|
 | 323 |     T_numtype operator()(const TinyVector<int, N_rank>& i)
 | 
|---|
 | 324 |     { return T_op::apply(iter1_(i), iter2_(i)); }
 | 
|---|
 | 325 | #endif
 | 
|---|
 | 326 | 
 | 
|---|
 | 327 |     int lbound(int rank)
 | 
|---|
 | 328 |     { 
 | 
|---|
 | 329 |         return bounds::compute_lbound(rank, iter1_.lbound(rank),
 | 
|---|
 | 330 |             iter2_.lbound(rank));
 | 
|---|
 | 331 |     }
 | 
|---|
 | 332 | 
 | 
|---|
 | 333 |     int ubound(int rank)
 | 
|---|
 | 334 |     {
 | 
|---|
 | 335 |         return bounds::compute_ubound(rank, iter1_.ubound(rank),
 | 
|---|
 | 336 |             iter2_.ubound(rank));
 | 
|---|
 | 337 |     }
 | 
|---|
 | 338 | 
 | 
|---|
 | 339 |     void push(int position)
 | 
|---|
 | 340 |     { 
 | 
|---|
 | 341 |         iter1_.push(position); 
 | 
|---|
 | 342 |         iter2_.push(position);
 | 
|---|
 | 343 |     }
 | 
|---|
 | 344 | 
 | 
|---|
 | 345 |     void pop(int position)
 | 
|---|
 | 346 |     { 
 | 
|---|
 | 347 |         iter1_.pop(position); 
 | 
|---|
 | 348 |         iter2_.pop(position);
 | 
|---|
 | 349 |     }
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 |     void advance()
 | 
|---|
 | 352 |     { 
 | 
|---|
 | 353 |         iter1_.advance(); 
 | 
|---|
 | 354 |         iter2_.advance();
 | 
|---|
 | 355 |     }
 | 
|---|
 | 356 | 
 | 
|---|
 | 357 |     void advance(int n)
 | 
|---|
 | 358 |     {
 | 
|---|
 | 359 |         iter1_.advance(n);
 | 
|---|
 | 360 |         iter2_.advance(n);
 | 
|---|
 | 361 |     }
 | 
|---|
 | 362 | 
 | 
|---|
 | 363 |     void loadStride(int rank)
 | 
|---|
 | 364 |     { 
 | 
|---|
 | 365 |         iter1_.loadStride(rank); 
 | 
|---|
 | 366 |         iter2_.loadStride(rank);
 | 
|---|
 | 367 |     }
 | 
|---|
 | 368 |     
 | 
|---|
 | 369 |     _bz_bool isUnitStride(int rank) const
 | 
|---|
 | 370 |     { return iter1_.isUnitStride(rank) && iter2_.isUnitStride(rank); }
 | 
|---|
 | 371 | 
 | 
|---|
 | 372 |     void advanceUnitStride()
 | 
|---|
 | 373 |     { 
 | 
|---|
 | 374 |         iter1_.advanceUnitStride(); 
 | 
|---|
 | 375 |         iter2_.advanceUnitStride();
 | 
|---|
 | 376 |     }
 | 
|---|
 | 377 | 
 | 
|---|
 | 378 |     _bz_bool canCollapse(int outerLoopRank, int innerLoopRank) const
 | 
|---|
 | 379 |     { 
 | 
|---|
 | 380 |         // BZ_DEBUG_MESSAGE("_bz_ArrayExprOp<>::canCollapse");
 | 
|---|
 | 381 |         return iter1_.canCollapse(outerLoopRank, innerLoopRank)
 | 
|---|
 | 382 |             && iter2_.canCollapse(outerLoopRank, innerLoopRank);
 | 
|---|
 | 383 |     } 
 | 
|---|
 | 384 | 
 | 
|---|
 | 385 |     T_numtype operator[](int i)
 | 
|---|
 | 386 |     { return T_op::apply(iter1_[i], iter2_[i]); }
 | 
|---|
 | 387 | 
 | 
|---|
 | 388 |     T_numtype fastRead(int i)
 | 
|---|
 | 389 |     { return T_op::apply(iter1_.fastRead(i), iter2_.fastRead(i)); }
 | 
|---|
 | 390 | 
 | 
|---|
 | 391 |     int suggestStride(int rank) const
 | 
|---|
 | 392 |     {
 | 
|---|
 | 393 |         int stride1 = iter1_.suggestStride(rank);
 | 
|---|
 | 394 |         int stride2 = iter2_.suggestStride(rank);
 | 
|---|
 | 395 |         return (stride1 > stride2) ? stride1 : stride2;
 | 
|---|
 | 396 |     }
 | 
|---|
 | 397 | 
 | 
|---|
 | 398 |     _bz_bool isStride(int rank, int stride) const
 | 
|---|
 | 399 |     {
 | 
|---|
 | 400 |         return iter1_.isStride(rank,stride) && iter2_.isStride(rank,stride);
 | 
|---|
 | 401 |     }
 | 
|---|
 | 402 | 
 | 
|---|
 | 403 |     template<int N_rank>
 | 
|---|
 | 404 |     void moveTo(const TinyVector<int,N_rank>& i)
 | 
|---|
 | 405 |     {
 | 
|---|
 | 406 |         iter1_.moveTo(i);
 | 
|---|
 | 407 |         iter2_.moveTo(i);
 | 
|---|
 | 408 |     }
 | 
|---|
 | 409 | 
 | 
|---|
 | 410 |     void prettyPrint(string& str, prettyPrintFormat& format) const
 | 
|---|
 | 411 |     {
 | 
|---|
 | 412 |         T_op::prettyPrint(str, format, iter1_, iter2_);
 | 
|---|
 | 413 |     }
 | 
|---|
 | 414 | 
 | 
|---|
 | 415 |     template<class T_shape>
 | 
|---|
 | 416 |     _bz_bool shapeCheck(const T_shape& shape)
 | 
|---|
 | 417 |     { return iter1_.shapeCheck(shape) && iter2_.shapeCheck(shape); }
 | 
|---|
 | 418 | 
 | 
|---|
 | 419 | protected:
 | 
|---|
 | 420 |     _bz_ArrayExprOp() { }
 | 
|---|
 | 421 | 
 | 
|---|
 | 422 |     T_expr1 iter1_;
 | 
|---|
 | 423 |     T_expr2 iter2_; 
 | 
|---|
 | 424 | };
 | 
|---|
 | 425 | 
 | 
|---|
 | 426 | template<class P_expr, class P_op>
 | 
|---|
 | 427 | class _bz_ArrayExprUnaryOp {
 | 
|---|
 | 428 | public:
 | 
|---|
 | 429 |     typedef P_expr T_expr;
 | 
|---|
 | 430 |     typedef _bz_typename P_expr::T_numtype T_numtype1;
 | 
|---|
 | 431 |     typedef _bz_typename P_op::T_numtype T_numtype;
 | 
|---|
 | 432 |     typedef P_op T_op;
 | 
|---|
 | 433 |     typedef T_expr T_ctorArg1;
 | 
|---|
 | 434 |     typedef int    T_ctorArg2;    // dummy
 | 
|---|
 | 435 | 
 | 
|---|
 | 436 |     enum { numArrayOperands = BZ_ENUM_CAST(T_expr::numArrayOperands),
 | 
|---|
 | 437 |         numIndexPlaceholders = BZ_ENUM_CAST(T_expr::numIndexPlaceholders),
 | 
|---|
 | 438 |         rank = BZ_ENUM_CAST(T_expr::rank) };
 | 
|---|
 | 439 | 
 | 
|---|
 | 440 |     _bz_ArrayExprUnaryOp(const _bz_ArrayExprUnaryOp<T_expr, P_op>& a)
 | 
|---|
 | 441 |         : iter_(a.iter_)
 | 
|---|
 | 442 |     { }
 | 
|---|
 | 443 | 
 | 
|---|
 | 444 |     _bz_ArrayExprUnaryOp(T_expr a)
 | 
|---|
 | 445 |         : iter_(a)
 | 
|---|
 | 446 |     { }
 | 
|---|
 | 447 | 
 | 
|---|
 | 448 |     _bz_ArrayExprUnaryOp(_bz_typename T_expr::T_ctorArg1 a)
 | 
|---|
 | 449 |         : iter_(a)
 | 
|---|
 | 450 |     { }
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 | #if BZ_TEMPLATE_CTOR_DOESNT_CAUSE_HAVOC
 | 
|---|
 | 453 |     template<class T1>
 | 
|---|
 | 454 |     _bz_explicit _bz_ArrayExprUnaryOp(T1 a)
 | 
|---|
 | 455 |         : iter_(a)
 | 
|---|
 | 456 |     { }
 | 
|---|
 | 457 | #endif
 | 
|---|
 | 458 | 
 | 
|---|
 | 459 |     int lbound(int rank)
 | 
|---|
 | 460 |     { return iter_.lbound(rank); }
 | 
|---|
 | 461 | 
 | 
|---|
 | 462 |     int ubound(int rank)
 | 
|---|
 | 463 |     { return iter_.ubound(rank); }
 | 
|---|
 | 464 | 
 | 
|---|
 | 465 |     T_numtype operator*()
 | 
|---|
 | 466 |     { return T_op::apply(*iter_); }
 | 
|---|
 | 467 | 
 | 
|---|
 | 468 | #ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
 | 
|---|
 | 469 |     template<int N_rank>
 | 
|---|
 | 470 |     T_numtype operator()(TinyVector<int, N_rank> i)
 | 
|---|
 | 471 |     { return T_op::apply(iter_(i)); }
 | 
|---|
 | 472 | #else
 | 
|---|
 | 473 |     template<int N_rank>
 | 
|---|
 | 474 |     T_numtype operator()(const TinyVector<int, N_rank>& i)
 | 
|---|
 | 475 |     { return T_op::apply(iter_(i)); }
 | 
|---|
 | 476 | #endif
 | 
|---|
 | 477 | 
 | 
|---|
 | 478 |     void push(int position)
 | 
|---|
 | 479 |     {
 | 
|---|
 | 480 |         iter_.push(position);
 | 
|---|
 | 481 |     }
 | 
|---|
 | 482 | 
 | 
|---|
 | 483 |     void pop(int position)
 | 
|---|
 | 484 |     {
 | 
|---|
 | 485 |         iter_.pop(position);
 | 
|---|
 | 486 |     }
 | 
|---|
 | 487 | 
 | 
|---|
 | 488 |     void advance()
 | 
|---|
 | 489 |     {
 | 
|---|
 | 490 |         iter_.advance();
 | 
|---|
 | 491 |     }
 | 
|---|
 | 492 | 
 | 
|---|
 | 493 |     void advance(int n)
 | 
|---|
 | 494 |     {
 | 
|---|
 | 495 |         iter_.advance(n);
 | 
|---|
 | 496 |     }
 | 
|---|
 | 497 | 
 | 
|---|
 | 498 |     void loadStride(int rank)
 | 
|---|
 | 499 |     {
 | 
|---|
 | 500 |         iter_.loadStride(rank);
 | 
|---|
 | 501 |     }
 | 
|---|
 | 502 | 
 | 
|---|
 | 503 |     _bz_bool isUnitStride(int rank) const
 | 
|---|
 | 504 |     { return iter_.isUnitStride(rank); }
 | 
|---|
 | 505 | 
 | 
|---|
 | 506 |     void advanceUnitStride()
 | 
|---|
 | 507 |     {
 | 
|---|
 | 508 |         iter_.advanceUnitStride();
 | 
|---|
 | 509 |     }
 | 
|---|
 | 510 | 
 | 
|---|
 | 511 |     template<int N_rank>
 | 
|---|
 | 512 |     void moveTo(const TinyVector<int,N_rank>& i)
 | 
|---|
 | 513 |     {
 | 
|---|
 | 514 |         iter_.moveTo(i);
 | 
|---|
 | 515 |     }
 | 
|---|
 | 516 | 
 | 
|---|
 | 517 |     _bz_bool canCollapse(int outerLoopRank, int innerLoopRank) const
 | 
|---|
 | 518 |     { 
 | 
|---|
 | 519 |         // BZ_DEBUG_MESSAGE("_bz_ArrayExprUnaryOp<>::canCollapse");
 | 
|---|
 | 520 |         return iter_.canCollapse(outerLoopRank, innerLoopRank); 
 | 
|---|
 | 521 |     }
 | 
|---|
 | 522 | 
 | 
|---|
 | 523 |     T_numtype operator[](int i)
 | 
|---|
 | 524 |     { return T_op::apply(iter_[i]); }
 | 
|---|
 | 525 | 
 | 
|---|
 | 526 |     T_numtype fastRead(int i)
 | 
|---|
 | 527 |     { return T_op::apply(iter_.fastRead(i)); }
 | 
|---|
 | 528 | 
 | 
|---|
 | 529 |     int suggestStride(int rank) const
 | 
|---|
 | 530 |     { return iter_.suggestStride(rank); }
 | 
|---|
 | 531 | 
 | 
|---|
 | 532 |     _bz_bool isStride(int rank, int stride) const
 | 
|---|
 | 533 |     { return iter_.isStride(rank,stride); }
 | 
|---|
 | 534 | 
 | 
|---|
 | 535 |     void prettyPrint(string& str, prettyPrintFormat& format) const
 | 
|---|
 | 536 |     { T_op::prettyPrint(str, format, iter_); }
 | 
|---|
 | 537 | 
 | 
|---|
 | 538 |     template<class T_shape>
 | 
|---|
 | 539 |     _bz_bool shapeCheck(const T_shape& shape)
 | 
|---|
 | 540 |     { return iter_.shapeCheck(shape); }
 | 
|---|
 | 541 | 
 | 
|---|
 | 542 | protected:
 | 
|---|
 | 543 |     _bz_ArrayExprUnaryOp() { }
 | 
|---|
 | 544 | 
 | 
|---|
 | 545 |     T_expr iter_;
 | 
|---|
 | 546 | };
 | 
|---|
 | 547 | 
 | 
|---|
 | 548 | template<class P_numtype>
 | 
|---|
 | 549 | class _bz_ArrayExprConstant {
 | 
|---|
 | 550 | public:
 | 
|---|
 | 551 |     typedef P_numtype T_numtype;
 | 
|---|
 | 552 |     typedef T_numtype T_ctorArg1;
 | 
|---|
 | 553 |     typedef int       T_ctorArg2;    // dummy
 | 
|---|
 | 554 | 
 | 
|---|
 | 555 |     enum { numArrayOperands = 0, numIndexPlaceholders = 0, rank = 0 };
 | 
|---|
 | 556 | 
 | 
|---|
 | 557 |     _bz_ArrayExprConstant(const _bz_ArrayExprConstant<T_numtype>& a)
 | 
|---|
 | 558 |         : value_(a.value_)
 | 
|---|
 | 559 |     { }
 | 
|---|
 | 560 | 
 | 
|---|
 | 561 |     _bz_ArrayExprConstant(T_numtype value)
 | 
|---|
 | 562 |         : value_(BZ_NO_PROPAGATE(value))
 | 
|---|
 | 563 |     { 
 | 
|---|
 | 564 |     }
 | 
|---|
 | 565 | 
 | 
|---|
 | 566 |     // tiny() and huge() return the smallest and largest representable
 | 
|---|
 | 567 |     // integer values.  See <blitz/numinquire.h>
 | 
|---|
 | 568 |     // NEEDS_WORK: use tiny(int()) once numeric_limits<T> available on
 | 
|---|
 | 569 |     // all platforms
 | 
|---|
 | 570 |     int lbound(int)
 | 
|---|
 | 571 |     { return INT_MIN; }
 | 
|---|
 | 572 | 
 | 
|---|
 | 573 |     int ubound(int)
 | 
|---|
 | 574 |     { return INT_MAX; }
 | 
|---|
 | 575 |     // NEEDS_WORK: use huge(int()) once numeric_limits<T> available on
 | 
|---|
 | 576 |     // all platforms
 | 
|---|
 | 577 | 
 | 
|---|
 | 578 |     T_numtype operator*()
 | 
|---|
 | 579 |     { return value_; }
 | 
|---|
 | 580 | 
 | 
|---|
 | 581 | #ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE
 | 
|---|
 | 582 |     template<int N_rank>
 | 
|---|
 | 583 |     T_numtype operator()(TinyVector<int,N_rank>)
 | 
|---|
 | 584 |     { return value_; }
 | 
|---|
 | 585 | #else
 | 
|---|
 | 586 |     template<int N_rank>
 | 
|---|
 | 587 |     T_numtype operator()(const TinyVector<int,N_rank>&)
 | 
|---|
 | 588 |     { return value_; }
 | 
|---|
 | 589 | #endif
 | 
|---|
 | 590 | 
 | 
|---|
 | 591 |     void push(int) { }
 | 
|---|
 | 592 |     void pop(int) { }
 | 
|---|
 | 593 |     void advance() { }
 | 
|---|
 | 594 |     void advance(int) { }
 | 
|---|
 | 595 |     void loadStride(int) { }
 | 
|---|
 | 596 | 
 | 
|---|
 | 597 |     _bz_bool isUnitStride(int rank) const
 | 
|---|
 | 598 |     { return _bz_true; }
 | 
|---|
 | 599 | 
 | 
|---|
 | 600 |     void advanceUnitStride()
 | 
|---|
 | 601 |     { }
 | 
|---|
 | 602 | 
 | 
|---|
 | 603 |     _bz_bool canCollapse(int,int) const 
 | 
|---|
 | 604 |     { return _bz_true; }
 | 
|---|
 | 605 | 
 | 
|---|
 | 606 |     T_numtype operator[](int)
 | 
|---|
 | 607 |     { return value_; }
 | 
|---|
 | 608 | 
 | 
|---|
 | 609 |     T_numtype fastRead(int)
 | 
|---|
 | 610 |     { return value_; }
 | 
|---|
 | 611 | 
 | 
|---|
 | 612 |     int suggestStride(int) const
 | 
|---|
 | 613 |     { return 1; }
 | 
|---|
 | 614 | 
 | 
|---|
 | 615 |     _bz_bool isStride(int,int) const
 | 
|---|
 | 616 |     { return _bz_true; }
 | 
|---|
 | 617 | 
 | 
|---|
 | 618 |     template<int N_rank>
 | 
|---|
 | 619 |     void moveTo(const TinyVector<int,N_rank>& i)
 | 
|---|
 | 620 |     {
 | 
|---|
 | 621 |     }
 | 
|---|
 | 622 | 
 | 
|---|
 | 623 |     void prettyPrint(string& str, prettyPrintFormat& format) const
 | 
|---|
 | 624 |     {
 | 
|---|
 | 625 |         if (format.tersePrintingSelected())
 | 
|---|
 | 626 |             str += format.nextScalarOperandSymbol();
 | 
|---|
 | 627 |         else
 | 
|---|
 | 628 |             str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_numtype);
 | 
|---|
 | 629 |     }
 | 
|---|
 | 630 | 
 | 
|---|
 | 631 |     template<class T_shape>
 | 
|---|
 | 632 |     _bz_bool shapeCheck(const T_shape&)
 | 
|---|
 | 633 |     { return _bz_true; }
 | 
|---|
 | 634 | 
 | 
|---|
 | 635 | protected:
 | 
|---|
 | 636 |     _bz_ArrayExprConstant() { }
 | 
|---|
 | 637 | 
 | 
|---|
 | 638 |     T_numtype value_;
 | 
|---|
 | 639 | };
 | 
|---|
 | 640 | 
 | 
|---|
 | 641 | BZ_NAMESPACE_END
 | 
|---|
 | 642 | 
 | 
|---|
 | 643 | #include <blitz/array/asexpr.h>
 | 
|---|
 | 644 | 
 | 
|---|
 | 645 | #endif // BZ_ARRAYEXPR_H
 | 
|---|
 | 646 | 
 | 
|---|