Skip to content

Commit 9a6237d

Browse files
committed
Add specialized float distance for type float
1 parent 773ec29 commit 9a6237d

File tree

1 file changed

+31
-0
lines changed
  • include/boost/math/special_functions

1 file changed

+31
-0
lines changed

include/boost/math/special_functions/next.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <boost/math/tools/traits.hpp>
1919
#include <type_traits>
2020
#include <cfloat>
21+
#include <cstdint>
2122

2223

2324
#if !defined(_CRAYC) && !defined(__CUDACC__) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)))
@@ -717,6 +718,36 @@ typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
717718
return boost::math::float_distance(a, b, policies::policy<>());
718719
}
719720

721+
// https://randomascii.wordpress.com/2012/01/23/stupid-float-tricks-2/
722+
inline std::int32_t float_distance(float a, float b)
723+
{
724+
using std::abs;
725+
constexpr float tol = 2 * (std::numeric_limits<float>::min)();
726+
727+
// 0, very small, and large magnitude distances all need special handling
728+
if (abs(a) == 0 || abs(b) == 0)
729+
{
730+
return static_cast<std::int32_t>(float_distance(a, b, policies::policy<>()));
731+
}
732+
else if (abs(a) < tol || abs(b) < tol)
733+
{
734+
return static_cast<std::int32_t>(float_distance(a, b, policies::policy<>()));
735+
}
736+
737+
static_assert(sizeof(float) == sizeof(std::int32_t), "float is incorrect size.");
738+
739+
const auto ai = *reinterpret_cast<std::int32_t*>(&a);
740+
const auto bi = *reinterpret_cast<std::int32_t*>(&b);
741+
auto result = bi - ai;
742+
743+
if (ai < 0 || bi < 0)
744+
{
745+
result = -result;
746+
}
747+
748+
return result;
749+
}
750+
720751
namespace detail{
721752

722753
template <class T, class Policy>

0 commit comments

Comments
 (0)