Boost logo

Boost :

From: Paul A Bristow (pbristow_at_[hidden])
Date: 2005-11-17 13:12:33


| -----Original Message-----
| From: boost-bounces_at_[hidden]
| [mailto:boost-bounces_at_[hidden]] On Behalf Of John Maddock
| Sent: 12 November 2005 17:16
| To: boost_at_[hidden]
| Subject: Re: [boost] [Test] BOOST_CHECK_CLOSE Feature request
|
| > comparing IEEE floats at
| http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
| >
| > This makes use of the property that IEEE floating point formats are
| > lexicographically ordered when reinterpreted as an appropriate length
| > signed integer. It appears you can use this to define a closeness
| > measure based on how many units in the last place the two numbers
| > differ by (equivalently, if you enumerated all possible floats and
| > counted how far
| > away one number is from the other in the enumeration). I only just
| > came across it now so I havn't tried playing with it yet, but it
| > looks like it would make a useful closeness measure.

I HAVE been playing with it, briefly,
and seems to work as expected for MS 8.0
using int for float (or should that be __int32?)
using __int64 type for double
 (and of course long double since it is the same).

        double a = 1.2;
        double b = 1.199999999999999;
        __int64 aInt64 = *(__int64*)&a; // float as 64-bit integer.
        __int64 bInt64 = *(__int64*)&b;
        cout << "a = " << a << " " << hex << aInt64 << endl;
        cout << "b = " << b << " " << hex << bInt64 << endl;
        __int64 d = aInt64 - bInt64;
        cout << "diff = " << hex << d << endl;

a = 1.2 3ff3333333333333
b = 1.2 3ff333333333332f
diff = 4

bool AlmostEqual2sComplement(double A, double B, int maxUlps);

cout << boolalpha << AlmostEqual2sComplement(a, b, 2) << endl;

outputs false, as expected because difference is 4.

But of course, this is the simple case of 64-bit double.
No doubt other exotic types can also be compared similarly with some bit
twiddling,
assuming we can select the right int to match the floating-point type.
If int is 64-bit and float is only 32 should still work?

But for now perhaps we can test and if not implemented then just give up:

        // Check is IEEE 754 - but really want a macro.
        if (!numeric_limits<double>::is_iec559)
        { // Code below is unsuitable.
                cout << "is NOT IEC559!" << endl;
                return -1;
        }

and of course, this doesn't work C1017: invalid integer constant expression
#if (!numeric_limits<double>::is_iec559)
# pragma error ("NOT IEC559!")
#endif

#if ((DBL_MANT_DIG == 53) && (DBL_RADIX == 2) && (DBL_MAX_EXP == 1024))
# pragma message ("Is very probably IEC559.")
// Want to give up here with pragma error, or something?
#endif

But I don't know if any of this takes account of (wrong-)endianness.
For example, VAX layout is different?

Boost test doesn't seem to rely on floating-point layout?

Any experts on this, either on an IS_IEEE macro, or endianness?

Paul

-- 
Paul A Bristow
Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB
Phone and SMS text +44 1539 561830, Mobile and SMS text +44 7714 330204
mailto: pbristow_at_[hidden]  www.hetp.u-net.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk