[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 204bd5f 5/5: Replace another assumption with
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 204bd5f 5/5: Replace another assumption with a static assertion |
Date: |
Thu, 13 Apr 2017 06:58:29 -0400 (EDT) |
branch: master
commit 204bd5f942adafd76e4c69fa3a2a36789aa541bc
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>
Replace another assumption with a static assertion
Added a static assertion to address this issue that Vadim had raised:
http://lists.nongnu.org/archive/html/lmi/2017-04/msg00001.html
| Still, it does seem wrong to add 1 to the maximally representable
| value of type "To" without being certain that it is _strictly_ less
| than that of type "From".
---
bourn_cast.hpp | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/bourn_cast.hpp b/bourn_cast.hpp
index d9c4b2d..039efa6 100644
--- a/bourn_cast.hpp
+++ b/bourn_cast.hpp
@@ -106,6 +106,33 @@ inline To bourn_cast(From from, std::false_type,
std::true_type)
/// Ones' complement might be handled thus [untested]:
/// - if(from < to_traits::lowest())
/// + if(from <= From(to_traits::lowest()) - 1)
+///
+/// Integral max() must be one less than an integer power of two,
+/// because C++11 [3.9.1/7] says "the representations of integral
+/// types shall define values by use of a pure binary numeration
+/// system", so the range of a signed eight-bit character (e.g.) is:
+/// [-127, +127] sign and magnitude, or ones' complement; or
+/// [-128, +127] two's complement;
+/// and the maximum must be 2^digits - 1 in any case.
+///
+/// It is not always feasible to compare the argument's value directly
+/// to this maximum in order to determine whether it is within range:
+/// see test_m64_neighborhood() in the accompanying unit test for a
+/// demonstration of the issues that arise in converting ULLONG_MAX to
+/// IEEE 754 binary32. Therefore, the tractable comparison
+/// argument <= maximum + 1 // i.e., <= 2^n exactly
+/// is substituted for the intractable
+/// argument < maximum // < 0xFF... may exceed float precision
+/// To ensure that the addition 'maximum + 1' is not done in extended
+/// precision (as actually observed with various versions of gcc), it
+/// is performed through writes to volatile memory. To ensure that
+/// the maximum can be incremented, a static assertion compares the
+/// number of integral radix digits to the number of floating exponent
+/// digits. This assertion would be expected to fail with a 128-bit
+/// integral type and a 32-bit IEEE 754 float. It is written as a
+/// static assertion rather than a throw-statement because 128-bit
+/// long long integers are not generally available, so it is not
+/// possible to test such logic today.
template<typename To, typename From>
#if 201402L < __cplusplus
@@ -116,11 +143,8 @@ inline To bourn_cast(From from, std::true_type,
std::false_type)
using to_traits = std::numeric_limits<To >;
using from_traits = std::numeric_limits<From>;
static_assert(to_traits::is_integer && !from_traits::is_integer, "");
+ static_assert(to_traits::digits < from_traits::max_exponent, "");
- // At least with i686-w64-mingw32-g++ version 4.9.1, this change:
- // - if(From(to_traits::max()) + 1 <= from)
- // + if(adj_max <= from)
- // fixes incorrect results with '-O0'.
static From const volatile raw_max = From(to_traits::max());
static From const volatile adj_max = raw_max + From(1);
- [lmi-commits] [lmi] master updated (ae5c2ad -> 204bd5f), Greg Chicares, 2017/04/13
- [lmi-commits] [lmi] master b68c82e 4/5: Replace implicit 2==radix assumption with explicit assertion, Greg Chicares, 2017/04/13
- [lmi-commits] [lmi] master 5a157a2 1/5: Rename variables: std::numeric_limits means traits, not just limits, Greg Chicares, 2017/04/13
- [lmi-commits] [lmi] master e64d190 3/5: Improve documentation, Greg Chicares, 2017/04/13
- [lmi-commits] [lmi] master 49c2d97 2/5: Improve documentation, Greg Chicares, 2017/04/13
- [lmi-commits] [lmi] master 204bd5f 5/5: Replace another assumption with a static assertion,
Greg Chicares <=