|
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