File indexing completed on 2025-09-15 08:54:44
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "corecel/cont/Range.hh"
0012 #include "corecel/grid/Interpolator.hh"
0013 #include "corecel/math/Algorithms.hh"
0014 #include "corecel/math/SoftEqual.hh"
0015
0016 namespace celeritas
0017 {
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 template<class G, class C>
0029 class InverseCdfFinder
0030 {
0031 public:
0032
0033 inline CELER_FUNCTION InverseCdfFinder(G&& grid, C&& calc_cdf);
0034
0035
0036 inline CELER_FUNCTION real_type operator()(real_type cdf) const;
0037
0038 private:
0039 G grid_;
0040 C calc_cdf_;
0041 };
0042
0043
0044
0045
0046
0047
0048
0049 template<class G, class C>
0050 CELER_FUNCTION InverseCdfFinder<G, C>::InverseCdfFinder(G&& grid, C&& calc_cdf)
0051 : grid_(celeritas::forward<G>(grid))
0052 , calc_cdf_(celeritas::forward<C>(calc_cdf))
0053 {
0054 CELER_EXPECT(grid_.size() >= 2);
0055 CELER_EXPECT(calc_cdf_[0] == 0
0056 && soft_equal(calc_cdf_[grid_.size() - 1], real_type(1)));
0057 }
0058
0059
0060
0061
0062
0063 template<class G, class C>
0064 CELER_FUNCTION real_type InverseCdfFinder<G, C>::operator()(real_type cdf) const
0065 {
0066 CELER_EXPECT(cdf >= 0 && cdf < 1);
0067
0068
0069 Range indices(grid_.size() - 1);
0070 auto iter = celeritas::lower_bound(
0071 indices.begin(), indices.end(), cdf, [this](size_type i, real_type c) {
0072 return calc_cdf_[i] < c;
0073 });
0074 if (calc_cdf_[*iter] != cdf)
0075 {
0076 --iter;
0077 }
0078 size_type i = iter - indices.begin();
0079
0080
0081 return LinearInterpolator<real_type>{
0082 {calc_cdf_[i], grid_[i]}, {calc_cdf_[i + 1], grid_[i + 1]}}(cdf);
0083 }
0084
0085
0086 }