Skip to content

Commit aad06c0

Browse files
committed
use scaling method to prevent overflow
1 parent a0657ed commit aad06c0

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

stl/inc/random

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,21 +2929,36 @@ private:
29292929
_Res = _Xx2;
29302930
_Valid = false;
29312931
} else { // generate two values, store one, return one
2932-
const _Ty _MinSx{static_cast<_Ty>(7.8159598771420286e-306)};
2933-
const _Ty _MaxSx{static_cast<_Ty>(1)};
29342932
_Ty _Vx1;
29352933
_Ty _Vx2;
2936-
_Ty _Sx;
2937-
for (;;) { // reject bad values
2934+
_Ty _Fx;
2935+
for (;;) {
29382936
_Vx1 = 2 * _NRAND(_Eng, _Ty) - 1;
29392937
_Vx2 = 2 * _NRAND(_Eng, _Ty) - 1;
2940-
_Sx = _Vx1 * _Vx1 + _Vx2 * _Vx2;
2941-
if (_MinSx < _Sx && _Sx < _MaxSx) {
2942-
// Good _Sx value! It will not cause overflow nor generating NaN/Inf on the next calculations.
2943-
break;
2938+
_Ty _Sx{_Vx1 * _Vx1 + _Vx2 * _Vx2};
2939+
if (static_cast<_Ty>(1) <= _Sx || _Sx == static_cast<_Ty>(0)) {
2940+
// Bad values! They will cause generating NaN/Inf on the next calculations.
2941+
continue;
2942+
}
2943+
2944+
_Ty _LogSx;
2945+
if (_Sx > 1.0e-4) {
2946+
_LogSx = _STD log(_Sx);
2947+
} else {
2948+
// Bad _Sx value! It will cause overflow on next calculations.
2949+
// generating a new value based on scaling method.
2950+
const _Ty _ln2{static_cast<_Ty>(0.69314718055994530941723212145818)};
2951+
const _Ty _Maxabs{_STD max(_STD abs(_Vx1), _STD abs(_Vx2))};
2952+
const int expMax{_STD ilogb(_Maxabs)};
2953+
_Vx1 = _STD scalbn(_Vx1, -expMax);
2954+
_Vx2 = _STD scalbn(_Vx2, -expMax);
2955+
_Sx = _Vx1 * _Vx1 + _Vx2 * _Vx2;
2956+
_LogSx = _STD log(_Sx) + static_cast<_Ty>(expMax) * (_ln2 * 2);
29442957
}
2958+
2959+
_Fx = static_cast<_Ty>(_STD sqrt(static_cast<_Ty>(-2) * _LogSx / _Sx));
2960+
break;
29452961
}
2946-
const auto _Fx = static_cast<_Ty>(_CSTD sqrt(-2.0 * _CSTD log(_Sx) / _Sx));
29472962
if (_Keep) { // save second value for next call
29482963
_Xx2 = _Fx * _Vx2;
29492964
_Valid = true;

0 commit comments

Comments
 (0)