00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00029
00030 #ifndef UTIL_MATH_H
00031 #define UTIL_MATH_H
00032
00033 #include <PVLE/Util/Assert.h>
00034 #include <boost/math/special_functions/fpclassify.hpp>
00035
00037 inline bool equivalent(const float & a, const float & b, const float & error=1e-6f) { return b==0 ? fabs(a)<error : (a==0 ? fabs(b)<error : fabs(a/b-1.f) < error); }
00039 inline bool equivalent(const double & a, const double & b, const double & error=1e-14) { return b==0 ? fabs(a)<error : (a==0 ? fabs(b)<error : fabs(a/b-1.) < error); }
00040
00041
00043 inline int round(const float & v) {
00044 int base = static_cast<int>(v);
00045 if (v<0) return (base-v > .5f) ? base-1 : base;
00046 return (v-base > .5f) ? base+1 : base;
00047 }
00048
00050 inline int round(const double & v) {
00051 int base = static_cast<int>(v);
00052 if (v<0) return (base-v > .5) ? base-1 : base;
00053 return (v-base > .5) ? base+1 : base;
00054 }
00055
00056
00057
00058
00059
00061 template<typename T>
00062 inline T round(const T & v, int nb_chiffres_significatifs) {
00063 ASSERT(nb_chiffres_significatifs>0);
00064 T e = pow(10+0.f, static_cast<int>(log10(v+0.f)) - (nb_chiffres_significatifs-1));
00065 int vTemp = static_cast<int>(v/(e+0.f));
00066 return (v/(e+0.f)-vTemp) >= .5 ? vTemp*e+e : vTemp*e;
00067 }
00068
00070 template<typename T>
00071 inline T round_inf(const T & v, int nb_chiffres_significatifs) {
00072 ASSERT(nb_chiffres_significatifs>0);
00073 T e = pow(10+0.f, static_cast<int>(log10(v*1.f)) - (nb_chiffres_significatifs-1));
00074 return static_cast<int>(v/(e+0.f)) * e;
00075 }
00076
00078 template<typename T>
00079 inline T round_sup(const T & v, int nb_chiffres_significatifs) {
00080 ASSERT(nb_chiffres_significatifs>0);
00081 T e = pow(10+0.f, static_cast<int>(log10(v*1.f)) - (nb_chiffres_significatifs-1));
00082 return ceil(v/(e+0.f)) * e;
00083 }
00084
00085
00088 template <typename T>
00089 inline T sigmoid(const T & x) { return static_cast<T>(1)/(static_cast<T>(1)+exp(-x)); }
00090
00091
00094 template <class T>
00095 inline T clamp_copy(const T & val, const T & min, const T & max) { return val<min ? min : (val>max ? max : val); }
00096
00098 template <class T>
00099 inline void clamp(T & val, const T & min, const T & max) { if (val<min) val=min; else if (val>max) val=max; }
00101 template <class T>
00102 inline void clampl(T & val, const T & min) { if (val<min) val=min; }
00104 template <class T>
00105 inline void clampu(T & val, const T & max) { if (val>max) val=max; }
00106
00108 template <class T>
00109 inline T _min(T a, T b) { return a<b? a : b; }
00111 template <class T>
00112 inline T _max(T a, T b) { return a>b? a : b; }
00113
00116 inline unsigned int log2(unsigned int val) {
00117 unsigned int idx;
00118 for(idx = 0 ; val > 0 ; ++idx, val >>= 1);
00119 return idx;
00120 }
00121 inline unsigned long log2(unsigned long val) {
00122 unsigned long idx;
00123 for(idx = 0 ; val > 0 ; ++idx, val >>= 1);
00124 return idx;
00125 }
00126
00127
00130 template <class T>
00131 inline void computePolynom1T(T ax, T ay, T bx, T by, T & out_a, T & out_b) {
00132 out_a = (by-ay)/(bx-ax);
00133 out_b = ay - out_a*ax;
00134 ASSERT(boost::math::isfinite(out_a));
00135 ASSERT(boost::math::isfinite(out_b));
00136 }
00137
00138 #define computePolynom1 computePolynom1T<float>
00139 #define computePolynom1f computePolynom1T<float>
00140 #define computePolynom1d computePolynom1T<double>
00141
00142
00145 template <class T>
00146 inline T get_y_polynom1T(T ax, T ay, T bx, T by, T x) {
00147 ASSERT(boost::math::isfinite((by-ay)/(bx-ax)));
00148 ASSERT(boost::math::isfinite(ay-(by-ay)/(bx-ax)*ax));
00149 return (by-ay)/(bx-ax)*(x-ax)+ay;
00150 }
00151
00152 #define get_y_polynom1 get_y_polynom1T<float>
00153 #define get_y_polynom1f get_y_polynom1T<float>
00154 #define get_y_polynom1d get_y_polynom1T<double>
00155
00156
00160 template <class T>
00161 static inline void computePolynom1_surfaceT(T A, T x1, T x2, T y2, T & out_a, T & out_b) {
00162 const T d = x1-x2;
00163 out_a = -2*(A + y2*d) / (d*d);
00164 out_b = y2 - out_a*x2;
00165 }
00166
00167 #define computePolynom1_surface computePolynom1_surfaceT<float>
00168 #define computePolynom1_surfacef computePolynom1_surfaceT<float>
00169 #define computePolynom1_surfaced computePolynom1_surfaceT<double>
00170
00171
00173 template <class T>
00174 void computePolynom2T(T ax, T ay, T bx, T by, T cx, T cy, T & out_a, T & out_b, T & out_c) {
00175 T t1 = ax*ax-bx*bx,
00176 t2 = static_cast<T>(2)*ax*ax-bx*bx-cx*cx;
00177 if (t1 == 0) {
00178
00179 out_b = (ay-by) / (ax-bx);
00180 out_a = ((static_cast<T>(2)*ay-by-cy)-out_b*(static_cast<T>(2)*ax-bx-cx)) / t2;
00181 } else {
00182
00183 out_b = ((ay-by)*t2-t1*(static_cast<T>(2)*ay-by-cy)) /
00184 ((ax-bx)*t2-t1*(static_cast<T>(2)*ax-bx-cx));
00185 out_a = (ay-by-out_b*(ax-bx))/t1;
00186 }
00187 out_c = ay - out_a*ax*ax - out_b*ax;
00188 ASSERT(boost::math::isfinite(out_a));
00189 ASSERT(boost::math::isfinite(out_b));
00190 ASSERT(boost::math::isfinite(out_c));
00191 }
00192
00193 #define computePolynom2 computePolynom2T<float>
00194 #define computePolynom2f computePolynom2T<float>
00195 #define computePolynom2d computePolynom2T<double>
00196
00197
00200 template <class T>
00201 inline T get_y_polynom2T(T ax, T ay, T bx, T by, T cx, T cy, T x) {
00202 T a, b, c;
00203 computePolynom2T<T>(ax, ay, bx, by, cx, cy, a, b, c);
00204 return a*x*x + b*x + c;
00205 }
00206
00207 #define get_y_polynom2 get_y_polynom2T<float>
00208 #define get_y_polynom2f get_y_polynom2T<float>
00209 #define get_y_polynom2d get_y_polynom2T<double>
00210
00211
00214 template<class T>
00215 inline T applique_mult(T val, T mult) { return (val-static_cast<T>(1))*mult+static_cast<T>(1); }
00216
00219 template<class T>
00220 inline T applique_mult(T val, T mult, T centre) { return (val-centre)*mult+centre; }
00221
00222
00224 inline double math_fmod(double a, double b) { return a<0 ? fmod(a, b)+b : fmod(a, b); }
00226 inline float math_fmod(float a, float b) { return a<0 ? fmod(a, b)+b : fmod(a, b); }
00228 inline float math_fmodf(float a, float b) { return a<0 ? fmodf(a, b)+b : fmodf(a, b); }
00230 inline int math_mod(int a, int b) { return a<0 ? a%b+b : a%b; }
00232 inline unsigned int math_mod(unsigned int a, unsigned int b) { return a<0 ? a%b+b : a%b; }
00233
00234
00235 #endif // UTIL_MATH_H