Substitution proposal

I propose to swap the current function juce::approximatelyEqual()

with:

template<std::floating_point value_t> [[nodiscard]]
constexpr bool is_float_equal(value_t l, value_t r)
{
    return r == std::nextafter(l, r);
}

a beautiful answer by Ilmari Karonen in this question

In my tests, it covers more cases than the juce function, especially when big ranges are involved (which is exactly why I had to search for an alternative in first place).

2 Likes

Does it work with SIMDRegister - the current approximatelyEqual has broken SmoothedValue for SIMD variables :frowning:

I wouldn’t know because I haven’t tested with SIMDRegister and I use my own value smoother class… In the case it doesn’t work, I reckon an SFINAE approach using enable_if or in the case of C++20, concepts, would allow you to specialize the function for those.

1 Like

I’ve also been looking into this. I’ve put together a fairly decent number of tests for the function.

Although I do love the simplicity of that particular implementation I’ve just run it through my tests and it does fall short on at least two of them.

Comparing subnormal values to zero

I think having the default behaviour be that all subnormal values compare true to zero seems like a sensible idea IMO

constexpr auto min = std::numeric_limits<double>::min();
approximatelyEqual (0.0, std::nextafter (min, 0.0)); // should be true

Only infinity is equal to infinity

This implementation means std::numeric_limits<value_t>::max() will compare true to infinity which is unexpected IMO

constexpr auto max = std::numeric_limits<double>::max();
constexpr auto infinity = std::numeric_limits<double>::infinity();
approximatelyEqual (max, infinity); // should be false


At the moment what I’ve implemented on an internal branch is a version that takes a tolerance object which can be constructed with a relative and/or absolute tolerance, that being said I’ve designed it such that in the future if we wanted another tolerance type we could, so something like this could be achieved with it.

1 Like