lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 8cbc3001 07/11: Make a value definitely exact


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 8cbc3001 07/11: Make a value definitely exact and definitely constexpr
Date: Tue, 31 May 2022 17:52:05 -0400 (EDT)

branch: master
commit 8cbc300103e2e301e7a016dbf9715c007fb866a8
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Make a value definitely exact and definitely constexpr
    
    Augmented the unit test to demonstrate that the values are correct,
    using hexadecimal floating literals to express touchstone values
    rather than integer literals: mixed-mode comparisons may appear to
    succeed even if only as an artifact of inexact conversions.
---
 bin_exp_test.cpp | 16 ++++++++++++++--
 tn_range.tpp     | 19 +++++--------------
 2 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/bin_exp_test.cpp b/bin_exp_test.cpp
index 9c90e259..b18f7b2c 100644
--- a/bin_exp_test.cpp
+++ b/bin_exp_test.cpp
@@ -264,6 +264,7 @@ void test_quodlibet()
     LMI_TEST_EQUAL(1748.2195908183271, bin_exp(12.04662322998046875, 3));
 
     // Compare bin_exp() to std::pow().
+
     double a0 = bin_exp
         (static_cast<double>(std::numeric_limits<double>::radix)
         ,                    std::numeric_limits<double>::digits
@@ -272,8 +273,19 @@ void test_quodlibet()
         (static_cast<double>(std::numeric_limits<double>::radix)
         ,static_cast<double>(std::numeric_limits<double>::digits)
         );
-    LMI_TEST_EQUAL(9007199254740992, a0);
-    LMI_TEST_EQUAL(9007199254740992, a1);
+    LMI_TEST_EQUAL(0x1p53, a0);
+    LMI_TEST_EQUAL(0x1p53, a1);
+
+    long double b0 = bin_exp
+        (static_cast<long double>(std::numeric_limits<long double>::radix)
+        ,                         std::numeric_limits<long double>::digits
+        );
+    long double b1 = std::pow
+        (static_cast<long double>(std::numeric_limits<long double>::radix)
+        ,static_cast<long double>(std::numeric_limits<long double>::digits)
+        );
+    LMI_TEST_EQUAL(0x1p64L, b0);
+    LMI_TEST_EQUAL(0x1p64L, b1);
 }
 
 void mete0()
diff --git a/tn_range.tpp b/tn_range.tpp
index fae1aab7..8495223d 100644
--- a/tn_range.tpp
+++ b/tn_range.tpp
@@ -22,17 +22,18 @@
 #include "tn_range.hpp"
 
 #include "alert.hpp"
+#include "bin_exp.hpp"
 #include "math_functions.hpp"           // signum()
 #include "unwind.hpp"                   // scoped_unwind_toggler
 #include "value_cast.hpp"
 
-#include <cmath>                        // pow(), signbit()
 #include <exception>
 #include <istream>
 #include <limits>
 #include <ostream>
 #include <sstream>
-#include <type_traits>
+#include <type_traits>                  // is_floating_point_v()
+#include <typeinfo>                     // type_info
 
 namespace
 {
@@ -44,7 +45,7 @@ namespace
     ///    [0.0, 1.7976931348623157E+308] // IEC 60559 double.
     ///    [0, 32767] // Minimum INT_MAX that C99 E.1 allows.
     /// because they are not likely to recognize those maximum values
-    /// as such. Any value of a type for which std::numeric_traits is
+    /// as such. Any value of a type for which std::numeric_limits is
     /// not specialized is treated as lying strictly between extrema
     /// for this purpose, because that generally yields an appropriate
     /// outcome, though of course a different behavior can be obtained
@@ -187,17 +188,7 @@ namespace
         static_assert(std::numeric_limits<T>::is_iec559);
         bool operator()(T t)
             {
-            // Here, nonstd::power() isn't preferable to pow(). This
-            // value needn't be exact, because no end user will enter
-            // a value exactly equal to 2^53 (e.g.). Furthermore, all
-            // releases compiled with gcc are optimized, so gcc should
-            // perform this constant calculation at compile time.
-            // Thus, the historical untrustworthiness of MinGW-w64's
-            // pow(), e.g.:
-            //    pow(10.0, 5.0) != 100000.0
-            //    pow(2.0, 0.5) != sqrt(2.0)
-            // shouldn't matter.
-            static T const z0 = std::pow
+            constexpr T z0 = bin_exp
                 (static_cast<T>(std::numeric_limits<T>::radix)
                 ,static_cast<T>(std::numeric_limits<T>::digits)
                 );



reply via email to

[Prev in Thread] Current Thread [Next in Thread]