iMSTK
Interactive Medical Simulation Toolkit
imstkParallelReduce.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkMath.h"
10 #include "imstkVecDataArray.h"
11 
12 DISABLE_WARNING_PUSH
13  DISABLE_WARNING_PADDING
14 #include <tbb/tbb.h>
15 DISABLE_WARNING_POP
16 
17 #undef min
18 #undef max
19 
20 namespace imstk
21 {
22 namespace ParallelUtils
23 {
28 template<class ContainerType>
30 {
31 public:
32  RangeFunctor(const ContainerType& data) : m_Data(data) { }
33  RangeFunctor(RangeFunctor& pObj, tbb::split) : m_Data(pObj.m_Data) { }
34 
35  // Prohibit copying
36  RangeFunctor() = delete;
37  RangeFunctor& operator=(const RangeFunctor&) = delete;
38 
39  void operator()(const tbb::blocked_range<size_t>& r)
40  {
41  for (size_t i = r.begin(); i != r.end(); i++)
42  {
43  m_Max = m_Max > m_Data[i] ? m_Max : m_Data[i];
44  m_Min = m_Max < m_Data[i] ? m_Min : m_Data[i];
45  }
46  }
47 
48  void join(RangeFunctor& pObj)
49  {
50  m_Max = m_Max > pObj.m_Max ? m_Max : pObj.m_Max;
51  m_Min = m_Min < pObj.m_Min ? m_Min : pObj.m_Min;
52  }
53 
54  Vec2d getRange() const { return Vec2d(m_Min, m_Max); }
55 
56 private:
57  double m_Min = IMSTK_DOUBLE_MAX;
58  double m_Max = IMSTK_DOUBLE_MIN;
59  const ContainerType& m_Data;
60 };
61 
67 {
68 public:
69  MaxL2NormFunctor(const VecDataArray<double, 3>& data) : m_Data(data) {}
70  MaxL2NormFunctor(MaxL2NormFunctor& pObj, tbb::split) : m_Data(pObj.m_Data) {}
71 
72  // Prohibit copying
73  MaxL2NormFunctor() = delete;
74  MaxL2NormFunctor& operator=(const MaxL2NormFunctor&) = delete;
75 
76  void operator()(const tbb::blocked_range<size_t>& r)
77  {
78  for (size_t i = r.begin(); i != r.end(); ++i)
79  {
80  double mag2 = m_Data[i].squaredNorm();
81  m_Result = m_Result > mag2 ? m_Result : mag2;
82  }
83  }
84 
85  void join(MaxL2NormFunctor& pObj) { m_Result = m_Result > pObj.m_Result ? m_Result : pObj.m_Result; }
86  double getResult() const { return std::sqrt(m_Result); }
87 
88 private:
89  double m_Result = 0.0;
90  const VecDataArray<double, 3>& m_Data;
91 };
92 
98 {
99 public:
100  AABBFunctor(const VecDataArray<double, 3>& data) : m_Data(data) { if (data.size() > 0) { m_UpperCorner = data[0]; } }
101  AABBFunctor(AABBFunctor& pObj, tbb::split) : m_Data(pObj.m_Data) {}
102 
103  // Prohibit copying
104  AABBFunctor() = delete;
105  AABBFunctor& operator=(const AABBFunctor&) = delete;
106 
110  void operator()(const tbb::blocked_range<size_t>& r)
111  {
112  for (size_t i = r.begin(); i != r.end(); ++i)
113  {
114  const auto& vec = m_Data[i];
115  for (int j = 0; j < 3; ++j)
116  {
117  m_LowerCorner[j] = (m_LowerCorner[j] < vec[j]) ? m_LowerCorner[j] : vec[j];
118  m_UpperCorner[j] = (m_UpperCorner[j] > vec[j]) ? m_UpperCorner[j] : vec[j];
119  }
120  }
121  }
122 
126  void join(AABBFunctor& pObj)
127  {
128  for (int j = 0; j < 3; ++j)
129  {
130  m_LowerCorner[j] = (m_LowerCorner[j] < pObj.m_LowerCorner[j]) ? m_LowerCorner[j] : pObj.m_LowerCorner[j];
131  m_UpperCorner[j] = (m_UpperCorner[j] > pObj.m_UpperCorner[j]) ? m_UpperCorner[j] : pObj.m_UpperCorner[j];
132  }
133  }
134 
138  const Vec3d& getLowerCorner() const { return m_LowerCorner; }
142  const Vec3d& getUpperCorner() const { return m_UpperCorner; }
143 
144 private:
145  Vec3d m_LowerCorner = Vec3d(std::numeric_limits<double>::max(),
146  std::numeric_limits<double>::max(),
147  std::numeric_limits<double>::max());
148  Vec3d m_UpperCorner = Vec3d(-std::numeric_limits<double>::max(),
149  -std::numeric_limits<double>::max(),
150  -std::numeric_limits<double>::max());
151  const VecDataArray<double, 3>& m_Data;
152 };
153 
157 inline double
158 findMaxL2Norm(const VecDataArray<double, 3>& data)
159 {
160  MaxL2NormFunctor pObj(data);
161  tbb::parallel_reduce(tbb::blocked_range<size_t>(0, data.size()), pObj);
162  return pObj.getResult();
163 }
164 
168 inline void
169 findAABB(const VecDataArray<double, 3>& points, Vec3d& lowerCorner, Vec3d& upperCorner)
170 {
171  AABBFunctor pObj(points);
172  tbb::parallel_reduce(tbb::blocked_range<size_t>(0, points.size()), pObj);
173  lowerCorner = pObj.getLowerCorner();
174  upperCorner = pObj.getUpperCorner();
175 }
176 } // end namespace ParallelUtils
177 } // end namespace imstk
Private helper class, providing operator() using in std::parallel_reduce for finding range of a conta...
Compound Geometry.
void operator()(const tbb::blocked_range< size_t > &r)
Compute the lower and upper corner of this in range r.
void join(AABBFunctor &pObj)
Compute the AABB of this and anohter object pObj as a whole.
Private helper class, providing operator() using in std::parallel_reduce for finding axis-aligned bou...
const Vec3d & getUpperCorner() const
Get the upper corner.
const Vec3d & getLowerCorner() const
Get the lower corner.
Private helper class, providing operator() using in std::parallel_reduce for finding max L2 norm of a...