Gaudi Framework, version v21r7

Home   Generated: 22 Jan 2010

Gaudi::Math Namespace Reference


Classes

class  Lomont< float >
 the specialization for float numbers More...
class  Lomont< double >
 the specialization for double numbers More...

Functions

GAUDI_API bool lomont_compare_float (const float af, const float bf, const unsigned short maxULPs)
 equality comparison of float numbers using as the metric the maximal number of Units in the Last Place (ULP).
GAUDI_API bool lomont_compare_double (const double af, const double bf, const unsigned int maxULPs)
 equality comparison of double numbers using as the metric the maximal number of Units in the Last Place (ULP).
GAUDI_API float next_float (const float af, const short ulps)
 Get the floating number that representation is different with respect to the argument for the certain number of "Units in the Last Position".
GAUDI_API double next_double (const double af, const short ulps)
 Get the floating number that representation is different with respect to the argument for the certain number of "Units in the Last Position".


Function Documentation

bool Gaudi::Math::lomont_compare_double ( const double  af,
const double  bf,
const unsigned int  maxULPs 
)

equality comparison of double numbers using as the metric the maximal number of Units in the Last Place (ULP).

It is a slightly modified version of very efficient implementation of the initial Bruce Dawson's algorithm by Chris Lomont.

See also:
www.lomont.org

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

C.Lomont claims the algorithm is factor 2-10 more efficient with respect to classical Knuth's algorithm for comparison of the floating number using the relative precision.

The effective relative difference depends on the choice of maxULPS:

  • For the case of maxULPs=1, (of course it is totally unphysical case!!!) the effective relative precision r = |a-b|/(|a|+|b|)is ~6e-16 for |a|,|b|>1.e-304, and then it quickly goes to ~1

  const double a = ... ;
  const double b = ... ;

  const bool equal = Gaudi::Math::lomont_compare_double ( a , b ) ;

Parameters:
af the first number
bf the second number
maxULPs the maximal metric deviation in the terms of maximal number of units in the last place
Author:
Vanya BELYAEV Ivan.Belyaev@nikhef.nl
Date:
2008-11-08

the final check

Definition at line 291 of file Lomont.cpp.

00294 {
00295   // ==========================================================================
00297   BOOST_STATIC_ASSERT( std::numeric_limits<double>  ::is_specialized &&
00298                        std::numeric_limits<Long>    ::is_specialized && 
00299                        std::numeric_limits<ULong>   ::is_specialized &&
00300                        boost::integer_traits<ULong> ::is_specialized &&
00301                        boost::integer_traits<Long>  ::is_specialized &&
00302                        sizeof(double)==sizeof(Long)                  && 
00303                        sizeof(double)==sizeof(ULong)                 &&
00304                        64 == std::numeric_limits<ULong>::digits      ) ;
00305   // ==========================================================================
00306   Cast_D caster ;
00307   
00308   //Long ai = *reinterpret_cast<const Long*>( &af ) ;
00309   //Long bi = *reinterpret_cast<const Long*>( &bf ) ;
00310   Long ai = caster.d2l ( af ) ;
00311   Long bi = caster.d2l ( bf ) ;
00312   
00313   Long test = (((ULong)(ai^bi))>>63)-1;
00314   
00315   // assert ( (0==test) || ( boost::integer_traits<ULong>::const_max == test ) ) ;
00316   
00317   Long diff = ((( boost::integer_traits<Long>::const_min - ai ) & (~test)) | ( ai& test )) - bi ;
00318   
00319   Long maxDiff_ = maxULPs ;
00320   
00321   Long v1 = maxDiff_ + diff ;
00322   Long v2 = maxDiff_ - diff ;
00323   
00324   return 0<=(v1|v2) ;
00325 }

bool Gaudi::Math::lomont_compare_float ( const float  af,
const float  bf,
const unsigned short  maxULPs 
)

equality comparison of float numbers using as the metric the maximal number of Units in the Last Place (ULP).

It is a slightly modified version of very efficient implementation of the initial Bruce Dawson's algorithm by Chris Lomont.

See also:
www.lomont.org

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

C.Lomont claims the algorithm is factor 2-10 more efficient with respect to classical Knuth's algorithm for comparison of the floating number using the relative precision.

The effective relative difference depends on the choice of maxULPS:

  • For the case of maxULPs=1, (of course it is totally unphysical case!!!) the effective relative precision r = |a-b|/(|a|+|b|)is between 3.5e-8 and 5.5e-8 for |a|,|b|>1.e-37, and then it quickly goes to ~1
  • For the case of maxULPS=10 the effective relative precision is between 3e-8 and 6e-7 for |a|,|b|>1.e-37, and then it quickly goes to ~1
  • For the case of maxULPS=100 the effective relative precision is around ~6e-6 for |a|,|b|>1.e-37, and then it quickly goes to ~1
  • For the case of maxULPS=1000 the effective relative precision is around ~6e-5 for |a|,|b|>1.e-37, and then it quickly goes to ~1

  const float a = ... ;
  const float b = ... ;

  const bool equal = Gaudi::Math::lomont_compare_float ( a , b ) ;

