# itkMath FloatAlmostEqual question

It looks like FloatAlmostEqual function (itkMath.h) does rather similar thing twice, in particular if floats are not almost equal - subtract, abs, compare (first to epsilon, then unit of least precision), isn’t it? It is not wrong, but may be it could impact performance?

FloatAlmostEqual

I think this is intended. A pair of floating point numbers could have a large absolute difference, and still be considered “almost equal”:

``````EXPECT_TRUE(
itk::Math::FloatAlmostEqual(
1.7976931348623158e+308, // <== Which is DBL_MAX.
1.7976931348623156e+308  // <== Mind the last decimal digit!
));
``````

In this case, the absolute difference is ~2.0e+292, while these two numbers only differ by one unit of least precision (ULP).

On the other hand, a pair of floating point numbers could have a large absolute ULP difference, and still be considered “almost equal”:

``````EXPECT_TRUE(
itk::Math::FloatAlmostEqual(
2.2250738585072014e-308, // <== Which is DBL_MIN.
0.0
));
``````

My debugger tells me that DBL_MIN is 4503599627370496 ULPs apart from 0.0, yet these numbers could be considered almost equal, right?

That’s possible, of course. But do you have a specific application or image filter in mind, whose performance could be affected by this function?

2 Likes

Thank you for explanation.

But do you have a specific application or image filter in mind, whose performance could be affected by this function?

``````./Modules/Numerics/Statistics/include/itkHistogramToTextureFeaturesFilter.hxx:  if( Math::FloatAlmostEqual( pixelVarianceSquared, 0.0, 4, 2*NumericTraits<double>::epsilon() ) )
./Modules/Filtering/Thresholding/include/itkOtsuMultipleThresholdsCalculator.hxx:         !Math::FloatAlmostEqual( maxVarBetween, varBetween, maxUlps) )
./Modules/Filtering/ImageFrequency/include/itkFrequencyBandImageFilter.hxx:    if ( Math::FloatAlmostEqual(scalarFrequency, this->m_LowFrequencyThreshold) )
./Modules/Filtering/ImageFrequency/include/itkFrequencyBandImageFilter.hxx:    if ( Math::FloatAlmostEqual(scalarFrequency, this->m_HighFrequencyThreshold) )
./Modules/Filtering/Path/include/itkPolyLineParametricPath.hxx:  if ( input > endPoint || itk::Math::FloatAlmostEqual( input, endPoint ) )
./Modules/Filtering/FastMarching/include/itkFastMarchingImageFilterBase.hxx:    if (itk::Math::FloatAlmostEqual<double>(cc, 0.0))
./Modules/Core/Common/include/itkVersor.hxx:  if ( Math::FloatAlmostEqual<T>(vectorNorm, 0.0) )
./Modules/Core/Transform/include/itkBSplineTransform.hxx:    if( Math::FloatAlmostEqual( index[j], maxLimit, 4 ) )
./Modules/Core/Transform/include/itkVersorRigid3DTransform.hxx:  if (Math::FloatAlmostEqual<TParametersValueType>(norm, 0.0))
``````

Edit: removed calls from tests

1 Like

Interesting. I think you’re right: it seems to me that in some of these cases, the performance could be improved by doing something else than calling the current `FloatAlmostEqual` function. For example, instead of `FloatAlmostEqual(x, 0.0)`, I think I would prefer something like `abs(x) < DBL_MIN`. But I haven’t had a close look yet at these particular cases.

1 Like

You are right, in some cases `FloatAlmostEqual` could be replaced by less general `std::abs(x)<epsilon`. But as that case is checked first in `FloatAlmostEqual`, and it should be in the predicted branch, the extra code in `FloatAlmostEqual` should not matter. Of course, to test this assumption a change should be made and performance compared with and without the change.

2 Likes