| [658] | 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 | 
 | 
|---|