00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef _EPSILON_H
00025 #define _EPSILON_H
00026
00027 #include "lux.h"
00028 #include "error.h"
00029 #include "geometry/vector.h"
00030 #include "geometry/point.h"
00031 #include "geometry/bbox.h"
00032
00033 #include <sstream>
00034
00035
00036
00037 #if defined(MACHINE_EPSILON_DEBUG)
00038 #define DEBUG(TYPE, VALUE) DebugPrint(TYPE, VALUE)
00039 #else
00040 #define DEBUG(TYPE, VALUE)
00041 #endif
00042
00043 namespace lux {
00044
00045
00046
00047
00048
00049 #define DEFAULT_EPSILON_MIN 1e-9f
00050 #define DEFAULT_EPSILON_MAX 1e-1f
00051 #define DEFAULT_EPSILON_STATIC 1e-5f
00052
00053
00054 #define DEFAULT_EPSILON_DISTANCE_FROM_VALUE 0x80u
00055
00056 class MachineEpsilon {
00057 public:
00058
00059 static void SetMin(const float min);
00060
00061 static void SetMax(const float max);
00062
00063
00064 static float E(const float value) {
00065 DEBUG("E(float).value", value);
00066 const float epsilon = fabsf(FloatAdvance(value) - value);
00067 DEBUG("E(float).epsilon", epsilon);
00068
00069 return Clamp(epsilon, minEpsilon, maxEpsilon);
00070 }
00071
00072
00073 static float E(const Vector &v) {
00074 return max(E(v.x), max(E(v.y), E(v.z)));
00075 }
00076
00077
00078 static float E(const Point &p) {
00079 return max(E(p.x), max(E(p.y), E(p.z)));
00080 }
00081
00082
00083 static float E(const BBox &bb) {
00084 return max(E(bb.pMin), E(bb.pMax));
00085 }
00086
00087
00088 static void Test();
00089
00090 private:
00091 union MachineFloat {
00092 float f;
00093 u_int i;
00094 };
00095
00096 static float minEpsilon;
00097 static float maxEpsilon;
00098
00099
00100 static float FloatAdvance(const float value) {
00101 MachineFloat mf;
00102 mf.f = value;
00103
00104 mf.i += DEFAULT_EPSILON_DISTANCE_FROM_VALUE;
00105
00106 return mf.f;
00107 }
00108
00109 static float Exp2Float(const int exp) {
00110 return ldexpf(1.f, exp);
00111 }
00112
00113 static int FloatSign(const float value) {
00114 return (value >= 0.f) ? 1 : -1;
00115 }
00116
00117 static int FloatExponent(const float value) {
00118 int exp;
00119 frexpf(value, &exp);
00120
00121 return exp;
00122 }
00123
00124 static float FloatSignificandPrecision(const float value) {
00125 int exp;
00126 const float s = frexpf(value, &exp);
00127
00128
00129 return s;
00130 }
00131
00132 #if defined(MACHINE_EPSILON_DEBUG)
00133 static void DebugPrint(const string type, const float e) {
00134 MachineFloat mf;
00135 mf.f = e;
00136
00137 char buf[256];
00138 sprintf(buf,"Epsilon.DebugPrint: %s=%e %x [%d * 2^%d * %f]",
00139 type.c_str(), mf.f, mf.i,
00140 FloatSign(e), FloatExponent(e), FloatSignificandPrecision(e));
00141 luxError(LUX_NOERROR, LUX_DEBUG, buf);
00142 }
00143
00144 static void DebugPrint(const string type, const int i) {
00145 char buf[256];
00146 sprintf(buf,"Epsilon.DebugPrint: %s=%d", type.c_str(), i);
00147 luxError(LUX_NOERROR, LUX_DEBUG, buf);
00148 }
00149 #endif
00150 };
00151
00152 }
00153
00154 #endif
00155