00001
00052 #ifndef __MATH_TOOLS__
00053 #define __MATH_TOOLS__
00054
00055
00056
00057
00058 #include <algorithm>
00059 #include <cmath>
00060 #include <cstdlib>
00061 #include <ctime>
00062
00063 #ifndef WITHOUT_LIMITS
00064 #include <limits>
00065 #endif
00066
00067 #include "msg_stream.h"
00068
00069
00070
00071
00072 namespace Math_tools{
00073
00074 template<typename Vec2,typename Real>
00075 inline void barycentric_coordinates(const Vec2& A,
00076 const Vec2& B,
00077 const Vec2& C,
00078 const Vec2& M,
00079 Real* const a,
00080 Real* const b,
00081 Real* const c);
00082
00083 inline void init_random() {std::srand(std::time(NULL));}
00084
00085 template<typename Real>
00086 inline Real random(const Real min_value_included,
00087 const Real max_value_included);
00088
00089
00090 template<typename ValueIterator>
00091 inline double entropy(ValueIterator begin,
00092 ValueIterator end);
00093
00094
00095
00096 template<typename Real>
00097 inline Real clamp(const Real min_value,
00098 const Real max_value,
00099 const Real x);
00100
00101
00102 template<typename Array,typename Real>
00103 inline
00104 typename Array::value_type
00105 bilinear_interpolation(const Array& array,
00106 const Real x,
00107 const Real y);
00108
00109
00110 inline double degree_to_radian(const double d);
00111
00112 inline double radian_to_degree(const double r);
00113
00114 template<typename Real>
00115 inline Real sign(const Real r);
00116
00117
00118 #ifndef WITHOUT_LIMITS
00119
00120 template<typename T> inline bool is_quiet_NaN(T x);
00121
00122 template<typename T> inline bool is_signaling_NaN(T x);
00123
00124 template<typename T> inline bool is_NaN(T x);
00125
00126 #endif
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 template<typename Vec2,typename Real>
00146 void barycentric_coordinates(const Vec2& A,
00147 const Vec2& B,
00148 const Vec2& C,
00149 const Vec2& M,
00150 Real* const a,
00151 Real* const b,
00152 Real* const c){
00153
00154 const Real Xa = A[0] - C[0];
00155 const Real Ya = A[1] - C[1];
00156
00157 const Real Xb = B[0] - C[0];
00158 const Real Yb = B[1] - C[1];
00159
00160 const Real Xm = M[0] - C[0];
00161 const Real Ym = M[1] - C[1];
00162
00163 const Real det = Xa*Yb - Ya*Xb;
00164
00165 if (det != 0){
00166
00167 const Real inv_det = 1.0/det;
00168
00169 *a = inv_det * (Yb*Xm - Xb*Ym);
00170 *b = inv_det * (-Ya*Xm + Ym*Xa);
00171 *c = 1.0 - (*a) - (*b);
00172 }
00173 else{
00174
00175 Message::error
00176 <<"barycentric_coordinates: colinear points not yet implemented"
00177 <<Message::done;
00178
00179 }
00180 }
00181
00182
00183
00184
00185 template<typename Real>
00186 Real random(const Real min_value_included,
00187 const Real max_value_included){
00188
00189 const double delta = static_cast<double>(max_value_included - min_value_included);
00190
00191 return min_value_included + static_cast<Real>(delta*rand()/(RAND_MAX));
00192 }
00193
00194
00195
00196
00197 template<typename ValueIterator>
00198 double entropy(ValueIterator begin,
00199 ValueIterator end){
00200
00201 double sum = 0;
00202 for(ValueIterator i=begin;i!=end;i++){
00203 if (*i>=0){
00204 sum+=*i;
00205 }
00206 else{
00207 Message::error<<"entropy: non-positive value"<<Message::done;
00208 }
00209 }
00210
00211 if (sum==0){
00212 Message::error<<"entropy: sum==0"<<Message::done;
00213 }
00214
00215 double result = 0;
00216 for(ValueIterator i=begin;i!=end;i++){
00217 const double p = (*i)/sum;
00218 result -= (p==0) ? 0 : p*log(p);
00219 }
00220
00221 return result;
00222 }
00223
00224
00225
00226 template<typename Real>
00227 inline Real clamp(const Real min_value,
00228 const Real max_value,
00229 const Real x){
00230
00231 return std::max(std::min(x,max_value),min_value);
00232 }
00233
00234
00235 template<typename Array,typename Real>
00236 inline
00237 typename Array::value_type
00238 bilinear_interpolation(const Array& array,
00239 const Real x,
00240 const Real y){
00241
00242 typedef unsigned int size_type;
00243 typedef float real_type;
00244
00245 const size_type x_size = array.x_size();
00246 const size_type y_size = array.y_size();
00247
00248 const size_type x_index =
00249 clamp<size_type>(0,x_size-1,static_cast<size_type>(x));
00250 const size_type xx_index =
00251 clamp<size_type>(0,x_size-1,x_index+1);
00252
00253 const size_type y_index =
00254 clamp<size_type>(0,y_size-1,static_cast<size_type>(y));
00255 const size_type yy_index =
00256 clamp<size_type>(0,y_size-1,y_index+1);
00257
00258 const real_type x_alpha = x - x_index;
00259 const real_type y_alpha = y - y_index;
00260
00261 return
00262 (1.0f-x_alpha) * (1.0f-y_alpha) * array(x_index, y_index) +
00263 x_alpha * (1.0f-y_alpha) * array(xx_index,y_index) +
00264 (1.0f-x_alpha) * y_alpha * array(x_index, yy_index) +
00265 x_alpha * y_alpha * array(xx_index,yy_index);
00266
00267 }
00268
00269
00270 inline double degree_to_radian(const double d){
00271 return d*M_PI/180;
00272 }
00273
00274
00275 inline double radian_to_degree(const double r){
00276 return r*180/M_PI;
00277 }
00278
00279
00280 template<typename Real>
00281 inline Real sign(const Real r){
00282 return (r==0) ? 0 : ((r>0) ? 1 : -1);
00283 }
00284
00285
00286
00287 #ifndef WITHOUT_LIMITS
00288
00289 template<typename T> bool is_quiet_NaN(T x){
00290
00291 const unsigned int size = sizeof(T)/sizeof(int);
00292
00293 T ref = std::numeric_limits<T>::quiet_NaN();
00294
00295 int* index_ref = reinterpret_cast<int*>(&ref);
00296 int* index_cmp = reinterpret_cast<int*>(&x);
00297
00298 for(unsigned int i=0;i<size;i++){
00299 if (index_ref[i]!=index_cmp[i]){
00300 return false;
00301 }
00302 }
00303
00304 return true;
00305 }
00306
00307
00308 template<typename T> bool is_signaling_NaN(T x){
00309
00310 const unsigned int size = sizeof(T)/sizeof(int);
00311
00312 T ref = std::numeric_limits<T>::signaling_NaN();
00313
00314 int* index_ref = reinterpret_cast<int*>(&ref);
00315 int* index_cmp = reinterpret_cast<int*>(&x);
00316
00317 for(unsigned int i=0;i<size;i++){
00318 if (index_ref[i]!=index_cmp[i]){
00319 return false;
00320 }
00321 }
00322
00323 return true;
00324 }
00325
00326
00327 template<typename T> bool is_NaN(T x){
00328 return (is_quiet_NaN(x)||is_signaling_NaN(x));
00329 }
00330
00331 #endif
00332
00333
00334 }
00335
00336
00337 #endif