diff --git a/stl/src/xfvalues.cpp b/stl/src/xfvalues.cpp index 5822c050fae..d0329ee4860 100644 --- a/stl/src/xfvalues.cpp +++ b/stl/src/xfvalues.cpp @@ -28,6 +28,6 @@ extern /* const */ _Dconst _FNan = {INIT((_FMAX << _FOFF) | (1 << (_FOFF - 1) extern /* const */ _Dconst _FSnan = {INIT2(_FMAX << _FOFF, 1)}; extern const _Dconst _FRteps = {INIT((_FBIAS - NBITS / 2) << _FOFF)}; -extern const float _FXbig = (NBITS + 1) * 347L / 1000; +extern const float _FXbig = (NBITS + 2) * 0.347f; _END_EXTERN_C_UNLESS_PURE diff --git a/stl/src/xlvalues.cpp b/stl/src/xlvalues.cpp index c2720fe8d16..7ec133738c2 100644 --- a/stl/src/xlvalues.cpp +++ b/stl/src/xlvalues.cpp @@ -26,4 +26,4 @@ extern /* const */ _Dconst _LNan = {INIT((_DMAX << _DOFF) | (1 << (_DOFF - 1) extern /* const */ _Dconst _LSnan = {INIT2(_DMAX << _DOFF, 1)}; extern const _Dconst _LRteps = {INIT((_DBIAS - NBITS / 2) << _DOFF)}; -extern const long double _LXbig = (NBITS + 1) * 347L / 1000; +extern const long double _LXbig = (NBITS + 2) * 0.347L; diff --git a/stl/src/xvalues.cpp b/stl/src/xvalues.cpp index e48d493d42c..1d9a1fb1e30 100644 --- a/stl/src/xvalues.cpp +++ b/stl/src/xvalues.cpp @@ -28,4 +28,4 @@ extern /* const */ _Dconst _Nan = {INIT((_DMAX << _DOFF) | (1 << (_DOFF - 1) extern /* const */ _Dconst _Snan = {INIT2(_DMAX << _DOFF, 1)}; extern const _Dconst _Rteps = {INIT((_DBIAS - NBITS / 2) << _DOFF)}; -extern const double _Xbig = (NBITS + 1) * 347L / 1000; +extern const double _Xbig = (NBITS + 2) * 0.347; diff --git a/tests/std/test.lst b/tests/std/test.lst index 0e60c21053b..34b48abda6f 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -164,6 +164,7 @@ tests\GH_000890_pow_template tests\GH_000940_missing_valarray_copy tests\GH_001010_filesystem_error_encoding tests\GH_001017_discrete_distribution_out_of_range +tests\GH_001059_hyperbolic_truncation tests\GH_001086_partial_sort_copy tests\GH_001103_countl_zero_correctness tests\LWG2597_complex_branch_cut diff --git a/tests/std/tests/GH_001059_hyperbolic_truncation/env.lst b/tests/std/tests/GH_001059_hyperbolic_truncation/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_001059_hyperbolic_truncation/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_001059_hyperbolic_truncation/test.cpp b/tests/std/tests/GH_001059_hyperbolic_truncation/test.cpp new file mode 100644 index 00000000000..67d69e1bb9a --- /dev/null +++ b/tests/std/tests/GH_001059_hyperbolic_truncation/test.cpp @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// GH-1059: "Incorrect const float values in xvalues.cpp files" +// The _Xbig constants, used to determine when the exp(-x) terms in +// cosh and sinh can be ignored, have off-by-one and integer +// truncation errors. + +#include +#include +#include +#include +#include +#include + +using namespace std; + +template +void Test(T x) { + const complex z{x}; + const T exp_over_2 = T{0.5} * real(exp(z)); + + const T cosh_expected = exp_over_2 + T{0.25} / exp_over_2; + const T cosh_calc = real(cosh(z)); + if (cosh_expected != cosh_calc) { + cout.precision(numeric_limits::digits10 + 2); + cout << "x = " << x << '\n' + << "cosh (expected) = " << cosh_expected << '\n' + << "cosh (calculated) = " << cosh_calc << endl; + assert(cosh_expected == cosh_calc); + } + + const T sinh_expected = exp_over_2 - T{0.25} / exp_over_2; + const T sinh_calc = real(sinh(z)); + if (sinh_expected != sinh_calc) { + cout.precision(numeric_limits::digits10 + 2); + cout << "x = " << x << '\n' + << "sinh (expected) = " << sinh_expected << '\n' + << "sinh (calculated) = " << sinh_calc << endl; + assert(sinh_expected == sinh_calc); + } +} + +template +constexpr array GenerateValues() { + // {old crossover, difference ~ 1 ulp, difference ~ ulp/2} + constexpr int DIG = numeric_limits::digits; + return {DIG * 347L / 1000L, DIG * static_cast(0.347), (DIG + 1) * static_cast(0.347)}; +} + +int main() { + constexpr auto fValues{GenerateValues()}; + for (const auto& x : fValues) { + Test(x); + } + + constexpr auto dValues{GenerateValues()}; + for (const auto& x : dValues) { + Test(x); + } + + return 0; +}