Panda3D

nearly_zero.h

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 
 All Classes Functions Variables Enumerations