00001 // Filename: nearly_zero.h 00002 // Created by: drose (08Mar00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef NEARLY_ZERO_H 00016 #define NEARLY_ZERO_H 00017 00018 #include "dtoolbase.h" 00019 00020 // The following two functions are defined just to make the 00021 // NEARLY_ZERO() macro work. They each return a suitable nearly-zero 00022 // value for their corresponding numeric type. 00023 00024 // Note that declaring these small numeric values first as a static 00025 // const identifier, and then returning the value of that identifier, 00026 // seems to lead to compilation errors (at least in VC7) in which 00027 // sometimes IS_THRESHOLD_COMPEQ(a, a, get_nearly_zero_value(a)) != 0. 00028 INLINE double 00029 get_nearly_zero_value(double) { 00030 return 1.0e-12; 00031 } 00032 00033 INLINE float 00034 get_nearly_zero_value(float) { 00035 return 1.0e-6f; 00036 } 00037 00038 00039 // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is 00040 // within threshold of zero. 00041 #define IS_THRESHOLD_ZERO(value, threshold) \ 00042 ((value) < (threshold) && (value) > -(threshold)) 00043 00044 // IS_THRESHOLD_EQUAL(value1, value2, threshold) returns true if the 00045 // two values are within threshold of each other. 00046 #define IS_THRESHOLD_EQUAL(value1, value2, threshold) \ 00047 (IS_THRESHOLD_ZERO((value1) - (value2), threshold)) 00048 00049 // IS_THRESHOLD_COMPEQ(value1, value2, threshold) returns true if 00050 // the two values are equal within threshold tolerance. Unlike 00051 // IS_THRESHOLD_EQUAL, the transitive principle is guaranteed: 00052 // IS_THRESHOLD_COMPEQ(a, b, t) && IS_THRESHOLD_COMPEQ(b, c, t) 00053 // implies IS_THRESHOLD_COMPEQ(a, c, t). 00054 #define IS_THRESHOLD_COMPEQ(value1, value2, threshold) \ 00055 (cfloor(value1 / threshold + 0.5f) == cfloor(value2 / threshold + 0.5f)) 00056 00057 // NEARLY_ZERO(float) returns a number that is considered to be so 00058 // close to zero as not to matter for a float. NEARLY_ZERO(double) 00059 // returns a similar, smaller number for a double. 00060 #define NEARLY_ZERO(FLOATTYPE) (get_nearly_zero_value((FLOATTYPE)0)) 00061 00062 // IS_NEARLY_ZERO(value) returns true if the value is very close to 00063 // zero. 00064 #define IS_NEARLY_ZERO(value) \ 00065 (IS_THRESHOLD_ZERO(value, get_nearly_zero_value(value))) 00066 00067 // IS_NEARLY_EQUAL(value1, value2) returns true if the two values are 00068 // very close to each other. 00069 #define IS_NEARLY_EQUAL(value1, value2) \ 00070 (IS_THRESHOLD_EQUAL(value1, value2, get_nearly_zero_value(value1))) 00071 00072 00073 // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the 00074 // value itself otherwise. 00075 #define MAYBE_ZERO(value) \ 00076 (IS_NEARLY_ZERO(value) ? 0.0 : (value)) 00077 00078 00079 #endif 00080