@@ -2428,7 +2428,7 @@ public:
24282428 _Ty1 _Logp;
24292429 _Ty1 _Logp1;
24302430
2431- _Small_poisson_distribution<_Ty> _Small;
2431+ _Small_poisson_distribution<_Ty> _Small; // TRANSITION, ABI: unused
24322432 };
24332433
24342434 binomial_distribution() : _Par(1, _Ty1(0.5)) {}
@@ -2505,8 +2505,26 @@ private:
25052505
25062506 return _Res;
25072507 } else if (_Par0._Mean < 1.0) {
2508- // events are rare, use Poisson distribution
2509- _Res = _Par0._Small(_Eng);
2508+ // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525).
2509+ const _Ty1 _Rand = _NRAND(_Eng, _Ty1);
2510+
2511+ // The exit condition is log(1 - _Rand)/t < log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If
2512+ // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two
2513+ // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's
2514+ // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t =
2515+ // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e.
2516+ const _Ty1 _Ub =
2517+ (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Pp + _Ty1{6.32120558828557678e-1});
2518+ if (_Rand > _Ub) {
2519+ _Res = _Ty{0};
2520+ } else {
2521+ _Ty _Denom = _Par0._Tx;
2522+ _Ty1 _Sum = _CSTD log(_Ty1{1.0} - _Rand) / _Denom;
2523+ while (_Sum >= _Par0._Logp1 && --_Denom != 0) {
2524+ _Sum += _CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / _Denom;
2525+ }
2526+ _Res = static_cast<_Ty>(_Par0._Tx - _Denom);
2527+ }
25102528 } else { // no shortcuts
25112529 using _Uty = make_unsigned_t<_Ty>;
25122530 const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))};
@@ -2780,7 +2798,7 @@ public:
27802798 }
27812799
27822800 _NODISCARD result_type(max)() const { // get largest possible result
2783- return ( numeric_limits<result_type>::max) ();
2801+ return numeric_limits<result_type>::infinity ();
27842802 }
27852803
27862804 void reset() {} // clear internal state
@@ -2917,11 +2935,11 @@ public:
29172935 }
29182936
29192937 _NODISCARD result_type(min)() const { // get smallest possible result
2920- return numeric_limits<result_type>::denorm_min ();
2938+ return - numeric_limits<result_type>::infinity ();
29212939 }
29222940
29232941 _NODISCARD result_type(max)() const { // get largest possible result
2924- return ( numeric_limits<result_type>::max) ();
2942+ return numeric_limits<result_type>::infinity ();
29252943 }
29262944
29272945 void reset() { // clear internal state
@@ -3057,7 +3075,7 @@ public:
30573075 }
30583076
30593077 _NODISCARD bool operator==(const param_type& _Right) const {
3060- return _Px == _Right._Px ;
3078+ return _Alpha == _Right._Alpha && _Beta == _Right._Beta ;
30613079 }
30623080
30633081 _NODISCARD bool operator!=(const param_type& _Right) const {
@@ -3111,11 +3129,11 @@ public:
31113129 }
31123130
31133131 _NODISCARD result_type(min)() const { // get smallest possible result
3114- return numeric_limits< result_type>::denorm_min() ;
3132+ return result_type{0.0} ;
31153133 }
31163134
31173135 _NODISCARD result_type(max)() const { // get largest possible result
3118- return ( numeric_limits<result_type>::max) ();
3136+ return numeric_limits<result_type>::infinity ();
31193137 }
31203138
31213139 void reset() {} // clear internal state
@@ -3306,7 +3324,7 @@ public:
33063324 }
33073325
33083326 _NODISCARD result_type(max)() const { // get largest possible result
3309- return ( numeric_limits<result_type>::max) ();
3327+ return numeric_limits<result_type>::infinity ();
33103328 }
33113329
33123330 void reset() {} // clear internal state
@@ -3438,11 +3456,11 @@ public:
34383456 }
34393457
34403458 _NODISCARD result_type(min)() const { // get smallest possible result
3441- return ( numeric_limits<result_type>::min) ();
3459+ return - numeric_limits<result_type>::infinity ();
34423460 }
34433461
34443462 _NODISCARD result_type(max)() const { // get largest possible result
3445- return ( numeric_limits<result_type>::max) ();
3463+ return numeric_limits<result_type>::infinity ();
34463464 }
34473465
34483466 void reset() {} // clear internal state
@@ -3576,11 +3594,11 @@ public:
35763594 }
35773595
35783596 _NODISCARD result_type(min)() const { // get smallest possible result
3579- return -(numeric_limits< result_type>::max)() ;
3597+ return result_type{0.0} ;
35803598 }
35813599
35823600 _NODISCARD result_type(max)() const { // get largest possible result
3583- return ( numeric_limits<result_type>::max) ();
3601+ return numeric_limits<result_type>::infinity ();
35843602 }
35853603
35863604 void reset() {} // clear internal state
@@ -3702,11 +3720,11 @@ public:
37023720 }
37033721
37043722 _NODISCARD result_type(min)() const { // get smallest possible result
3705- return numeric_limits< result_type>::denorm_min() ;
3723+ return result_type{0.0} ;
37063724 }
37073725
37083726 _NODISCARD result_type(max)() const { // get largest possible result
3709- return ( numeric_limits<result_type>::max) ();
3727+ return numeric_limits<result_type>::infinity ();
37103728 }
37113729
37123730 void reset() {} // clear internal state
@@ -3834,11 +3852,11 @@ public:
38343852 }
38353853
38363854 _NODISCARD result_type(min)() const { // get smallest possible result
3837- return -( numeric_limits<result_type>::max) ();
3855+ return -numeric_limits<result_type>::infinity ();
38383856 }
38393857
38403858 _NODISCARD result_type(max)() const { // get largest possible result
3841- return ( numeric_limits<result_type>::max) ();
3859+ return numeric_limits<result_type>::infinity ();
38423860 }
38433861
38443862 void reset() {} // clear internal state
@@ -4035,7 +4053,7 @@ public:
40354053 }
40364054
40374055 _NODISCARD result_type(max)() const { // get largest possible result
4038- return ( numeric_limits<result_type>::max) ();
4056+ return numeric_limits<result_type>::infinity ();
40394057 }
40404058
40414059 void reset() {} // clear internal state
@@ -4168,11 +4186,11 @@ public:
41684186 }
41694187
41704188 _NODISCARD result_type(min)() const { // get smallest possible result
4171- return -( numeric_limits<result_type>::max) ();
4189+ return -numeric_limits<result_type>::infinity ();
41724190 }
41734191
41744192 _NODISCARD result_type(max)() const { // get largest possible result
4175- return ( numeric_limits<result_type>::max) ();
4193+ return numeric_limits<result_type>::infinity ();
41764194 }
41774195
41784196 void reset() {} // clear internal state
0 commit comments