lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master facecf4 3/3: Prefer std::midpoint() to calcul


From: Greg Chicares
Subject: [lmi-commits] [lmi] master facecf4 3/3: Prefer std::midpoint() to calculating a mean
Date: Tue, 13 Jul 2021 22:10:49 -0400 (EDT)

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

    Prefer std::midpoint() to calculating a mean
---
 math_functions.hpp      | 25 +++++++------------------
 math_functions_test.cpp | 15 ++++++++-------
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/math_functions.hpp b/math_functions.hpp
index 7e0f416..f6559ef 100644
--- a/math_functions.hpp
+++ b/math_functions.hpp
@@ -27,7 +27,7 @@
 #include <algorithm>                    // max(), min(), transform()
 #include <cmath>                        // expm1l(), log1pl(), signbit()
 #include <limits>
-#include <numeric>                      // partial_sum()
+#include <numeric>                      // midpoint(), partial_sum()
 #include <stdexcept>
 #include <type_traits>                  // /is_.*_v/
 #include <vector>
@@ -57,20 +57,9 @@ std::vector<T>& back_sum(std::vector<T>& v)
 // std::binary_function would have provided, because they're still
 // required for std::binder1st() or std::binder2nd(), or for PETE.
 
-/// Arithmetic mean.
-///
-/// Calculate mean as
-///   (half of x) plus (half of y)
-/// instead of
-///   half of (x plus y)
-/// because the addition in the latter can overflow. Generally,
-/// hardware deals better with underflow than with overflow.
-///
-/// The domain is restricted to floating point because integers would
-/// give surprising results. For instance, the integer mean of one and
-/// two would be truncated to one upon either returning an integer or
-/// assigning the result to one. Returning a long double in all cases
-/// is the best that could be done, but that seems unnatural.
+namespace detail
+{
+/// Arithmetic mean; used only by assign_midpoint().
 
 template<typename T>
 struct mean
@@ -78,10 +67,10 @@ struct mean
     using first_argument_type  = T;
     using second_argument_type = T;
     using result_type          = T;
-    static_assert(std::is_floating_point_v<T>);
     T operator()(T const& x, T const& y) const
-        {return 0.5 * x + 0.5 * y;}
+        {return std::midpoint(x, y);}
 };
+} // namespace detail
 
 /// Divide integers, rounding away from zero.
 ///
@@ -366,7 +355,7 @@ void assign_midpoint
         ,in_0.end()
         ,in_1.begin()
         ,out.begin()
-        ,mean<double>()
+        ,detail::mean<double>()
         );
 }
 
diff --git a/math_functions_test.cpp b/math_functions_test.cpp
index dc5c440..634d7f8 100644
--- a/math_functions_test.cpp
+++ b/math_functions_test.cpp
@@ -333,15 +333,16 @@ int test_main(int, char*[])
     long double smallnumL = std::numeric_limits<long double>::min();
     long double bignumL   = std::numeric_limits<long double>::max();
 
-    // Test mean<>().
+    // Test detail::mean<>(). This is pointless as long as
+    // std::midpoint() is correctly implemented.
 
-    LMI_TEST_EQUAL(1.5, mean<double>()(1.0, 2.0));
-    LMI_TEST_EQUAL(smallnumD, mean<double>()(smallnumD, smallnumD));
-    LMI_TEST_EQUAL(bignumD  , mean<double>()(bignumD  , bignumD  ));
+    LMI_TEST_EQUAL(1.5, detail::mean<double>()(1.0, 2.0));
+    LMI_TEST_EQUAL(smallnumD, detail::mean<double>()(smallnumD, smallnumD));
+    LMI_TEST_EQUAL(bignumD  , detail::mean<double>()(bignumD  , bignumD  ));
 
-    LMI_TEST_EQUAL(1.5, mean<long double>()(1.0, 2.0));
-    LMI_TEST_EQUAL(smallnumL, mean<long double>()(smallnumL, smallnumL));
-    LMI_TEST_EQUAL(bignumL  , mean<long double>()(bignumL  , bignumL  ));
+    LMI_TEST_EQUAL(1.5, detail::mean<long double>()(1.0, 2.0));
+    LMI_TEST_EQUAL(smallnumL, detail::mean<long 
double>()(smallnumL,smallnumL));
+    LMI_TEST_EQUAL(bignumL  , detail::mean<long double>()(bignumL  ,bignumL  
));
 
     // Test outward_quotient().
 



reply via email to

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