source: Sophya/trunk/Poubelle/DPC:FitsIOServer/Blitz/blitz/array/expr.h@ 658

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

no message

File size: 16.0 KB
Line 
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
76BZ_NAMESPACE(blitz)
77
78template<class T1, class T2>
79class _bz_ExprPair {
80public:
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
91protected:
92 T1 first_;
93 T2 second_;
94};
95
96template<class T1, class T2>
97inline _bz_ExprPair<T1,T2> makeExprPair(const T1& a, const T2& b)
98{
99 return _bz_ExprPair<T1,T2>(a,b);
100}
101
102template<class P_expr>
103class _bz_ArrayExpr
104#ifdef BZ_NEW_EXPRESSION_TEMPLATES
105 : public ETBase<_bz_ArrayExpr<P_expr> >
106#endif
107{
108
109public:
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
233protected:
234 _bz_ArrayExpr() { }
235
236 T_expr iter_;
237};
238
239struct 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
284template<class P_expr1, class P_expr2, class P_op>
285class _bz_ArrayExprOp {
286public:
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
422protected:
423 _bz_ArrayExprOp() { }
424
425 T_expr1 iter1_;
426 T_expr2 iter2_;
427};
428
429template<class P_expr, class P_op>
430class _bz_ArrayExprUnaryOp {
431public:
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
545protected:
546 _bz_ArrayExprUnaryOp() { }
547
548 T_expr iter_;
549};
550
551template<class P_numtype>
552class _bz_ArrayExprConstant {
553public:
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
638protected:
639 _bz_ArrayExprConstant() { }
640
641 T_numtype value_;
642};
643
644BZ_NAMESPACE_END
645
646#include <blitz/array/asexpr.h>
647
648#endif // BZ_ARRAYEXPR_H
649
Note: See TracBrowser for help on using the repository browser.