source: Sophya/trunk/SophyaExt/Blitz/blitz/array/expr.h@ 4024

Last change on this file since 4024 was 221, checked in by ansari, 26 years ago

Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99

File size: 15.9 KB
RevLine 
[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
73BZ_NAMESPACE(blitz)
74
75template<class T1, class T2>
76class _bz_ExprPair {
77public:
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
88protected:
89 T1 first_;
90 T2 second_;
91};
92
93template<class T1, class T2>
94inline _bz_ExprPair<T1,T2> makeExprPair(const T1& a, const T2& b)
95{
96 return _bz_ExprPair<T1,T2>(a,b);
97}
98
99template<class P_expr>
100class _bz_ArrayExpr
101#ifdef BZ_NEW_EXPRESSION_TEMPLATES
102 : public ETBase<_bz_ArrayExpr<P_expr> >
103#endif
104{
105
106public:
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
230protected:
231 _bz_ArrayExpr() { }
232
233 T_expr iter_;
234};
235
236struct 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
281template<class P_expr1, class P_expr2, class P_op>
282class _bz_ArrayExprOp {
283public:
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
419protected:
420 _bz_ArrayExprOp() { }
421
422 T_expr1 iter1_;
423 T_expr2 iter2_;
424};
425
426template<class P_expr, class P_op>
427class _bz_ArrayExprUnaryOp {
428public:
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
542protected:
543 _bz_ArrayExprUnaryOp() { }
544
545 T_expr iter_;
546};
547
548template<class P_numtype>
549class _bz_ArrayExprConstant {
550public:
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
635protected:
636 _bz_ArrayExprConstant() { }
637
638 T_numtype value_;
639};
640
641BZ_NAMESPACE_END
642
643#include <blitz/array/asexpr.h>
644
645#endif // BZ_ARRAYEXPR_H
646
Note: See TracBrowser for help on using the repository browser.