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 
48 namespace Atlas {
49 namespace {
50 
51 double _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 
61 float _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 }
71 bool 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 
79 bool 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