@@ -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