[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().