2323
2424#include < geode/stochastic/geometry/random_engine.hpp>
2525
26- #include < geode/stochastic/geometry/random_sample_spec .hpp>
26+ #include < geode/stochastic/geometry/distributions .hpp>
2727
2828#include < geode/basic/pimpl_impl.hpp>
2929
3333#include " absl/random/uniform_int_distribution.h"
3434#include " absl/random/uniform_real_distribution.h"
3535
36- #include < variant>
36+ #include " absl/hash/hash.h"
37+ #include < limits>
3738
3839namespace
3940{
40- std::seed_seq create_seed_seq ( uint64_t seed )
41+ std::seed_seq create_seed_seq ( std::string_view word )
4142 {
43+ uint64_t seed = absl::Hash< std::string_view >{}( word );
4244 std::vector< uint32_t > seed_data = { static_cast < uint32_t >(
43- seed & 0xFFFFFFFF ),
44- static_cast < uint32_t >( seed >> 32 ) };
45+ seed >> 32 ),
46+ static_cast < uint32_t >( seed & 0xFFFFFFFF ) };
4547 return std::seed_seq ( seed_data.begin (), seed_data.end () );
4648 }
4749} // namespace
@@ -51,79 +53,96 @@ namespace geode
5153 class RandomEngine ::Impl
5254 {
5355 public:
54- explicit Impl ( uint64_t seed ) : rand_gen_{ create_seed_seq ( seed ) } {}
56+ explicit Impl () = default;
5557 ~Impl () = default ;
5658
57- template < typename RANDSPEC >
58- auto do_sample ( const RANDSPEC & spec )
59+ void set_seed ( std::string_view word )
5960 {
60- return do_sample_impl ( spec ) ;
61+ rand_gen_ = absl::BitGen{ create_seed_seq ( word ) } ;
6162 }
6263
6364 template < typename Type >
6465 Type sample_uniform ( const Uniform< Type >& law )
6566 {
66- // check interval values correctness
67+ OPENGEODE_DATA_EXCEPTION ( law.min .value < law.max .value ,
68+ " Uniform sampling cannot be done since " , law.min .value ,
69+ " is not < than " , law.max .value , " ." );
6770 if ( law.min .is_included )
6871 {
6972 if ( law.max .is_included )
7073 {
71- return absl::Uniform (
72- absl::IntervalClosed, rand_gen_, law.min , law.max );
74+ return absl::Uniform ( absl::IntervalClosed, rand_gen_,
75+ law.min . value , law.max . value );
7376 }
74- return absl::Uniform (
75- absl::IntervalClosedOpen, rand_gen_, law.min , law.max );
77+ return absl::Uniform ( absl::IntervalClosedOpen, rand_gen_,
78+ law.min . value , law.max . value );
7679 }
7780 if ( law.max .is_included )
7881 {
79- return absl::Uniform (
80- absl::IntervalOpenClosed, rand_gen_, law.min , law.max );
82+ return absl::Uniform ( absl::IntervalOpenClosed, rand_gen_,
83+ law.min . value , law.max . value );
8184 }
8285 return absl::Uniform (
83- absl::IntervalOpen, rand_gen_, law.min , law.max );
86+ absl::IntervalOpen, rand_gen_, law.min . value , law.max . value );
8487 }
8588
86- private:
87- int do_sample_impl ( const UniformInt& spec )
89+ double sample_gaussian ( const Gaussian& law )
8890 {
89- return absl::Uniform (
90- absl::IntervalClosed, rand_gen_, spec.min , spec.max );
91- }
92- double do_sample_impl ( const UniformDouble& spec )
93- {
94- return absl::Uniform ( rand_gen_, spec.min , spec.max );
95- }
96- double do_sample_impl ( const Gaussian& spec )
97- {
98- return absl::gaussian_distribution< double >(
99- spec.mean , spec.stddev )( rand_gen_ );
91+ OPENGEODE_DATA_EXCEPTION (
92+ law.standard_deviation > 0
93+ && std::isfinite ( law.standard_deviation )
94+ && std::isfinite ( law.mean ),
95+ " Gaussian sampling cannot be done, please check the mean (" ,
96+ law.mean , " ) and the standard deviation (" ,
97+ law.standard_deviation , " )." );
98+ if ( !law.min .has_value () || !law.max .has_value () )
99+ {
100+ return absl::gaussian_distribution< double >(
101+ law.mean , law.standard_deviation )( rand_gen_ );
102+ };
103+ const auto max =
104+ law.max .value_or ( std::numeric_limits< double >::infinity () );
105+ const auto min =
106+ law.min .value_or ( -std::numeric_limits< double >::infinity () );
107+
108+ OPENGEODE_DATA_EXCEPTION ( min < max,
109+ " Gaussian sampling cannot be done since " , min,
110+ " is not < than " , max, " ." );
111+
112+ OPENGEODE_DATA_EXCEPTION ( law.mean > min && law.mean < max,
113+ " Gaussian sampling cannot be done since please the mean value "
114+ " (" ,
115+ law.mean , " ) is not in [" , min, " ," , max, " ]." );
116+ double value;
117+ do
118+ {
119+ value = absl::gaussian_distribution< double >(
120+ law.mean , law.standard_deviation )( rand_gen_ );
121+ } while ( value < min || value > max );
122+ return value;
100123 }
101- bool do_sample_impl ( const Bernoulli& spec )
124+
125+ bool sample_bernoulli ( double probability_of_success )
102126 {
103- return absl::bernoulli_distribution ( spec.probability )(
127+ OPENGEODE_DATA_EXCEPTION (
128+ probability_of_success >= 0 . && probability_of_success <= 1.0 ,
129+ " Bernoulli sampling cannot be done since " ,
130+ probability_of_success, " is not in [0.,1.]." );
131+ return absl::bernoulli_distribution ( probability_of_success )(
104132 rand_gen_ );
105133 }
106134
107135 private:
108136 absl::BitGen rand_gen_;
109137 };
110138
111- RandomEngine::RandomEngine ( uint64_t seed ) : impl_{ seed } {}
112- RandomEngine::~RandomEngine () = default ;
139+ RandomEngine::RandomEngine () = default ;
113140
114- double RandomEngine::sample ( const RandomDoubleSpec& random_double_spec )
115- {
116- return std::visit (
117- [this ]( const auto & s ) {
118- return impl_->do_sample ( s );
119- },
120- random_double_spec );
121- }
141+ RandomEngine::~RandomEngine () = default ;
122142
123- template < typename RANDSPEC >
124- auto RandomEngine::sample ( const RANDSPEC & spec )
143+ void RandomEngine::set_seed ( std::string_view word )
125144 {
126- return impl_->do_sample ( spec );
145+ impl_->set_seed ( word );
127146 }
128147
129148 template < typename Type >
@@ -143,11 +162,14 @@ namespace geode
143162 template double opengeode_stochastic_geometry_api
144163 RandomEngine::sample_uniform ( const Uniform< double >& );
145164
146- template auto opengeode_stochastic_geometry_api RandomEngine::sample (
147- const UniformDouble& );
148- template auto opengeode_stochastic_geometry_api RandomEngine::sample (
149- const Gaussian& );
150- template auto opengeode_stochastic_geometry_api RandomEngine::sample (
151- const Bernoulli& );
165+ double RandomEngine::sample_gaussian ( const Gaussian& law )
166+ {
167+ return impl_->sample_gaussian ( law );
168+ }
169+
170+ bool RandomEngine::sample_bernoulli ( double probability_of_success )
171+ {
172+ return impl_->sample_bernoulli ( probability_of_success );
173+ }
152174
153175} // namespace geode
0 commit comments