/cvmfs/atlas.cern.ch/repo/sw/ASG/AnalysisBase/2.4.28/CxxUtils/CxxUtils/fpcompare.h File Reference

Workaround x86 precision issues for FP inequality comparisons. More...

#include <cmath>
#include <functional>

Go to the source code of this file.

Classes

struct  CxxUtils::fpcompare_fn::equal
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::equalf
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::greater
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::greaterf
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::less
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::lessf
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::greater_equal
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::greater_equalf
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::less_equal
 Compare two FP numbers, working around x87 precision issues. More...
struct  CxxUtils::fpcompare_fn::less_equalf
 Compare two FP numbers, working around x87 precision issues. More...

Namespaces

namespace  CxxUtils
 

Copy the elements of a sequence for which a predicate is true.


Functions

bool CxxUtils::fpcompare::equal (double a, double b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::equal (float a, float b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::greater (double a, double b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::greater (float a, float b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::less (double a, double b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::less (float a, float b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::greater_equal (double a, double b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::greater_equal (float a, float b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::less_equal (double a, double b)
 Compare two FP numbers, working around x87 precision issues.
bool CxxUtils::fpcompare::less_equal (float a, float b)
 Compare two FP numbers, working around x87 precision issues.

Detailed Description

Workaround x86 precision issues for FP inequality comparisons.

Author:
scott snyder
Date:
Sep 2008 The functions contained here can be used to work around one of the effects of the brain-damage of the x87 FPU.

Brief summary: If you're writing a comparison function for sort, where the comparison depends on computed floating-point values, eg:

    bool compare (IParticle* a, IParticle* b)
    { return a->pt() > b->pt(); }

then you should replace the comparison with a call to one of the functions in this file:

    bool compare (IParticle* a, IParticle* b)
    { return CxxUtils::fpcompare::greater (a->pt(), b->pt()); }

Longer explanation:

An expression like this (where pt() returns a double):

    a->pt() > b->pt()

is compiled (on x86) into a sequence like this:

call a->pt() save result from FPU to a double stack temporary call b->pt() load the temporary back into the FPU do the comparison

If pt() returns a result with the extra precision bits used (so that the value changes when rounded to a double), then it is possible for this comparison to return true for the case where a==b. This violates the assumptions that std::sort makes of the comparison function, and can cause a crash (possibly even silently wrong results!).

As a fix, we force both parameters into something that has been declared volatile. That forces them to be spilled to memory, ensuring that they are both correctly rounded for the declared data type. The comparison is then done on these rounded values.

We condition this on the parameter __FLT_EVAL_METHOD__ being 2. This is defined in the C standard; a value of 2 means that all FP calculations are done as long double. For other cases, we leave out the volatile qualifiers; this should result in the functions being inlined completely away.

In addition to the free functions in the CxxUtils::fpcompare namespace. we define corresponding functionals in the CxxUtils::fpcompare_fn namespace.

It's also worth pointing out that exactly the same issue arises if one uses a floating-point value as the key for a STL associative container. In that case, this comparison instability may cause the container to become corrupted. While it's probably best to avoid using floats for associative container keys in the first place, if you do have to do that, you can work around this problem by using one of the above functionals as the container's comparison type.

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 15 Apr 2017 for RootCore Packages by  doxygen 1.6.1