OpenVDB 13.0.1
Loading...
Searching...
No Matches
PrefixSum.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file nanovdb/util/PrefixSum.h
6
7 \author Ken Museth
8
9 \date March 12, 2023
10
11 \brief Multi-threaded implementations of inclusive prefix sum
12
13 \note An exclusive prefix sum is simply an array starting with zero
14 followed by the elements in the inclusive prefix sum, minus its
15 last entry which is the sum of all the input elements.
16*/
17
18#ifndef NANOVDB_UTIL_PREFIX_SUM_H_HAS_BEEN_INCLUDED
19#define NANOVDB_UTIL_PREFIX_SUM_H_HAS_BEEN_INCLUDED
20
21#include <nanovdb/util/Range.h>// for Range1D
22#include <vector>
23#include <functional>// for std::plus
24
25#ifdef NANOVDB_USE_TBB
26#include <tbb/parallel_scan.h>
27#endif
28
29namespace nanovdb {
30
31namespace util {
32
33/// @brief Computes inclusive prefix sum of a vector
34/// @tparam T Type of the elements in the input/out vector
35/// @tparam OpT Type of operation performed on each element (defaults to sum)
36/// @param vec input and output vector
37/// @param threaded if true multi-threading is used
38/// @param op binary operation used to combine successive elements (defaults to @c std::plus<T>)
39/// @note Inclusive prefix sum: for (i=1; i<N; ++i) vec[i] += vec[i-1]
40/// @return sum of all input elements, which is also the last element of the inclusive prefix sum
41template<typename T, typename OpT = std::plus<T>>
42T prefixSum(std::vector<T> &vec, bool threaded = true, OpT op = OpT());
43
44/// @brief An inclusive scan includes in[i] when computing out[i]
45/// @note Inclusive prefix operation: for (i=1; i<N; ++i) vec[i] = Op(vec[i],vec[i-1])
46template<typename T, typename Op>
47void inclusiveScan(T *array, size_t size, const T &identity, bool threaded, Op op)
48{
49#ifndef NANOVDB_USE_TBB
50 threaded = false;
51 (void)identity;// avoids compiler warning
52#endif
53
54 if (threaded) {
55#ifdef NANOVDB_USE_TBB
56 using RangeT = tbb::blocked_range<size_t>;
57 tbb::parallel_scan(RangeT(0, size), identity,
58 [&](const RangeT &r, T sum, bool is_final_scan)->T {
59 T tmp = sum;
60 for (size_t i = r.begin(); i < r.end(); ++i) {
61 tmp = op(tmp, array[i]);
62 if (is_final_scan) array[i] = tmp;
63 }
64 return tmp;
65 },[&](const T &a, const T &b) {return op(a, b);}
66 );
67#endif
68 } else { // serial inclusive prefix operation
69 for (size_t i=1; i<size; ++i) array[i] = op(array[i], array[i-1]);
70 }
71}// inclusiveScan
72
73template<typename T, typename OpT>
74T prefixSum(std::vector<T> &vec, bool threaded, OpT op)
75{
76 inclusiveScan(vec.data(), vec.size(), T(0), threaded, op);
77 return vec.back();// sum of all input elements
78}// prefixSum
79
80}// namespace util
81
82template<typename T, typename OpT = std::plus<T>>
83[[deprecated("Use nanovdb::util::prefixSum instead")]]
84T prefixSum(std::vector<T> &vec, bool threaded = true, OpT op = OpT())
85{
86 return util::prefixSum<T, OpT>(vec, threaded, op);
87}// prefixSum
88
89}// namespace nanovdb
90
91#endif // NANOVDB_UTIL_PREFIX_SUM_H_HAS_BEEN_INCLUDED
Custom Range class that is compatible with the tbb::blocked_range classes.
Definition ForEach.h:29
T prefixSum(std::vector< T > &vec, bool threaded=true, OpT op=OpT())
Computes inclusive prefix sum of a vector.
Definition PrefixSum.h:74
void inclusiveScan(T *array, size_t size, const T &identity, bool threaded, Op op)
An inclusive scan includes in[i] when computing out[i].
Definition PrefixSum.h:47
Definition GridHandle.h:27
T prefixSum(std::vector< T > &vec, bool threaded=true, OpT op=OpT())
Definition PrefixSum.h:84