Atlas 0.7.0
Networking protocol for the Worldforge system.
float.cpp
1// float.cpp (basic comparison functions copied from WFMath const.cpp)
2//
3// The WorldForge Project
4// Copyright (C) 2000, 2001, 2002 The WorldForge Project
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19//
20// For information about WorldForge and its authors, please contact
21// the Worldforge Web Site at http://www.worldforge.org.
22//
23
24// Author: Ron Steinke
25
26#include "float.h"
27
28#include <cmath>
29
30
31// Implementation of IsFloatEqual() is borrowed from Jesse Jones (thanks!).
32// The comments also belong to him. The names have been changed
33// to protect the innocent....
34//
35// Comparing floating point numbers for equality is tricky because
36// the limited precision of the hardware introduces small errors
37// so that two numbers that should compare equal don't. So what
38// we do is consider the numbers equal if their difference is less
39// than some epsilon value. But choosing this epsilon is also tricky
40// because if the numbers are large epsilon should also be large,
41// and if the numbers are very small the epsilon must be even smaller.
42// To get around this we'll use a technique from Knuth's "Seminumerical
43// Algorithms" section 4.2.2 and scale epsilon by the exponent of
44// one of the specified numbers.
45//
46//---------------------------------------------------------------
47
48namespace Atlas {
49namespace {
50
51double _ScaleEpsilon(double x1, double x2, double epsilon) {
52 // Get the exponent of the smaller of the two numbers (using the
53 // smaller of the two gives us a tighter epsilon value).
54 int exponent;
55 (void) std::frexp(std::fabs(x1) < std::fabs(x2) ? x1 : x2, &exponent);
56
57 // Scale epsilon by the exponent.
58 return std::ldexp(epsilon, exponent);
59}
60
61float _ScaleEpsilon(float x1, float x2, float epsilon) {
62 // Get the exponent of the smaller of the two numbers (using the
63 // smaller of the two gives us a tighter epsilon value).
64 int exponent;
65 (void) std::frexp(std::fabs(x1) < std::fabs(x2) ? x1 : x2, &exponent);
66
67 // Scale epsilon by the exponent.
68 return std::ldexp(epsilon, exponent);
69}
70}
71bool Equal(double x1, double x2, double epsilon)
72{
73 // If the difference between the numbers is smaller than the
74 // scaled epsilon we'll consider the numbers to be equal.
75
76 return std::fabs(x1 - x2) <= _ScaleEpsilon(x1, x2, epsilon);
77}
78
79bool Equal(float x1, float x2, float epsilon)
80{
81 // If the difference between the numbers is smaller than the
82 // scaled epsilon we'll consider the numbers to be equal.
83
84 return std::fabs(x1 - x2) <= _ScaleEpsilon(x1, x2, epsilon);
85}
86
87
88
89}
Definition: Bridge.h:20