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