Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: fd0eaa11ed
Fetching contributors…

Cannot retrieve contributors at this time

112 lines (91 sloc) 3.652 kb
// const.cpp (basic comparison functions)
//
// The WorldForge Project
// Copyright (C) 2000, 2001, 2002 The WorldForge Project
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// For information about WorldForge and its authors, please contact
// the Worldforge Web Site at http://www.worldforge.org.
//
// Author: Ron Steinke
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <wfmath/const.h>
#include <cmath>
#include <cassert>
// Implementation of IsFloatEqual() is borrowed from Jesse Jones (thanks!).
// The comments also belong to him. The names have been changed
// to protect the innocent....
//
// Comparing floating point numbers for equality is tricky because
// the limited precision of the hardware introduces small errors
// so that two numbers that should compare equal don't. So what
// we do is consider the numbers equal if their difference is less
// than some epsilon value. But choosing this epsilon is also tricky
// because if the numbers are large epsilon should also be large,
// and if the numbers are very small the epsilon must be even smaller.
// To get around this we'll use a technique from Knuth's "Seminumerical
// Algorithms" section 4.2.2 and scale epsilon by the exponent of
// one of the specified numbers.
//
//---------------------------------------------------------------
namespace WFMath {
bool Equal(double x1, double x2, double epsilon)
{
// If the difference between the numbers is smaller than the
// scaled epsilon we'll consider the numbers to be equal.
return std::fabs(x1 - x2) <= _ScaleEpsilon(x1, x2, epsilon);
}
bool Equal(float x1, float x2, float epsilon)
{
// If the difference between the numbers is smaller than the
// scaled epsilon we'll consider the numbers to be equal.
return std::fabs(x1 - x2) <= _ScaleEpsilon(x1, x2, epsilon);
}
double _ScaleEpsilon(double x1, double x2, double epsilon)
{
// Get the exponent of the smaller of the two numbers (using the
// smaller of the two gives us a tighter epsilon value).
int exponent;
(void) std::frexp(std::fabs(x1) < std::fabs(x2) ? x1 : x2, &exponent);
// Scale epsilon by the exponent.
return std::ldexp(epsilon, exponent);
}
float _ScaleEpsilon(float x1, float x2, float epsilon)
{
// Get the exponent of the smaller of the two numbers (using the
// smaller of the two gives us a tighter epsilon value).
int exponent;
(void) std::frexp(std::fabs(x1) < std::fabs(x2) ? x1 : x2, &exponent);
// Scale epsilon by the exponent.
return std::ldexp(epsilon, exponent);
}
CoordType _ScaleEpsilon(const CoordType* x1, const CoordType* x2,
int length, CoordType epsilon)
{
assert(length > 0);
float max1 = 0, max2 = 0;
for(int i = 0; i < length; ++i) {
float val1 = std::fabs(x1[i]), val2 = std::fabs(x2[i]);
if(val1 > max1)
max1 = val1;
if(val2 > max2)
max2 = val2;
}
return _ScaleEpsilon(max1, max2, epsilon);
}
}
Jump to Line
Something went wrong with that request. Please try again.