Parameters:
af the first number
bf the second number
maxULPs the maximal metric deviation in the terms of maximal number of units in the last place
Author:
Vanya BELYAEV Ivan.Belyaev@nikhef.nl
Date:
2008-11-08

Definition at line 195 of file Lomont.cpp.

00198 {
00199   // ==========================================================================
00200   // prerequisites:
00201   BOOST_STATIC_ASSERT( std::numeric_limits<float>          ::is_specialized &&
00202                        boost::integer_traits<int>          ::is_specialized && 
00203                        boost::integer_traits<unsigned int> ::is_specialized &&
00204                        sizeof(float)==sizeof(int)                           && 
00205                        sizeof(float)==sizeof(unsigned int)                  &&
00206                        32 == boost::integer_traits<unsigned int>::digits    ) ;
00207   // ==========================================================================
00208   
00209   Cast_F caster ;
00210   
00211   //int ai = *reinterpret_cast<const int*>( &af ) ;
00212   //int bi = *reinterpret_cast<const int*>( &bf ) ;
00213   int ai = caster.f2i ( af ) ;
00214   int bi = caster.f2i ( bf ) ;
00215   
00216   int test = (((unsigned int)(ai^bi))>>31)-1;
00217   
00218   // assert ( (0==test) || ( boost::integer_traits<unsigned int>::const_max == test ) ) ;
00219   
00220   int diff = ((( boost::integer_traits<int>::const_min - ai ) & (~test)) | ( ai& test )) - bi ;
00221   
00222   int maxDiff_ = maxULPs ;
00223   
00224   int v1 = maxDiff_ + diff ;
00225   int v2 = maxDiff_ - diff ;
00226   
00227   return 0<=(v1|v2) ;
00228 }

double Gaudi::Math::next_double ( const double  af,
const short  ulps 
)

Get the floating number that representation is different with respect to the argument for the certain number of "Units in the Last Position".

For ulps=1, it is just next float number, for ulps=-1 is is the previous one.

This routine is very convenient to test the parameter maxULPS for the routine Gaudi::Math::lomont_compare_double

See also:
Gaudi::Math::lomont_compare_double
Parameters:
af the reference number
ulps the bias
Returns:
the biased float number (on distance "ulps")
Author:
Vanya BELYAEV Ivan.Belyaev@nikhef.nl
Date:
2008-11-08

the final check

Definition at line 344 of file Lomont.cpp.

00345 {
00346   // ==========================================================================
00348   BOOST_STATIC_ASSERT( std::numeric_limits<double> ::is_specialized &&
00349                        std::numeric_limits<Long>   ::is_specialized && 
00350                        sizeof(double)==sizeof(Long) ) ;
00351   // ==========================================================================
00352   Cast_D caster ;
00353   
00354   //Long al = *reinterpret_cast<const Long*>( &ad ) ;
00355   Long al = caster.d2l ( ad ) ;
00356   al += ulps ;
00357   //return *reinterpret_cast<double*>(&al) ;
00358   return caster.l2d ( al ) ;
00359 }

float Gaudi::Math::next_float ( const float  af,
const short  ulps 
)

Get the floating number that representation is different with respect to the argument for the certain number of "Units in the Last Position".

For ulps=1, it is just next float number, for ulps=-1 is is the previous one.

This routine is very convenient to test the parameter maxULPS for the routine Gaudi::Math::lomont_compare_float

See also:
Gaudi:Math::lomont_compare_float
Parameters:
af the reference number
ulps the bias
Returns:
the biased float number (on distance "ulps")
Author:
Vanya BELYAEV Ivan.Belyaev@nikhef.nl
Date:
2008-11-08

the final check

Definition at line 247 of file Lomont.cpp.

00248 {
00250   BOOST_STATIC_ASSERT( std::numeric_limits<float> ::is_specialized &&
00251                        std::numeric_limits<int>   ::is_specialized && 
00252                        sizeof(float)==sizeof(int) ) ;
00253   // ==========================================================================
00254   Cast_F caster ;
00255   
00256   // int ai = *reinterpret_cast<const int*>( &af ) ;
00257   int ai = caster.f2i ( af ) ;
00258   ai += ulps ;
00259   // return *reinterpret_cast<float*>(&ai) ;
00260   return   caster.i2f ( ai ) ;
00261 }


Generated at Fri Jan 22 20:44:28 2010 for Gaudi Framework, version v21r7 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004