00001 // Filename: nearly_zero.h 00002 // Created by: drose (08Mar00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #ifndef NEARLY_ZERO_H 00020 #define NEARLY_ZERO_H 00021 00022 00023 // The following two functions are defined just to make the 00024 // NEARLY_ZERO() macro work. They each return a suitable nearly-zero 00025 // value for their corresponding numeric type. 00026 INLINE_LINMATH double 00027 get_nearly_zero_value(double) { 00028 return 1.0e-12; 00029 } 00030 00031 INLINE_LINMATH float 00032 get_nearly_zero_value(float) { 00033 return 1.0e-6f; 00034 } 00035 00036 00037 // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is 00038 // within threshold of zero. 00039 #define IS_THRESHOLD_ZERO(value, threshold) \ 00040 ((value) < (threshold) && (value) > -(threshold)) 00041 00042 // IS_THRESHOLD_EQUAL(value1, value2, threshold) returns true if the 00043 // two values are within threshold of each other. 00044 #define IS_THRESHOLD_EQUAL(value1, value2, threshold) \ 00045 (IS_THRESHOLD_ZERO((value1) - (value2), threshold)) 00046 00047 // IS_THRESHOLD_COMPEQ(value1, value2, threshold) returns true if 00048 // the two values are equal within threshold tolerance. Unlike 00049 // IS_THRESHOLD_EQUAL, the transitive principle is guaranteed: 00050 // IS_THRESHOLD_COMPEQ(a, b, t) && IS_THRESHOLD_COMPEQ(b, c, t) 00051 // implies IS_THRESHOLD_COMPEQ(a, c, t). 00052 #define IS_THRESHOLD_COMPEQ(value1, value2, threshold) \ 00053 (cfloor(value1 / threshold + 0.5f) == cfloor(value2 / threshold + 0.5f)) 00054 00055 // NEARLY_ZERO(float) returns a number that is considered to be so 00056 // close to zero as not to matter for a float. NEARLY_ZERO(double) 00057 // returns a similar, smaller number for a double. 00058 #define NEARLY_ZERO(FLOATTYPE) (get_nearly_zero_value((FLOATTYPE)0)) 00059 00060 // IS_NEARLY_ZERO(value) returns true if the value is very close to 00061 // zero. 00062 #define IS_NEARLY_ZERO(value) \ 00063 (IS_THRESHOLD_ZERO(value, get_nearly_zero_value(value))) 00064 00065 // IS_NEARLY_EQUAL(value1, value2) returns true if the two values are 00066 // very close to each other. 00067 #define IS_NEARLY_EQUAL(value1, value2) \ 00068 (IS_THRESHOLD_EQUAL(value1, value2, get_nearly_zero_value(value1))) 00069 00070 00071 // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the 00072 // value itself otherwise. 00073 #define MAYBE_ZERO(value) \ 00074 (IS_NEARLY_ZERO(value) ? 0.0 : (value)) 00075 00076 00077 #endif 00078