[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master eab8e30 4/6: Improve signum()
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master eab8e30 4/6: Improve signum() |
Date: |
Sun, 30 Apr 2017 11:49:36 -0400 (EDT) |
branch: master
commit eab8e30c218ab3f23598cd85f3cefbf88193b1a5
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>
Improve signum()
Notably, C++11 makes it possible to examine the sign of a NaN portably.
---
tn_range.tpp | 38 ++++++++------------------------------
tn_range_test.cpp | 4 ++--
2 files changed, 10 insertions(+), 32 deletions(-)
diff --git a/tn_range.tpp b/tn_range.tpp
index 4d29e56..50954d5 100644
--- a/tn_range.tpp
+++ b/tn_range.tpp
@@ -24,7 +24,7 @@
#include "alert.hpp"
#include "value_cast.hpp"
-#include <cmath> // std::pow()
+#include <cmath> // std::pow(), std::signbit()
#include <exception>
#include <istream>
#include <limits>
@@ -99,29 +99,17 @@ namespace
return strictly_between_extrema_tester<T>()(t);
}
- /// Signum, defined here to return 0 for NaNs.
+ /// Algebraic sign of argument.
///
- /// To handle unsigned types without warnings, the value zero is
- /// stored in a volatile variable, and the value negative one is
- /// cast to the argument type.
+ /// Return value is of same type as argument, as for many members
+ /// of std::numeric_limits. Thus, (t * signum(t)) is of type T,
+ /// which would not always be the case if an int were returned.
template<typename T>
T signum(T t)
{
static_assert(std::is_arithmetic<T>::value, "");
- T volatile zero = 0;
- if(t < zero)
- {
- return static_cast<T>(-1);
- }
- else if(0 < t)
- {
- return 1;
- }
- else
- {
- return 0;
- }
+ return (0 == t) ? 0 : std::signbit(t) ? -1 : 1;
}
/// Exact-integer determination for floating types.
@@ -236,23 +224,13 @@ namespace
{
return t;
}
-
- // The return values computed here are cast to T because, for
- // instance, if T is signed char, then an integral promotion
- // would be performed--even though these calculations are
- // actually reachable only for floating-point types. This
- // workaround is more compact than specializing the template.
else if(t < direction)
{
- return static_cast<T>
- (t * (1 + signum(t) * std::numeric_limits<T>::epsilon())
- );
+ return t * (T(1) + signum(t) * std::numeric_limits<T>::epsilon());
}
else if(direction < t)
{
- return static_cast<T>
- (t * (1 - signum(t) * std::numeric_limits<T>::epsilon())
- );
+ return t * (T(1) - signum(t) * std::numeric_limits<T>::epsilon());
}
else
{
diff --git a/tn_range_test.cpp b/tn_range_test.cpp
index 5ab39ab..c4e85ea 100644
--- a/tn_range_test.cpp
+++ b/tn_range_test.cpp
@@ -171,8 +171,8 @@ void tn_range_test::test_auxiliary_functions(char const*
file, int line)
if(is_iec559 && has_quiet_NaN)
{
T const qnanT = std::numeric_limits<T>::quiet_NaN();
- INVOKE_BOOST_TEST_EQUAL( 0, signum(-qnanT), file, line);
- INVOKE_BOOST_TEST_EQUAL( 0, signum( qnanT), file, line);
+ INVOKE_BOOST_TEST_EQUAL(-1, signum(-qnanT), file, line);
+ INVOKE_BOOST_TEST_EQUAL( 1, signum( qnanT), file, line);
}
}
- [lmi-commits] [lmi] master updated (f306a7d -> 2cbcddd), Greg Chicares, 2017/04/30
- [lmi-commits] [lmi] master 2faa024 5/6: Test auxiliary functions with an unsigned type too, Greg Chicares, 2017/04/30
- [lmi-commits] [lmi] master eab8e30 4/6: Improve signum(),
Greg Chicares <=
- [lmi-commits] [lmi] master 1484727 1/6: Remove emulation of std::isnan(), Greg Chicares, 2017/04/30
- [lmi-commits] [lmi] master eb921be 3/6: Fix peccable unit tests, Greg Chicares, 2017/04/30
- [lmi-commits] [lmi] master 2cbcddd 6/6: Test auxiliary functions with type bool too, Greg Chicares, 2017/04/30
- [lmi-commits] [lmi] master 3718824 2/6: Improve interest-conversion example, Greg Chicares, 2017/04/30