/*! \file FPEqual.h
\brief This file contains declaration and implementation of functions that check floating point numbers for equalty.
*/
/*
*
* website: http://www.coolsoft-sd.com/
* contact: support@coolsoft-sd.com
*
*/
/*
* Genetic Algorithm Library
* Copyright (C) 2007-2008 Coolsoft Software Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __FPEQUAL_H__
#define __FPEQUAL_H__
#include <stdlib.h>
#include "Platform.h"
/// <summary>This macro interprets <c>float</c> as <c>int</c> for easier bitwies access.</summary>
#define FLOAT_AS_INT(x) ( ( *(int*)&( x ) ) )
/// <summary>This macro interprets <c>double</c> as <c>long long</c> for easier bitwies access.</summary>
#define DOUBLE_AS_LONGLONG(x) ( ( *(long long*)&( x ) ) )
/// <summary>Extracts sign from single precision floating point number.</summary>
#define FLOAT_SIGN 0x80000000UL
/// <summary>Extracts sign from double precision floating point number.</summary>
#define DOUBLE_SIGN 0x8000000000000000ULL
/// <summary>Contains common classes, functions, datatypes and objects used by the library.</summary>
namespace Common
{
/// <summary>This method compares two single precision floating point numbers for equality with defined level of tolerance.</summary>
/// <param name="x">the first number</param>
/// <param name="y">the second number</param>
/// <param name="ulpTolerance">maximum difference between these two numbers in ULPs that is tolerated for almost equality. Default value is 10.</param>
/// <returns>Returns <c>true</c> if the two values are almost equal.</returns>
inline bool GACALL FloatsEqual(float x,
float y,
int ulpTolerance = 10)
{
// to avoid equality of small numbers with opposite signs
if( ( FLOAT_AS_INT( x ) & FLOAT_SIGN ) != ( FLOAT_AS_INT( y ) & FLOAT_SIGN ) )
return x == y;
// make x lexicographically ordered as a twos-complement
if( FLOAT_AS_INT( x ) < 0 )
FLOAT_AS_INT( x ) = 0x80000000 - FLOAT_AS_INT( x );
// make y lexicographically ordered as a twos-complement
if( FLOAT_AS_INT( y ) < 0 )
FLOAT_AS_INT( y ) = 0x80000000 - FLOAT_AS_INT( y );
// comparing x and y
return abs( FLOAT_AS_INT( x ) - FLOAT_AS_INT( y ) ) <= ulpTolerance;
}
/// <summary>This method compares two double precision floating point numbers for equality with defined level of tolerance.</summary>
/// <param name="x">the first number</param>
/// <param name="y">the second number</param>
/// <param name="ulpTolerance">maximum difference between these two numbers in ULPs that is tolerated for almost equality. Default value is 10.</param>
/// <returns>Returns <c>true</c> if the two values are almost equal.</returns>
inline bool GACALL DoublesEqual(double x,
double y,
int ulpTolerance = 10)
{
// to avoid equality of small numbers with opposite signs
if ( ( DOUBLE_AS_LONGLONG( x ) & DOUBLE_SIGN ) != ( DOUBLE_AS_LONGLONG( y ) & DOUBLE_SIGN ) )
return x == y;
// make x lexicographically ordered as a twos-complement
if( DOUBLE_AS_LONGLONG( x ) < 0 )
DOUBLE_AS_LONGLONG( x ) = 0x80000000 - DOUBLE_AS_LONGLONG( x );
// make y lexicographically ordered as a twos-complement
if( DOUBLE_AS_LONGLONG( y ) < 0 )
DOUBLE_AS_LONGLONG( y ) = 0x80000000 - DOUBLE_AS_LONGLONG( y );
// comparing x and y
long long r = DOUBLE_AS_LONGLONG( x ) - DOUBLE_AS_LONGLONG( y );
return ( r < 0 ? -r : r ) <= ulpTolerance;
}
} // Common
#endif // __FPEQUAL_H__