1 | /***************************************************************************
|
---|
2 | * blitz/array/reduce.h Reductions of an array (or array expression) in a
|
---|
3 | * single rank: sum, mean, min, minIndex, max, maxIndex,
|
---|
4 | * product, count, any, all
|
---|
5 | *
|
---|
6 | * $Id: reduce.h,v 1.1.1.1 1999-11-26 16:37:07 ansari Exp $
|
---|
7 | *
|
---|
8 | * Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
|
---|
9 | *
|
---|
10 | * This program is free software; you can redistribute it and/or
|
---|
11 | * modify it under the terms of the GNU General Public License
|
---|
12 | * as published by the Free Software Foundation; either version 2
|
---|
13 | * of the License, or (at your option) any later version.
|
---|
14 | *
|
---|
15 | * This program is distributed in the hope that it will be useful,
|
---|
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
18 | * GNU General Public License for more details.
|
---|
19 | *
|
---|
20 | * Suggestions: blitz-suggest@cybervision.com
|
---|
21 | * Bugs: blitz-bugs@cybervision.com
|
---|
22 | *
|
---|
23 | * For more information, please see the Blitz++ Home Page:
|
---|
24 | * http://seurat.uwaterloo.ca/blitz/
|
---|
25 | *
|
---|
26 | ***************************************************************************
|
---|
27 | * $Log: not supported by cvs2svn $
|
---|
28 | * Revision 1.1.1.1 1999/04/09 17:59:04 ansari
|
---|
29 | * Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99
|
---|
30 | *
|
---|
31 | * Revision 1.2 1998/03/14 00:04:47 tveldhui
|
---|
32 | * 0.2-alpha-05
|
---|
33 | *
|
---|
34 | * Revision 1.1 1997/07/16 14:51:20 tveldhui
|
---|
35 | * Update: Alpha release 0.2 (Arrays)
|
---|
36 | *
|
---|
37 | */
|
---|
38 |
|
---|
39 | #ifndef BZ_ARRAYREDUCE_H
|
---|
40 | #define BZ_ARRAYREDUCE_H
|
---|
41 |
|
---|
42 | #ifndef BZ_ARRAYEXPR_H
|
---|
43 | #error <blitz/array/reduce.h> must be included after <blitz/array/expr.h>
|
---|
44 | #endif
|
---|
45 |
|
---|
46 | #ifndef BZ_REDUCE_H
|
---|
47 | #include <blitz/reduce.h>
|
---|
48 | #endif
|
---|
49 |
|
---|
50 | BZ_NAMESPACE(blitz)
|
---|
51 |
|
---|
52 | template<class T_expr, int N_index, class T_reduction>
|
---|
53 | class _bz_ArrayExprReduce {
|
---|
54 |
|
---|
55 | public:
|
---|
56 | typedef _bz_typename T_reduction::T_numtype T_numtype;
|
---|
57 | typedef T_expr T_ctorArg1;
|
---|
58 | typedef T_reduction T_ctorArg2;
|
---|
59 |
|
---|
60 | enum { numArrayOperands = BZ_ENUM_CAST(T_expr::numArrayOperands),
|
---|
61 | numIndexPlaceholders = BZ_ENUM_CAST(T_expr::numIndexPlaceholders) + 1,
|
---|
62 | rank = BZ_ENUM_CAST(T_expr::rank) - 1 };
|
---|
63 |
|
---|
64 | _bz_ArrayExprReduce(const _bz_ArrayExprReduce<T_expr,N_index,T_reduction>&
|
---|
65 | reduce)
|
---|
66 | : reduce_(reduce.reduce_), iter_(reduce.iter_)
|
---|
67 | {
|
---|
68 | }
|
---|
69 |
|
---|
70 | _bz_ArrayExprReduce(T_expr expr)
|
---|
71 | : iter_(expr)
|
---|
72 | { }
|
---|
73 |
|
---|
74 | _bz_ArrayExprReduce(T_expr expr, T_reduction reduce)
|
---|
75 | : iter_(expr), reduce_(reduce)
|
---|
76 | { }
|
---|
77 |
|
---|
78 | int lbound(int rank)
|
---|
79 | { return iter_.lbound(rank); }
|
---|
80 |
|
---|
81 | int ubound(int rank)
|
---|
82 | { return iter_.ubound(rank); }
|
---|
83 |
|
---|
84 | template<int N_destRank>
|
---|
85 | T_numtype operator()(const TinyVector<int, N_destRank>& destIndex)
|
---|
86 | {
|
---|
87 | BZPRECHECK(N_destRank == N_index,
|
---|
88 | "Array reduction performed over rank " << N_index
|
---|
89 | << " to produce a rank " << N_destRank << " expression." << endl
|
---|
90 | << "You must reduce over rank " << N_destRank << " instead.");
|
---|
91 |
|
---|
92 | TinyVector<int, N_destRank + 1> index;
|
---|
93 |
|
---|
94 | // This metaprogram copies elements 0..N-1 of destIndex into index
|
---|
95 | _bz_meta_vecAssign<N_index, 0>::assign(index, destIndex,
|
---|
96 | _bz_update<int,int>());
|
---|
97 |
|
---|
98 | int lbound = iter_.lbound(N_index);
|
---|
99 | int ubound = iter_.ubound(N_index);
|
---|
100 |
|
---|
101 | // NEEDS_WORK: replace with tiny(int()) and huge(int()) once
|
---|
102 | // <limits> widely available
|
---|
103 | BZPRECHECK((lbound != INT_MIN) && (ubound != INT_MAX),
|
---|
104 | "Array reduction performed over rank " << N_index
|
---|
105 | << " is unbounded." << endl
|
---|
106 | << "There must be an array object in the expression being reduced"
|
---|
107 | << endl << "which provides a bound in rank " << N_index << ".");
|
---|
108 |
|
---|
109 | reduce_.reset();
|
---|
110 |
|
---|
111 | for (index[N_index] = iter_.lbound(N_index);
|
---|
112 | index[N_index] <= ubound; ++index[N_index])
|
---|
113 | {
|
---|
114 | if (!reduce_(iter_(index), index[N_index]))
|
---|
115 | break;
|
---|
116 | }
|
---|
117 |
|
---|
118 | return reduce_.result(ubound-lbound+1);
|
---|
119 | }
|
---|
120 |
|
---|
121 | // If you have a precondition failure on this routine, it means
|
---|
122 | // you are trying to use stack iteration mode on an expression
|
---|
123 | // which contains an index placeholder. You must use index
|
---|
124 | // iteration mode instead.
|
---|
125 | int operator*()
|
---|
126 | {
|
---|
127 | BZPRECONDITION(0);
|
---|
128 | return 0;
|
---|
129 | }
|
---|
130 |
|
---|
131 | // See operator*() note
|
---|
132 | void push(int)
|
---|
133 | {
|
---|
134 | BZPRECONDITION(0);
|
---|
135 | }
|
---|
136 |
|
---|
137 | // See operator*() note
|
---|
138 | void pop(int)
|
---|
139 | {
|
---|
140 | BZPRECONDITION(0);
|
---|
141 | }
|
---|
142 |
|
---|
143 | // See operator*() note
|
---|
144 | void advance()
|
---|
145 | {
|
---|
146 | BZPRECONDITION(0);
|
---|
147 | }
|
---|
148 |
|
---|
149 | // See operator*() note
|
---|
150 | void advance(int)
|
---|
151 | {
|
---|
152 | BZPRECONDITION(0);
|
---|
153 | }
|
---|
154 |
|
---|
155 | // See operator*() note
|
---|
156 | void loadStride(int)
|
---|
157 | {
|
---|
158 | BZPRECONDITION(0);
|
---|
159 | }
|
---|
160 |
|
---|
161 | _bz_bool isUnitStride(int rank) const
|
---|
162 | {
|
---|
163 | BZPRECONDITION(0);
|
---|
164 | return false;
|
---|
165 | }
|
---|
166 |
|
---|
167 | void advanceUnitStride()
|
---|
168 | {
|
---|
169 | BZPRECONDITION(0);
|
---|
170 | }
|
---|
171 |
|
---|
172 | _bz_bool canCollapse(int,int) const
|
---|
173 | { BZPRECONDITION(0); return _bz_false; }
|
---|
174 |
|
---|
175 | T_numtype operator[](int)
|
---|
176 | {
|
---|
177 | BZPRECONDITION(0);
|
---|
178 | return T_numtype();
|
---|
179 | }
|
---|
180 |
|
---|
181 | T_numtype fastRead(int)
|
---|
182 | {
|
---|
183 | BZPRECONDITION(0);
|
---|
184 | return T_numtype();
|
---|
185 | }
|
---|
186 |
|
---|
187 | int suggestStride(int) const
|
---|
188 | {
|
---|
189 | BZPRECONDITION(0);
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 |
|
---|
193 | _bz_bool isStride(int,int) const
|
---|
194 | {
|
---|
195 | BZPRECONDITION(0);
|
---|
196 | return _bz_true;
|
---|
197 | }
|
---|
198 |
|
---|
199 | template<int N_rank>
|
---|
200 | void moveTo(const TinyVector<int,N_rank>& i)
|
---|
201 | {
|
---|
202 | BZPRECONDITION(0);
|
---|
203 | return;
|
---|
204 | }
|
---|
205 |
|
---|
206 | void prettyPrint(std::string& str, prettyPrintFormat& format) const
|
---|
207 | {
|
---|
208 | // NEEDS_WORK-- do real formatting for reductions
|
---|
209 | str += "reduce[NEEDS_WORK](";
|
---|
210 | iter_.prettyPrint(str,format);
|
---|
211 | str += ")";
|
---|
212 | }
|
---|
213 |
|
---|
214 | template<class T_shape>
|
---|
215 | _bz_bool shapeCheck(const T_shape& shape) const
|
---|
216 | {
|
---|
217 | // NEEDS_WORK-- do a real shape check (tricky)
|
---|
218 | return _bz_true;
|
---|
219 | }
|
---|
220 |
|
---|
221 | private:
|
---|
222 | _bz_ArrayExprReduce() { }
|
---|
223 |
|
---|
224 | T_reduction reduce_;
|
---|
225 | T_expr iter_;
|
---|
226 | };
|
---|
227 |
|
---|
228 | #define BZ_DECL_ARRAY_PARTIAL_REDUCE(fn,reduction) \
|
---|
229 | template<class T_expr, int N_index> \
|
---|
230 | inline \
|
---|
231 | _bz_ArrayExpr<_bz_ArrayExprReduce<_bz_ArrayExpr<T_expr>, N_index, \
|
---|
232 | reduction<_bz_typename T_expr::T_numtype> > > \
|
---|
233 | fn(_bz_ArrayExpr<T_expr> expr, const IndexPlaceholder<N_index>&) \
|
---|
234 | { \
|
---|
235 | return _bz_ArrayExprReduce<_bz_ArrayExpr<T_expr>, N_index, \
|
---|
236 | reduction<_bz_typename T_expr::T_numtype> >(expr); \
|
---|
237 | } \
|
---|
238 | \
|
---|
239 | template<class T_numtype, int N_rank, int N_index> \
|
---|
240 | inline \
|
---|
241 | _bz_ArrayExpr<_bz_ArrayExprReduce<ArrayIterator<T_numtype,N_rank>, \
|
---|
242 | N_index, reduction<T_numtype> > > \
|
---|
243 | fn(const Array<T_numtype, N_rank>& array, \
|
---|
244 | const IndexPlaceholder<N_index>&) \
|
---|
245 | { \
|
---|
246 | return _bz_ArrayExprReduce<ArrayIterator<T_numtype,N_rank>, \
|
---|
247 | N_index, reduction<T_numtype> > (array.begin()); \
|
---|
248 | }
|
---|
249 |
|
---|
250 | BZ_DECL_ARRAY_PARTIAL_REDUCE(sum, ReduceSum)
|
---|
251 | BZ_DECL_ARRAY_PARTIAL_REDUCE(mean, ReduceMean)
|
---|
252 | BZ_DECL_ARRAY_PARTIAL_REDUCE(min, ReduceMin)
|
---|
253 | BZ_DECL_ARRAY_PARTIAL_REDUCE(minIndex, ReduceMinIndex)
|
---|
254 | BZ_DECL_ARRAY_PARTIAL_REDUCE(max, ReduceMax)
|
---|
255 | BZ_DECL_ARRAY_PARTIAL_REDUCE(maxIndex, ReduceMaxIndex)
|
---|
256 | BZ_DECL_ARRAY_PARTIAL_REDUCE(product, ReduceProduct)
|
---|
257 | BZ_DECL_ARRAY_PARTIAL_REDUCE(count, ReduceCount)
|
---|
258 | BZ_DECL_ARRAY_PARTIAL_REDUCE(any, ReduceAny)
|
---|
259 | BZ_DECL_ARRAY_PARTIAL_REDUCE(all, ReduceAll)
|
---|
260 | BZ_DECL_ARRAY_PARTIAL_REDUCE(first, ReduceFirst)
|
---|
261 |
|
---|
262 | /*
|
---|
263 | * Complete reductions
|
---|
264 | */
|
---|
265 |
|
---|
266 | // Prototype of reduction function
|
---|
267 | template<class T_expr, class T_reduction>
|
---|
268 | _bz_typename T_reduction::T_resulttype
|
---|
269 | _bz_ArrayExprFullReduce(T_expr expr, T_reduction reduction);
|
---|
270 |
|
---|
271 | #define BZ_DECL_ARRAY_FULL_REDUCE(fn,reduction) \
|
---|
272 | template<class T_expr> \
|
---|
273 | inline \
|
---|
274 | _bz_typename reduction<_bz_typename T_expr::T_numtype>::T_resulttype \
|
---|
275 | fn(_bz_ArrayExpr<T_expr> expr) \
|
---|
276 | { \
|
---|
277 | return _bz_ArrayExprFullReduce(expr, \
|
---|
278 | reduction<_bz_typename T_expr::T_numtype>()); \
|
---|
279 | } \
|
---|
280 | \
|
---|
281 | template<class T_numtype, int N_rank> \
|
---|
282 | inline \
|
---|
283 | _bz_typename reduction<T_numtype>::T_resulttype \
|
---|
284 | fn(const Array<T_numtype, N_rank>& array) \
|
---|
285 | { \
|
---|
286 | return _bz_ArrayExprFullReduce(array.begin(), \
|
---|
287 | reduction<T_numtype>()); \
|
---|
288 | }
|
---|
289 |
|
---|
290 | BZ_DECL_ARRAY_FULL_REDUCE(sum, ReduceSum)
|
---|
291 | BZ_DECL_ARRAY_FULL_REDUCE(mean, ReduceMean)
|
---|
292 | BZ_DECL_ARRAY_FULL_REDUCE(min, ReduceMin)
|
---|
293 | BZ_DECL_ARRAY_FULL_REDUCE(minIndex, ReduceMinIndex)
|
---|
294 | BZ_DECL_ARRAY_FULL_REDUCE(max, ReduceMax)
|
---|
295 | BZ_DECL_ARRAY_FULL_REDUCE(maxIndex, ReduceMaxIndex)
|
---|
296 | BZ_DECL_ARRAY_FULL_REDUCE(product, ReduceProduct)
|
---|
297 | BZ_DECL_ARRAY_FULL_REDUCE(count, ReduceCount)
|
---|
298 | BZ_DECL_ARRAY_FULL_REDUCE(any, ReduceAny)
|
---|
299 | BZ_DECL_ARRAY_FULL_REDUCE(all, ReduceAll)
|
---|
300 | BZ_DECL_ARRAY_FULL_REDUCE(first, ReduceFirst)
|
---|
301 |
|
---|
302 | BZ_NAMESPACE_END
|
---|
303 |
|
---|
304 | #include <blitz/array/reduce.cc>
|
---|
305 |
|
---|
306 | #endif // BZ_ARRAYREDUCE_H
|
---|