Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-26 09:34:37

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/random/distribution/RoundedNonnegDistribution.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <type_traits>
0010 
0011 #include "corecel/Macros.hh"
0012 #include "corecel/Types.hh"
0013 #include "corecel/math/Algorithms.hh"
0014 #include "corecel/math/NumericLimits.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Sample from a distribution and return a rounded non-negative integer.
0021  *
0022  * This distribution wraps an arbitrary underlying sampler and rounds each
0023  * value to the nearest integer by adding 0.5 and truncating. Negative values
0024  * are clamped to zero. The underlying distribution MUST NOT return a value
0025  * greater than the maximum representable value of the integer type (i.e.,
0026  * don't use this to sample the number of atoms in a gram of substance).
0027  */
0028 template<class Distribution, class IntType = celeritas::size_type>
0029 class RoundedNonnegDistribution
0030 {
0031   public:
0032     //!@{
0033     //! \name Type aliases
0034     using real_type = typename Distribution::real_type;
0035     using result_type = IntType;
0036     //!@}
0037 
0038     static_assert(std::is_floating_point_v<real_type>);
0039     static_assert(std::is_integral_v<result_type>);
0040 
0041   public:
0042     // Construct with distribution arguments
0043     template<class... Args>
0044     inline CELER_FUNCTION explicit RoundedNonnegDistribution(Args&&... args);
0045 
0046     // Sample a rounded non-negative integer
0047     template<class Generator>
0048     inline CELER_FUNCTION result_type operator()(Generator& rng);
0049 
0050   private:
0051     Distribution sample_;
0052 };
0053 
0054 //---------------------------------------------------------------------------//
0055 // INLINE DEFINITIONS
0056 //---------------------------------------------------------------------------//
0057 /*!
0058  * Construct with arguments forwarded to the wrapped distribution.
0059  */
0060 template<class Distribution, class IntType>
0061 template<class... Args>
0062 CELER_FUNCTION
0063 RoundedNonnegDistribution<Distribution, IntType>::RoundedNonnegDistribution(
0064     Args&&... args)
0065     : sample_(celeritas::forward<Args>(args)...)
0066 {
0067 }
0068 
0069 //---------------------------------------------------------------------------//
0070 /*!
0071  * Sample a random number according to the rounded non-negative distribution.
0072  */
0073 template<class Distribution, class IntType>
0074 template<class Generator>
0075 CELER_FUNCTION auto
0076 RoundedNonnegDistribution<Distribution, IntType>::operator()(Generator& rng)
0077     -> result_type
0078 {
0079     real_type value = clamp_to_nonneg(sample_(rng) + real_type{0.5});
0080     CELER_ENSURE(value < static_cast<real_type>(NumericLimits<IntType>::max()));
0081     return static_cast<result_type>(value);
0082 }
0083 
0084 //---------------------------------------------------------------------------//
0085 }  // namespace celeritas