Panda3D
nearly_zero.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file nearly_zero.h
10  * @author drose
11  * @date 2000-03-08
12  */
13 
14 #ifndef NEARLY_ZERO_H
15 #define NEARLY_ZERO_H
16 
17 #include "dtoolbase.h"
18 
19 // The following two functions are defined just to make the NEARLY_ZERO()
20 // macro work. They each return a suitable nearly-zero value for their
21 // corresponding numeric type.
22 
23 // Note that declaring these small numeric values first as a static const
24 // identifier, and then returning the value of that identifier, seems to lead
25 // to compilation errors (at least in VC7) in which sometimes
26 // IS_THRESHOLD_COMPEQ(a, a, get_nearly_zero_value(a)) != 0.
27 constexpr double
28 get_nearly_zero_value(double) {
29  return 1.0e-12;
30 }
31 
32 constexpr float
33 get_nearly_zero_value(float) {
34  return 1.0e-6f;
35 }
36 
37 constexpr int
38 get_nearly_zero_value(int) {
39  // This is a bit silly, but we should nevertheless define it in case it is
40  // called for an integer type.
41  return 0;
42 }
43 
44 
45 // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is within
46 // threshold of zero.
47 #define IS_THRESHOLD_ZERO(value, threshold) \
48  ((value) < (threshold) && (value) > -(threshold))
49 
50 // IS_THRESHOLD_EQUAL(value1, value2, threshold) returns true if the two
51 // values are within threshold of each other.
52 #define IS_THRESHOLD_EQUAL(value1, value2, threshold) \
53  (IS_THRESHOLD_ZERO((value1) - (value2), threshold))
54 
55 // IS_THRESHOLD_COMPEQ(value1, value2, threshold) returns true if the two
56 // values are equal within threshold tolerance. Unlike IS_THRESHOLD_EQUAL,
57 // the transitive principle is guaranteed: IS_THRESHOLD_COMPEQ(a, b, t) &&
58 // IS_THRESHOLD_COMPEQ(b, c, t) implies IS_THRESHOLD_COMPEQ(a, c, t).
59 #define IS_THRESHOLD_COMPEQ(value1, value2, threshold) \
60  (cfloor(value1 / threshold + 0.5f) == cfloor(value2 / threshold + 0.5f))
61 
62 // NEARLY_ZERO(float) returns a number that is considered to be so close to
63 // zero as not to matter for a float. NEARLY_ZERO(double) returns a similar,
64 // smaller number for a double.
65 #define NEARLY_ZERO(FLOATTYPE) (get_nearly_zero_value((FLOATTYPE)0))
66 
67 // IS_NEARLY_ZERO(value) returns true if the value is very close to zero.
68 #define IS_NEARLY_ZERO(value) \
69  (IS_THRESHOLD_ZERO(value, get_nearly_zero_value(value)))
70 
71 // IS_NEARLY_EQUAL(value1, value2) returns true if the two values are very
72 // close to each other.
73 #define IS_NEARLY_EQUAL(value1, value2) \
74  (IS_THRESHOLD_EQUAL(value1, value2, get_nearly_zero_value(value1)))
75 
76 
77 // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the value
78 // itself otherwise.
79 #define MAYBE_ZERO(value) \
80  (IS_NEARLY_ZERO(value) ? 0 : (value))
81 
82 
83 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.