2
/***************************************************************************
3
* blitz/array/reduce.h Reductions of an array (or array expression) in a
4
* single rank: sum, mean, min, minIndex, max, maxIndex,
5
* product, count, any, all
7
* Copyright (C) 1997-2001 Todd Veldhuizen <tveldhui@oonumerics.org>
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License
11
* as published by the Free Software Foundation; either version 2
12
* of the License, or (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* Suggestions: blitz-dev@oonumerics.org
20
* Bugs: blitz-bugs@oonumerics.org
22
* For more information, please see the Blitz++ Home Page:
23
* http://oonumerics.org/blitz/
25
****************************************************************************/
26
#ifndef BZ_ARRAYREDUCE_H
27
#define BZ_ARRAYREDUCE_H
29
#ifndef BZ_ARRAYEXPR_H
30
#error <blitz/array/reduce.h> must be included after <blitz/array/expr.h>
33
#include <blitz/reduce.h>
37
template<typename T_expr, int N_index, typename T_reduction>
38
class _bz_ArrayExprReduce {
41
typedef _bz_typename T_reduction::T_numtype T_numtype;
42
typedef T_expr T_ctorArg1;
43
typedef T_reduction T_ctorArg2;
46
numArrayOperands = T_expr::numArrayOperands,
47
numIndexPlaceholders = T_expr::numIndexPlaceholders + 1,
48
rank = T_expr::rank - 1;
50
_bz_ArrayExprReduce(const _bz_ArrayExprReduce<T_expr,N_index,T_reduction>&
52
: reduce_(reduce.reduce_), iter_(reduce.iter_), ordering_(reduce.ordering_)
56
_bz_ArrayExprReduce(T_expr expr)
58
{ computeOrdering(); }
60
_bz_ArrayExprReduce(T_expr expr, T_reduction reduce)
61
: iter_(expr), reduce_(reduce)
62
{ computeOrdering(); }
65
{ return iter_.ascending(r); }
68
{ return ordering_[r]; }
71
{ return iter_.lbound(r); }
74
{ return iter_.ubound(r); }
76
template<int N_destRank>
77
T_numtype operator()(const TinyVector<int, N_destRank>& destIndex)
79
BZPRECHECK(N_destRank == N_index,
80
"Array reduction performed over rank " << N_index
81
<< " to produce a rank " << N_destRank << " expression." << endl
82
<< "You must reduce over rank " << N_destRank << " instead.");
84
TinyVector<int, N_destRank + 1> index;
86
// This metaprogram copies elements 0..N-1 of destIndex into index
87
_bz_meta_vecAssign<N_index, 0>::assign(index, destIndex,
88
_bz_update<int,int>());
90
int lbound = iter_.lbound(N_index);
91
int ubound = iter_.ubound(N_index);
93
// NEEDS_WORK: replace with tiny(int()) and huge(int()) once
94
// <limits> widely available
95
BZPRECHECK((lbound != INT_MIN) && (ubound != INT_MAX),
96
"Array reduction performed over rank " << N_index
97
<< " is unbounded." << endl
98
<< "There must be an array object in the expression being reduced"
99
<< endl << "which provides a bound in rank " << N_index << ".");
103
for (index[N_index] = iter_.lbound(N_index);
104
index[N_index] <= ubound; ++index[N_index])
106
if (!reduce_(iter_(index), index[N_index]))
110
return reduce_.result(ubound-lbound+1);
113
// If you have a precondition failure on this routine, it means
114
// you are trying to use stack iteration mode on an expression
115
// which contains an index placeholder. You must use index
116
// iteration mode instead.
123
// See operator*() note
129
// See operator*() note
135
// See operator*() note
141
// See operator*() note
147
// See operator*() note
153
bool isUnitStride(int) const
159
void advanceUnitStride()
164
bool canCollapse(int,int) const
165
{ BZPRECONDITION(0); return false; }
167
T_numtype operator[](int)
173
T_numtype fastRead(int)
179
int suggestStride(int) const
185
bool isStride(int,int) const
192
void moveTo(const TinyVector<int,N_rank>&)
198
void prettyPrint(BZ_STD_SCOPE(string) &str,
199
prettyPrintFormat& format) const
201
// NEEDS_WORK-- do real formatting for reductions
202
str += "reduce[NEEDS_WORK](";
203
iter_.prettyPrint(str,format);
207
template<typename T_shape>
208
bool shapeCheck(const T_shape&) const
210
// NEEDS_WORK-- do a real shape check (tricky)
215
_bz_ArrayExprReduce() { }
216
// method for properly initializing the ordering values
217
void computeOrdering()
219
TinyVector<bool,rank> in_ordering;
223
for (int i=0; i<rank; ++i)
225
int orderingj = iter_.ordering(i);
226
if (orderingj != INT_MIN && orderingj < rank &&
227
!in_ordering(orderingj)) { // unique value in ordering array
228
in_ordering(orderingj) = true;
229
ordering_(j++) = orderingj;
234
// It is possible that ordering is not a permutation of 0,...,rank-1.
235
// In that case j will be less than rank. We fill in ordering with
236
// the unused values in decreasing order.
237
for (int i = rank-1; j < rank; ++j) {
238
while (in_ordering(i))
246
TinyVector<int,rank> ordering_;
249
#define BZ_DECL_ARRAY_PARTIAL_REDUCE(fn,reduction) \
250
template<typename T_expr, int N_index> \
252
_bz_ArrayExpr<_bz_ArrayExprReduce<_bz_ArrayExpr<T_expr>, N_index, \
253
reduction<_bz_typename T_expr::T_numtype> > > \
254
fn(_bz_ArrayExpr<T_expr> expr, const IndexPlaceholder<N_index>&) \
256
return _bz_ArrayExprReduce<_bz_ArrayExpr<T_expr>, N_index, \
257
reduction<_bz_typename T_expr::T_numtype> >(expr); \
260
template<typename T_numtype, int N_rank, int N_index> \
262
_bz_ArrayExpr<_bz_ArrayExprReduce<FastArrayIterator<T_numtype,N_rank>, \
263
N_index, reduction<T_numtype> > > \
264
fn(const Array<T_numtype, N_rank>& array, \
265
const IndexPlaceholder<N_index>&) \
267
return _bz_ArrayExprReduce<FastArrayIterator<T_numtype,N_rank>, \
268
N_index, reduction<T_numtype> > (array.beginFast()); \
271
BZ_DECL_ARRAY_PARTIAL_REDUCE(sum, ReduceSum)
272
BZ_DECL_ARRAY_PARTIAL_REDUCE(mean, ReduceMean)
273
BZ_DECL_ARRAY_PARTIAL_REDUCE(min, ReduceMin)
274
BZ_DECL_ARRAY_PARTIAL_REDUCE(minIndex, ReduceMinIndex)
275
BZ_DECL_ARRAY_PARTIAL_REDUCE(max, ReduceMax)
276
BZ_DECL_ARRAY_PARTIAL_REDUCE(maxIndex, ReduceMaxIndex)
277
BZ_DECL_ARRAY_PARTIAL_REDUCE(product, ReduceProduct)
278
BZ_DECL_ARRAY_PARTIAL_REDUCE(count, ReduceCount)
279
BZ_DECL_ARRAY_PARTIAL_REDUCE(any, ReduceAny)
280
BZ_DECL_ARRAY_PARTIAL_REDUCE(all, ReduceAll)
281
BZ_DECL_ARRAY_PARTIAL_REDUCE(first, ReduceFirst)
282
BZ_DECL_ARRAY_PARTIAL_REDUCE(last, ReduceLast)
285
* Complete reductions
288
// Prototype of reduction function
289
template<typename T_expr, typename T_reduction>
290
_bz_typename T_reduction::T_resulttype
291
_bz_ArrayExprFullReduce(T_expr expr, T_reduction reduction);
293
#define BZ_DECL_ARRAY_FULL_REDUCE(fn,reduction) \
294
template<typename T_expr> \
296
_bz_typename reduction<_bz_typename T_expr::T_numtype>::T_resulttype \
297
fn(_bz_ArrayExpr<T_expr> expr) \
299
return _bz_ArrayExprFullReduce(expr, \
300
reduction<_bz_typename T_expr::T_numtype>()); \
303
template<typename T_numtype, int N_rank> \
305
_bz_typename reduction<T_numtype>::T_resulttype \
306
fn(const Array<T_numtype, N_rank>& array) \
308
return _bz_ArrayExprFullReduce(array.beginFast(), \
309
reduction<T_numtype>()); \
312
BZ_DECL_ARRAY_FULL_REDUCE(sum, ReduceSum)
313
BZ_DECL_ARRAY_FULL_REDUCE(mean, ReduceMean)
314
BZ_DECL_ARRAY_FULL_REDUCE(min, ReduceMin)
315
BZ_DECL_ARRAY_FULL_REDUCE(max, ReduceMax)
316
BZ_DECL_ARRAY_FULL_REDUCE(product, ReduceProduct)
317
BZ_DECL_ARRAY_FULL_REDUCE(count, ReduceCount)
318
BZ_DECL_ARRAY_FULL_REDUCE(any, ReduceAny)
319
BZ_DECL_ARRAY_FULL_REDUCE(all, ReduceAll)
320
BZ_DECL_ARRAY_FULL_REDUCE(first, ReduceFirst)
321
BZ_DECL_ARRAY_FULL_REDUCE(last, ReduceLast)
323
// Special versions of complete reductions: minIndex and
326
#define BZ_DECL_ARRAY_FULL_REDUCE_INDEXVECTOR(fn,reduction) \
327
template<typename T_expr> \
329
_bz_typename reduction<_bz_typename T_expr::T_numtype, \
330
T_expr::rank>::T_resulttype \
331
fn(_bz_ArrayExpr<T_expr> expr) \
333
return _bz_reduceWithIndexVectorTraversal(expr, \
334
reduction<_bz_typename T_expr::T_numtype, T_expr::rank>()); \
337
template<typename T_numtype, int N_rank> \
339
_bz_typename reduction<T_numtype,N_rank>::T_resulttype \
340
fn(const Array<T_numtype, N_rank>& array) \
342
return _bz_reduceWithIndexVectorTraversal( array.beginFast(), \
343
reduction<T_numtype,N_rank>()); \
346
BZ_DECL_ARRAY_FULL_REDUCE_INDEXVECTOR(minIndex, ReduceMinIndexVector)
347
BZ_DECL_ARRAY_FULL_REDUCE_INDEXVECTOR(maxIndex, ReduceMaxIndexVector)
351
#include <blitz/array/reduce.cc>
353
#endif // BZ_ARRAYREDUCE_H