2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file ParallelIIEstimator.ih
19 * @author Bastien Doignies
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), INSA-Lyon, France
24 * Header file for module ParallelEstimator.ih
26 * This file is part of the DGtal library.
36 template<class TEstimator, typename TSplitter>
37 template<class... Args>
38 ParallelIIEstimator<TEstimator, TSplitter>::
39 ParallelIIEstimator(Splitter splitter, int32_t nbThread, Args&&... args)
40 : mySplitter(std::move(splitter))
43 nbThread = std::max(1, omp_get_max_threads());
45 // Note: We can not use std::vector constructor or resize
46 // because it will copy the estimator but it can have shared
48 // We rather build a new one in a loop by calling the constructor
49 // implictely with emplace_back
50 myEstimators.reserve(nbThread);
51 for (int i = 0; i < nbThread; ++i)
52 myEstimators.emplace_back(std::forward<Args>(args)...);
55 template<class TEstimator, typename TSplitter>
56 void ParallelIIEstimator<TEstimator, TSplitter>::clear()
58 for (auto& estim : myEstimators)
62 template<class TEstimator, typename TSplitter>
63 typename ParallelIIEstimator<TEstimator, TSplitter>::Scalar
64 ParallelIIEstimator<TEstimator, TSplitter>::h() const { return myEstimators[0].h(); }
66 template<class TEstimator, typename TSplitter>
67 void ParallelIIEstimator<TEstimator, TSplitter>::attach(
69 ConstAlias<PointPredicate> pp)
74 myPointPredicate = pp;
77 template<class TEstimator, typename TSplitter>
78 void ParallelIIEstimator<TEstimator, TSplitter>::setParams(double dRadius)
83 template<class TEstimator, typename TSplitter>
84 bool ParallelIIEstimator<TEstimator, TSplitter>::isValid() const
87 for (const auto& estim : myEstimators)
88 valid = valid && estim.isValid();
93 template<class TEstimator, typename TSplitter>
94 template<typename ItA, typename ItB>
95 void ParallelIIEstimator<TEstimator, TSplitter>::init(double h_, ItA, ItB)
100 template<class TEstimator, typename TSplitter>
101 template<typename It>
102 typename ParallelIIEstimator<TEstimator, TSplitter>::Quantity
103 ParallelIIEstimator<TEstimator, TSplitter>::eval(It it)
105 // TODO: Initialize properly the estimator (attaching shape, ...)
106 if (!myEstimators[0].isValid())
108 auto ite = it; ite++;
109 myEstimators[0].init(myH, it, ite);
114 .value = myEstimators[0].eval(it)
118 template<class TEstimator, typename TSplitter>
119 template<typename It, typename Oit>
120 Oit ParallelIIEstimator<TEstimator, TSplitter>::eval(It itb, It ite, Oit rslt)
122 Domain mainDomain(myKSpace->lowerBound(), myKSpace->upperBound());
123 std::vector<SplitInfo<Domain>> domains = mySplitter(mainDomain, myEstimators.size());
125 using Result = std::pair<Surfel, std::optional<EstimatorQuantity>>;
126 std::deque<Result> result;
127 std::vector<std::vector<Result*>> resultLocation(domains.size());
128 for ( auto it = itb; it != ite; ++it )
130 result.push_back( { *it, std::nullopt } );
131 Result* current = &result.back();
133 for (unsigned int j = 0; j < domains.size(); ++j)
135 // Should be true for only one of the domain. The break ensure
136 // each surfel belongs to one and only one domain, meaning there
137 // will be no concurrent write afterward
138 if (domains[j].domain.isInside(myKSpace->interiorVoxel(*it)))
140 resultLocation[j].push_back( current );
146 #pragma omp parallel for
147 for (uint32_t i = 0; i < domains.size(); ++i)
149 auto surfels = resultLocation[i] | std::views::transform([](const auto* kv) -> const Surfel&
153 auto values = resultLocation[i] | std::views::transform([](auto* kv) -> std::optional<EstimatorQuantity>&
158 auto& estim = myEstimators[i];
160 estim.attach(*myKSpace, *myPointPredicate);
161 estim.setParams(myRadius);
163 estim.init(myH, surfels.begin(), surfels.end());
164 estim.eval(surfels.begin(), surfels.end(), values.begin());
167 for ( const auto& entry : result )
168 *rslt++ = *( entry.second );
173 template<class TEstimator, typename TSplitter>
175 ParallelIIEstimator<TEstimator, TSplitter>::selfDisplay( std::ostream & out ) const
177 out << "[ParallelIIEstimator Estim=";
178 myEstimators[0].selfDisplay(out);