11namespace alpaka::rand::distribution::internal
18 template<std::
floating_po
int T_Floating>
19 consteval T_Floating prevOne() noexcept
21 if constexpr(
sizeof(T_Floating) == 4)
23 return std::bit_cast<T_Floating>(
static_cast<uint32_t
>(0x3f7f'ffff));
25 else if constexpr(
sizeof(T_Floating) == 8)
27 return std::bit_cast<T_Floating>(
static_cast<uint64_t
>(0x3fef'ffff'ffff'ffff));
35 template<std::
unsigned_
integral T_Integer, std::
floating_po
int T_Floating>
39 static constexpr T_Floating normalizedIntervalBin
40 = T_Floating{1} /
static_cast<T_Floating
>(std::numeric_limits<T_Integer>::max());
44 static constexpr T_Floating halfBinWidth = normalizedIntervalBin / T_Floating{2};
47 static constexpr T_Floating normalizedOpenIntervalBin
48 = prevOne<T_Floating>() /
static_cast<T_Floating
>(std::numeric_limits<T_Integer>::max());
57 template<
typename T_Engine, concepts::Interval T_Interval, std::
integral T_Integer, std::
floating_po
int T_Floating>
58 struct IntervalAwareConversion;
64 template<
typename T_Engine, std::
integral T_Integer, std::
floating_po
int T_Floating>
65 struct IntervalAwareConversion<T_Engine, interval::CO, T_Integer, T_Floating>
67 constexpr auto operator()(T_Integer
const& i)
const
69 constexpr auto interval = Constants<T_Integer, T_Floating>::normalizedOpenIntervalBin;
70 return static_cast<T_Floating
>(i) * interval;
82 template<
typename T_Engine, std::
integral T_Integer, std::
floating_po
int T_Floating>
83 struct IntervalAwareConversion<T_Engine, interval::OO, T_Integer, T_Floating>
85 constexpr auto operator()(T_Integer
const& i)
const
87 return static_cast<T_Floating
>(i) * Constants<T_Integer, T_Floating>::normalizedOpenIntervalBin
88 + Constants<T_Integer, T_Floating>::halfBinWidth;
98 template<
typename T_Engine, std::
integral T_Integer, std::
floating_po
int T_Floating>
99 struct IntervalAwareConversion<T_Engine, interval::OC, T_Integer, T_Floating>
101 constexpr auto operator()(T_Integer
const& i)
const
103 return static_cast<T_Floating
>(i) * Constants<T_Integer, T_Floating>::normalizedIntervalBin
104 + Constants<T_Integer, T_Floating>::halfBinWidth;
110 template<
typename T_Engine, std::
integral T_Integer, std::
floating_po
int T_Floating>
111 struct IntervalAwareConversion<T_Engine, interval::CC, T_Integer, T_Floating>
113 constexpr auto operator()(T_Integer
const& i)
const
115 return static_cast<T_Floating
>(i) * Constants<T_Integer, T_Floating>::normalizedIntervalBin;
122 template<
typename T_Engine, u
int32_t
byteLengthEngineResult, u
int32_t
byteLengthRealType>
123 struct BitLengthConformityAdapter
126 (byteLengthEngineResult == 4u || byteLengthRealType == 8u),
127 "Result returned by the randomBitGenerator does not have a length that is accepted by the uniformReal "
130 (byteLengthEngineResult == 8u || byteLengthRealType == 4u),
131 "The requested floating point type does not have a length that is accepted by the uniformReal "
134 byteLengthEngineResult == byteLengthRealType,
135 "By logic this should never fail in case the compiler accepts the specialization of the adapter!");
137 constexpr auto operator()(T_Engine& engine)
144 template<
typename T_Engine>
145 struct BitLengthConformityAdapter<T_Engine, 4u, 8u>
147 constexpr auto operator()(T_Engine& engine)
149 return static_cast<uint64_t
>(engine()) << 32 |
static_cast<uint64_t
>(engine());
154 template<
typename T_Engine>
155 struct BitLengthConformityAdapter<T_Engine, 8u, 4u>
157 constexpr auto operator()(T_Engine& engine)
159 return static_cast<uint32_t
>(engine());
167 template<concepts::Interval T_Interval, std::
floating_po
int T_Result,
typename T_Engine>
168 constexpr auto getNormalizedUniformReal(T_Engine& engine) -> T_Result
170 using T_EngineResult = std::remove_cvref_t<
decltype(engine())>;
172 auto adaptedBits = BitLengthConformityAdapter<
174 static_cast<uint32_t
>(
sizeof(T_EngineResult)),
175 static_cast<uint32_t
>(
sizeof(T_Result))>{}(engine);
177 return IntervalAwareConversion<T_Engine, T_Interval,
ALPAKA_TYPEOF(adaptedBits), T_Result>{}(adaptedBits);
179 template<concepts::UniformVectorEngine T_Engine, u
int32_t TResultSize, u
int32_t TElemSize, u
int32_t TElems>
180 struct vectorDispatchWrapper;
182 template<concepts::UniformVectorEngine T_Engine, u
int32_t TElemSize, u
int32_t TElems>
183 struct vectorDispatchWrapper<T_Engine, 4u, TElemSize, TElems>
186 static_assert(TElems > 0,
"RandomEngine did not return any elements!");
188 constexpr explicit vectorDispatchWrapper(T_Engine& eng) : ph(eng)
192 constexpr uint32_t operator()()
const
195 return static_cast<uint32_t
>(res[0]);
201 template<concepts::UniformVectorEngine T_Engine, u
int32_t TElems>
202 struct vectorDispatchWrapper<T_Engine, 8u, 4u, TElems>
205 using TResult =
decltype(ph());
206 static constexpr auto dim = TResult::dim();
207 static_assert(TElems >= 2,
"Engine result dimension must be >= 2, to be usable in UniformReal<double>");
209 constexpr explicit vectorDispatchWrapper(T_Engine& eng) : ph(eng)
213 constexpr uint64_t operator()()
const
216 return (
static_cast<uint64_t
>(res[0]) << 32) |
static_cast<uint64_t
>(res[1]);
220 template<std::
floating_po
int T_Floating, concepts::Interval T_Interval>
221 class UniformRealBase
224 using result_type = T_Floating;
226 using Interval_type = T_Interval;
228 constexpr explicit UniformRealBase(T_Floating min, T_Floating max, [[maybe_unused]] T_Interval)
231 , m_range(m_max - m_min)
236 T_Floating
const m_min;
237 T_Floating
const m_max;
238 T_Floating
const m_range;
257 template<std::
floating_po
int T_Result, concepts::Interval T_Interval =
interval::CO>
258 struct UniformReal : internal::UniformRealBase<T_Result, T_Interval>
260 static_assert(
static_cast<uint32_t
>(
sizeof(T_Result)) == 4u ||
static_cast<uint32_t
>(
sizeof(T_Result)) == 8u);
262 template<std::
integral T_Value>
266 static_cast<uint32_t
>(
sizeof(T_Value)) == 4u ||
static_cast<uint32_t
>(
sizeof(T_Value)) == 8u);
269 using Base = internal::UniformRealBase<T_Result, T_Interval>;
295 template<concepts::UniformRandomEngine T_Engine>
298 return engineDispatch(
engine);
305 template<concepts::UniformStdEngine T_Engine>
306 constexpr auto engineDispatch(T_Engine&
engine)
const -> T_Result
310 T_Result res = internal::getNormalizedUniformReal<T_Interval, T_Result, T_Engine>(
engine);
312 return scaleInterval(res);
318 template<concepts::UniformVectorEngine T_Engine>
319 constexpr auto engineDispatch(T_Engine&
engine)
const -> T_Result
322 using valueType =
typename T_EngineResult::type;
324 constexpr auto dim =
getDim(T_EngineResult{});
325 auto dispatchWrapper = internal::vectorDispatchWrapper<
327 static_cast<uint32_t
>(
sizeof(T_Result)),
328 static_cast<uint32_t
>(
sizeof(valueType)),
330 using T_DispatchWrapper =
decltype(dispatchWrapper);
332 = internal::getNormalizedUniformReal<T_Interval, T_Result, T_DispatchWrapper>(dispatchWrapper);
333 return scaleInterval(res);
350 constexpr auto scaleInterval(T_Result
const& normalizedVal)
const -> T_Result
352 T_Result res = normalizedVal * this->m_range + this->m_min;
354 if constexpr(std::is_same_v<T_Interval, interval::OC> || std::is_same_v<T_Interval, interval::OO>)
356 if(res == this->m_min)
357 res = std::nextafter(this->m_min, this->m_max);
359 if constexpr(std::is_same_v<T_Interval, interval::CO> || std::is_same_v<T_Interval, interval::OO>)
361 if(res == this->m_max)
362 res = std::nextafter(this->m_max, this->m_min);
#define ALPAKA_TYPEOF(...)
Get the type of instance.
constexpr auto min(auto const &a, auto const &b)
constexpr auto max(auto const &a, auto const &b)
consteval uint32_t getDim(T const &any)