00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _LIB_NUMERICS_MATH_H_
00018 #define _LIB_NUMERICS_MATH_H_
00019
00020 #include <lib/sconfig.h>
00021
00022
00047 #include <math.h>
00048
00071
00072
00073
00074
00076 namespace NUM
00077 {
00078
00079
00080 #undef M_PI
00081
00082
00083
00084
00085
00086 #if USE_STATIC_CONST_FP_MEMB || defined(DOXYGEN_IS_SCANNING)
00087 # define SCFMinit(x) =x
00088 #else
00089 # define SCFMinit(x)
00090 #endif
00091
00098 template<typename T>struct FPConst
00099 {
00101 T macheps1;
00103 T sqrt_macheps1;
00104
00107 T macheps1_prec;
00108
00109
00110
00111
00112 static const T pi SCFMinit(3.1415926535897932384626433832795029);
00113 static const T div_pi_2 SCFMinit(1.5707963267948966192313216916397514);
00114 static const T div_pi_3 SCFMinit(1.047197551196597746154214461093168);
00115 static const T div_pi_4 SCFMinit(0.7853981633974483096156608458198757);
00116 static const T mul_pi_2 SCFMinit(6.283185307179586476925286766559006);
00117 static const T mul_pi_3 SCFMinit(9.424777960769379715387930149838509);
00118 static const T mul_pi_4 SCFMinit(12.56637061435917295385057353311801);
00119 static const T mul_pi_2_3 SCFMinit(2.094395102393195492308428922186335);
00120 static const T div_1_pi SCFMinit(0.3183098861837906715377675267450287);
00121 static const T div_2_pi SCFMinit(0.6366197723675813430755350534900574);
00122 static const T div_2_sqrt_pi SCFMinit(1.1283791670955125738961589031215452);
00123
00124 static const T sqrt_2 SCFMinit(1.4142135623730950488016887242096981);
00125 static const T div_1_sqrt_2 SCFMinit(0.7071067811865475244008443621048490);
00126
00127 static const T e SCFMinit(2.7182818284590452353602874713526625);
00128 static const T log2_e SCFMinit(1.4426950408889634073599246810018921);
00129 static const T log10_e SCFMinit(0.4342944819032518276511289189166051);
00130 static const T ln_2 SCFMinit(0.6931471805599453094172321214581766);
00131 static const T ln_10 SCFMinit(2.3025850929940456840179914546843642);
00132
00133 static const T div_1_pow_2_31 SCFMinit(1.0/2147483648.0);
00134 static const T div_1_pow_2_31m1 SCFMinit(1.0/2147483647.0);
00135 static const T div_1_pow_2_32 SCFMinit(1.0/4294967296.0);
00136 static const T div_1_pow_2_32m1 SCFMinit(1.0/4294967295.0);
00137 static const T div_1_pow_2_53 SCFMinit(1.0/9007199254740992.0);
00138 static const T div_1_pow_2_53m1 SCFMinit(1.0/9007199254740991.0);
00139
00140
00141
00142
00143
00144
00150 static const T huge_val;
00151
00153 static const T max_val;
00155 static const T min_val;
00156 };
00157
00158
00159 #undef SCFMinit
00160
00162 extern const FPConst<dbl> fpconst_dbl;
00164 extern const FPConst<flt> fpconst_flt;
00165
00166
00167
00168
00169
00170
00171 #ifdef sgn
00172 #error sgn defined
00173 #endif
00174
00180 template<typename T>inline _constfn_ int sgn(T x)
00181 { return(x>0 ? 1 : (x<0 ? -1 : 0)); }
00182
00191 template<typename T>inline _constfn_ int sgn11(T x)
00192 { return(x<0 ? -1 : 1); }
00193
00194
00195 #ifndef DOXYGEN_IS_SCANNING
00196
00197
00198
00199 template<typename T>inline _constfn_ bool is_negative(T x)
00200 { return(x<0); }
00201
00202
00203
00204
00205
00206 inline _constfn_ bool is_negative(double x)
00207 { return(signbit(x)); }
00208 inline _constfn_ bool is_negative(float x)
00209 { return(signbit(x)); }
00210 inline _constfn_ bool is_negative(long double x)
00211 { return(signbit(x)); }
00212
00213
00214
00215 #if HAVE_ISINF
00216 template<typename T>inline _constfn_ bool is_inf(T x)
00217 { return(isinf(x)); }
00218 #elif HAVE_FPCLASSIFY
00219 template<typename T>inline _constfn_ bool is_inf(T x)
00220 { return(fpclassify(x)==FP_INFINITE); }
00221 #else
00222 # error "You lack isinf()/fpclassify()."
00223 #endif
00224
00225
00226 #if HAVE_ISNAN
00227 template<typename T>inline _constfn_ bool is_nan(T x)
00228 { return(isnan(x)); }
00229 #elif HAVE_FPCLASSIFY
00230 template<typename T>inline _constfn_ bool is_nan(T x)
00231 { return(fpclassify(x)==FP_NAN); }
00232 #else
00233 # error "You lack isnan()/fpclassify()."
00234 #endif
00235
00236
00237 #if HAVE_FINITE
00238 template<typename T>inline _constfn_ bool is_finite(T x)
00239 { return(finite(x)); }
00240 #elif HAVE_ISFINITE
00241 template<typename T>inline _constfn_ bool is_finite(T x)
00242 { return(isfinite(x)); }
00243 #elif HAVE_FPCLASSIFY
00244 template<typename T>inline _constfn_ bool is_finite(T x)
00245 { return(fpclassify(x)!=FP_NAN && fpclassify(x)!=FP_INFINITE); }
00246 #else
00247 # error "You lack finite()/isfinite()/fpclassify()."
00248 #endif
00249
00250
00251 #if defined(sqr) || defined(SQR)
00252 #error sqr defined
00253 #endif
00254
00255 template<typename T>inline _constfn_ T sqr(T x) { return(x*x); }
00256
00257 #ifdef fabs
00258 #error fabs defined
00259 #endif
00260
00261
00262 template<typename T>inline T fabs(T x) { return(x<0 ? -x : x); }
00263
00264 #if defined(max) || defined(min)
00265 #error max or min defined
00266 #endif
00267
00268 template<typename T>inline T max(T a,T b)
00269 { return(a<b ? b : a); }
00271 template<typename T>inline T min(T a,T b)
00272 { return(a<b ? a : b); }
00273
00274
00275 #define NUM_OVERLOADED_R(func,cfunc) \
00276 inline double func(double x) { return(::cfunc(x)); } \
00277 inline float func(float x) { return(::cfunc ## f(x)); } \
00278 inline long double func(long double x) { return(::cfunc ## l(x)); }
00279 #define NUM_OVERLOADED(func) NUM_OVERLOADED_R(func,func)
00280
00281 #define NUM_OVERLOADED2_R(func,cfunc) \
00282 inline double func(double x,double y) { return(::cfunc(x,y)); } \
00283 inline float func(float x,float y) { return(::cfunc ## f(x,y)); } \
00284 inline long double func(long double x,long double y) \
00285 { return(::cfunc ## l(x,y)); }
00286 #define NUM_OVERLOADED2(func) NUM_OVERLOADED2_R(func,func)
00287
00288 #if defined(sqrt) || defined(sin) || defined(cos) || defined(tan) || defined(exp) || defined(log)
00289 #error defined math functions
00290 #endif
00291
00292 NUM_OVERLOADED(fabs)
00293 NUM_OVERLOADED(sqrt) NUM_OVERLOADED2(pow)
00294 NUM_OVERLOADED(sin) NUM_OVERLOADED(asin)
00295 NUM_OVERLOADED(cos) NUM_OVERLOADED(acos)
00296 NUM_OVERLOADED(sinh) NUM_OVERLOADED(asinh)
00297 NUM_OVERLOADED(cosh) NUM_OVERLOADED(acosh)
00298 NUM_OVERLOADED(tan) NUM_OVERLOADED(atan) NUM_OVERLOADED2(atan2)
00299 NUM_OVERLOADED(tanh) NUM_OVERLOADED(atanh)
00300 NUM_OVERLOADED(exp) NUM_OVERLOADED(log)
00301
00302 NUM_OVERLOADED(ceil) NUM_OVERLOADED(floor)
00303 NUM_OVERLOADED(trunc)
00304
00305 NUM_OVERLOADED2(remainder)
00306
00307
00308
00309 #if HAVE_FMAX
00310 NUM_OVERLOADED2_R(max,fmax)
00311 #endif
00312 #if HAVE_FMIN
00313 NUM_OVERLOADED2_R(min,fmin)
00314 #endif
00315
00316 extern _deprecated_ dbl fmax(dbl x,dbl y);
00317 extern _deprecated_ flt fmaxf(flt x,flt y);
00318 extern _deprecated_ dbl fmin(dbl x,dbl y);
00319 extern _deprecated_ flt fminf(flt x,flt y);
00320
00321
00322
00323
00324
00325
00326
00327 extern _deprecated_ dbl rint(dbl x);
00328 extern _deprecated_ dbl nearbyint(dbl x);
00329 extern _deprecated_ dbl round(dbl x);
00330
00331
00332
00333 template<typename I,typename FP>inline I iroundc(FP x);
00334
00335 template<> inline int32 iroundc<int32,double> (double x) { return(::lrint(x)); }
00336 template<> inline int32 iroundc<int32,float> (float x) { return(::lrintf(x)); }
00337 template<> inline int32 iroundc<int32,long double>(long double x) { return(::lrintl(x)); }
00338 template<> inline int64 iroundc<int64,double> (double x) { return(::llrint(x)); }
00339 template<> inline int64 iroundc<int64,float> (float x) { return(::llrintf(x)); }
00340 template<> inline int64 iroundc<int64,long double>(long double x) { return(::llrintl(x)); }
00341
00342 #define IROUND_OVERLOADED(func,itype) \
00343 template<> inline itype func<itype,double>(double x) \
00344 { return(NUM::func<int32>(x)); } \
00345 template<> inline itype func<itype,float>(float x) \
00346 { return(NUM::func<int32>(x)); } \
00347 template<> inline itype func<itype,long double>(long double x) \
00348 { return(NUM::func<int32>(x)); }
00349 IROUND_OVERLOADED(iroundc,int8);
00350 IROUND_OVERLOADED(iroundc,uint8);
00351 IROUND_OVERLOADED(iroundc,int16);
00352 IROUND_OVERLOADED(iroundc,uint16);
00353
00354 template<typename I,typename FP>inline I iroundc(I *d,FP x)
00355 { return(*d=NUM::iroundc<I,FP>(x)); }
00356
00357
00358
00359 template<typename I,typename FP>inline I iround(FP x);
00360
00361 template<> inline int32 iround<int32,double> (double x) { return(::lround(x)); }
00362 template<> inline int32 iround<int32,float> (float x) { return(::lroundf(x)); }
00363 template<> inline int32 iround<int32,long double>(long double x) { return(::lroundl(x)); }
00364 template<> inline int64 iround<int64,double> (double x) { return(::llround(x)); }
00365 template<> inline int64 iround<int64,float> (float x) { return(::llroundf(x)); }
00366 template<> inline int64 iround<int64,long double>(long double x) { return(::llroundl(x)); }
00367
00368 IROUND_OVERLOADED(iround,int8);
00369 IROUND_OVERLOADED(iround,uint8);
00370 IROUND_OVERLOADED(iround,int16);
00371 IROUND_OVERLOADED(iround,uint16);
00372 #undef IROUND_OVERLOADED
00373
00374 template<typename I,typename FP>inline I iround(I *d,FP x)
00375 { return(*d=NUM::iround<I,FP>(x)); }
00376
00377
00378 #if HAVE_CBRT
00379 NUM_OVERLOADED(cbrt)
00380 #else
00381 template<typename T>inline T cbrt(T x)
00382 { return( NUM::is_negative(x) ?
00383 -NUM::pow(-x,0.3333333333333333333333333333333333) :
00384 NUM::pow( x,0.3333333333333333333333333333333333) ); }
00385 #endif
00386
00387 #if HAVE_EXP10
00388 NUM_OVERLOADED(exp10)
00389 #else
00390 template<typename T>inline T exp10(T x)
00391 { return(NUM::pow(T(10),x)); }
00392 #endif
00393
00394 #if HAVE_LOG10
00395 NUM_OVERLOADED(log10)
00396 #else
00397 template<typename T>inline T log10(T x)
00398 { return(NUM::log(x)/FPConst<T>::ln_10); }
00399 #endif
00400
00401 #if HAVE_EXP2
00402 NUM_OVERLOADED(exp2)
00403 #else
00404 template<typename T>inline T exp2(T x)
00405 { return(NUM::pow(T(2),x)); }
00406 #endif
00407
00408 #if HAVE_LOG2
00409 NUM_OVERLOADED(log2)
00410 #elif HAVE_LOGB
00411 NUM_OVERLOADED_R(log2,logb)
00412 #else
00413 template<typename T>inline T log2(T x)
00414 { return(NUM::log(x)/FPConst<T>::ln_2); }
00415 #endif
00416
00417 extern _deprecated_ dbl logb(dbl x);
00418 extern _deprecated_ flt logbf(flt x);
00419
00420 #if HAVE_ILOGB
00421 inline int ilog2(double x) { return(::ilogb(x)); }
00422 inline int ilog2(float x) { return(::ilogbf(x)); }
00423 inline int ilog2(long double x) { return(::ilogbl(x)); }
00424 #else
00425
00426 template<typename T>inline int ilog2(T x)
00427 { return((int)NUM::floor(NUM::log2(x))); }
00428 #endif
00429
00430 extern _deprecated_ int ilogb(dbl x);
00431 extern _deprecated_ int ilogbf(flt x);
00432
00433 #if HAVE_EXPM1
00434 NUM_OVERLOADED(expm1)
00435 #else
00436 template<typename T>inline T expm1(T x)
00437 { return(NUM::exp(x)-1); }
00438 #endif
00439
00440 #if HAVE_LOG1P
00441 NUM_OVERLOADED(log1p)
00442 #else
00443 template<typename T>inline T log1p(T x)
00444 { return(NUM::log(1+x)); }
00445 #endif
00446
00447 #if HAVE_COPYSIGN
00448 NUM_OVERLOADED2(copysign)
00449 #else
00450 template<typename T>inline T copysign(T x,T y)
00451 { return(NUM::is_negative(x)==NUM::is_negative(y) ? x : -x); }
00452 #endif
00453
00454 #if HAVE_FDIM
00455 NUM_OVERLOADED2(fdim)
00456 #else
00457 template<typename T>inline T fdim(T x,T y)
00458 { T tmp=x-y; return(is_negative(tmp) ? T(0) : tmp); }
00459 #endif
00460
00461 #if HAVE_FMA
00462 inline double fma(double x,double y,double z) { return(::fma(x,y,z)); }
00463 inline float fma(float x,float y,float z) { return(::fmaf(x,y,z)); }
00464 inline long double fma(long double x,long double y,long double z)
00465 { return(::fmal(x,y,z)); }
00466 #else
00467 template<typename T>inline T fma(T x,T y,T z)
00468 { return(x*y+z)); }
00469 #endif
00470
00471 #if defined(sincos)
00472 #error defined math function sincos
00473 #endif
00474 #if HAVE_SINCOS
00475 inline void sincos(double x,double *sinx,double *cosx)
00476 { ::sincos(x,sinx,cosx); }
00477 inline void sincos(float x,float *sinx,float *cosx)
00478 { ::sincosf(x,sinx,cosx); }
00479 inline void sincos(long double x,long double *sinx,long double *cosx)
00480 { ::sincosl(x,sinx,cosx); }
00481 #else
00482 template<typename T>inline void sincos(T x,T *sinx,T *cosx)
00483 { *sinx=NUM::sin(x); *cosx=NUM::cos(x); }
00484 #endif
00485
00486
00487
00488 inline double ldexp(double x,int exp) { return(::ldexp(x,exp)); }
00489 inline float ldexp(float x,int exp) { return(::ldexpf(x,exp)); }
00490 inline long double ldexp(long double x,int exp) { return(::ldexpl(x,exp)); }
00491
00492 extern _deprecated_ dbl scalbn(dbl x,int exp);
00493 extern _deprecated_ dbl scalb(dbl x,int exp);
00494
00495
00496
00497
00498 inline double modf(double x,double *iptr)
00499 { return(::modf(x,iptr)); }
00500 inline float modf(float x,float *iptr)
00501 { return(::modff(x,iptr)); }
00502 inline long double modf(long double x,long double *iptr)
00503 { return(::modfl(x,iptr)); }
00504
00505
00506
00507 inline double frexp(double x,int *exp) { return(::frexp(x,exp)); }
00508 inline float frexp(float x,int *exp) { return(::frexpf(x,exp)); }
00509 inline long double frexp(long double x,int *exp) { return(::frexpl(x,exp)); }
00510
00511
00512 extern _deprecated_ dbl drem(dbl x,dbl y);
00513 extern _deprecated_ flt drem(flt x,flt y);
00514 extern _deprecated_ flt dremf(flt x,flt y);
00515
00516 #undef NUM_OVERLOADED
00517 #undef NUM_OVERLOADED2
00518 #undef NUM_OVERLOADED_R
00519 #undef NUM_OVERLOADED2_R
00520
00521 #else
00522
00523
00524 #error "This should not be compiled; only for doxygen."
00525
00535 template<typename T>inline bool is_inf(T x);
00536
00546 template<typename T>inline bool is_nan(T x);
00547
00557 template<typename T>inline bool is_finite(T x);
00558
00559
00569 template<typename T>inline bool is_negative(T x);
00570
00581 template<typename T>inline T fabs(T x);
00582
00593 template<typename T>inline T copysign(T x,T y);
00594
00602 template<typename T>inline T max(T a,T b);
00603
00611 template<typename T>inline T min(T a,T b);
00612
00614 template<typename T>inline T asin(T x);
00616 template<typename T>inline T acos(T x);
00618 template<typename T>inline T tan(T x);
00619
00621 template<typename T>inline T sinh(T x);
00623 template<typename T>inline T cosh(T x);
00625 template<typename T>inline T tanh(T x);
00626
00628 template<typename T>inline T asinh(T x);
00630 template<typename T>inline T acosh(T x);
00632 template<typename T>inline T atanh(T x);
00633
00642 template<typename T>inline T sin(T x);
00643
00652 template<typename T>inline T cos(T x);
00653
00660 template<typename T>inline T atan(T x);
00661
00669 template<typename T>inline T atan2(T x);
00670
00672 template<typename T>inline T sqr(T x);
00674 template<typename T>inline T sqrt(T x);
00676 template<typename T>inline T cbrt(T x);
00677
00683 template<typename T>inline T pow(T x,T y);
00684
00691 template<typename T>inline T exp(T x);
00692
00698 template<typename T>inline T log(T x);
00699
00706 template<typename T>inline T expm1(T x);
00707
00713 template<typename T>inline T log1p(T x);
00714
00716 template<typename T>inline T exp10(T x);
00718 template<typename T>inline T log10(T x);
00719
00727 template<typename T>inline T fdim(T x,T y);
00728
00734 template<typename T>inline T exp2(T x);
00735
00741 template<typename T>inline T log2(T x);
00742
00750 template<typename T>inline int ilog2(T x);
00751
00760 template<typename T>inline T ldexp(T x,int exp);
00761
00771 template<typename T>inline T modf(T x,T *iptr);
00772
00784 template<typename T>inline T frexp(T x,int *exp);
00785
00787 template<typename T>inline void sincos(T x,T *sinx,T *cosx);
00788
00798 template<typename T>inline T remainder(T x,T y);
00799
00805 template<typename T>inline T fma(T x,T y,T z);
00806
00808 template<typename T>inline T ceil(T x);
00810 template<typename T>inline T floor(T x);
00812 template<typename T>inline T trunc(T x);
00813
00828 template<typename I,typename FP>inline I iroundc(FP x);
00829
00841 template<typename I,typename FP>inline I iroundc(I *d,FP x);
00842
00857 template<typename I,typename FP>inline I iround(FP x);
00858
00870 template<typename I,typename FP>inline I iround(I *d,FP x);
00871
00872
00873 #endif
00874
00882 template<typename T>inline T dabs(T x,T y)
00883 { return(NUM::fabs(x-y)); }
00884
00885
00886
00887
00888
00889 #ifndef DOXYGEN_IS_SCANNING
00890
00891
00892
00893 #undef signbit
00894 extern _deprecated_ int signbit(dbl x);
00895
00896 #undef isinf
00897 extern _deprecated_ int isinf(dbl x);
00898
00899 #undef isnan
00900 extern _deprecated_ int isnan(dbl x);
00901
00902 #undef finite
00903 #undef isfinite
00904 extern _deprecated_ int finite(dbl x);
00905 extern _deprecated_ int isfinite(dbl x);
00906
00907
00908 #undef fpclassify
00909 extern _deprecated_ int fpclassify(dbl x);
00910
00911
00912
00913 #undef significand
00914 extern _deprecated_ dbl significand(dbl x);
00915
00916 #endif
00917
00918
00919
00920
00921
00923 template<typename T>inline T max(T a,T b,T c)
00924 { return(b<a ? NUM::max(a,c) : NUM::max(b,c)); }
00926 template<typename T>inline T min(T a,T b,T c)
00927 { return(a<b ? NUM::min(a,c) : NUM::min(b,c)); }
00928
00930 inline _constfn_ int powii(int x,int y)
00931 {
00932 if(y<0) return(-1);
00933 int res=1;
00934 for(;y;x*=x) { if(y&1) res*=x; y/=2; }
00935 return(res);
00936 }
00938 template<typename T>inline _constfn_ T powi(T x,int y)
00939 {
00940 #if 0
00941 bool neg=(y<0 ? (y=-y,1) : 0);
00942 T res=1;
00943 for(;y;x*=x) { if(y&1) res*=x; y/=2; }
00944 return(neg ? 1/res : res);
00945 #else
00946
00947
00948 if(y<0) { x=1/x; y=-y; }
00949 T res=1;
00950 do { if(y&1) res*=x; x*=x; } while((y/=2));
00951 return(res);
00952 #endif
00953 }
00954
00955
00962 template<typename T>inline _constfn_ T clamp2(T x,T low,T high)
00963 { return(x<low ? low : (x>high ? high : x)); }
00964
00970 template<typename T>inline T clamp1(T x,T b)
00971 { return(NUM::fabs(x)>b ? (x>b ? b : -b) : x); }
00972
00980 template<typename T>inline T hypot2(T a,T b)
00981 {
00982 a=NUM::fabs(a); b=NUM::fabs(b);
00983 return(a>b ? (a * sqrt(1 + sqr(b/a))) :
00984 (b==0 ? 0 : b * sqrt(1 + sqr(a/b))) );
00985 }
00986
00987
01001 template<typename T,typename P>inline T lerp2(T l,T r,P p,P p1)
01002 { return( p*r + p1*l ); }
01003
01013 template<typename T,typename P>inline T lerp(T l,T r,P p)
01014 { return(NUM::lerp2<T,P>(l,r,p,1-p)); }
01015
01016
01036 template<typename T,typename P>inline T bilerp2(
01037 T lt,T rt,T lb,T rb,
01038 P px,P py,P px1,P py1)
01039 { return( py * (px*rb + px1*lb) + py1 * (px*rt + px1*lt) ); }
01040
01050 template<typename T,typename P>inline T bilerp(
01051 T lt,T rt,T lb,T rb,
01052 P px,P py)
01053 { return(NUM::bilerp2<T,P>(lt,rt,lb,rb,px,py,1-px,1-py)); }
01054
01055
01064 template<typename T>inline T FermiDirac(T x)
01065 { return(1/(1+NUM::exp(-x))); }
01066
01085 template<typename T>inline T FermiDirac(T x,T t)
01086 { return(NUM::FermiDirac(x*t)); }
01087
01088
01099 template<typename T>inline T StepLinear(T x,T a,T b)
01100 { return( x<=a ? 0 : (x>=b ? 1 : (x-a)/(b-a)) ); }
01101
01112 template<typename T>inline T StepCubic(T x,T a,T b)
01113 { T v=NUM::StepLinear(x,a,b); return((3-2*v)*v*v); }
01114
01115
01125 template<typename T>inline T NormEuclidic2(const T *x,int dim)
01126 {
01127 T sum=0;
01128 for(int i=0; i<dim; i++) sum+=NUM::sqr(x[i]);
01129 return(sum);
01130 }
01131
01141 template<typename T>inline T NormEuclidic(const T *x,int dim)
01142 {
01143 if(dim==1) return(NUM::fabs(*x));
01144 T sum=0;
01145 for(int i=0; i<dim; i++) sum+=NUM::sqr(x[i]);
01146 return(sqrt(sum));
01147 }
01148
01156 template<typename T>inline T DistEuclidic2(const T *x,const T *y,int dim)
01157 {
01158 T sum=0;
01159 for(int i=0; i<dim; i++) sum+=NUM::sqr(y[i]-x[i]);
01160 return(sum);
01161 }
01162
01170 template<typename T>inline T DistEuclidic(const T *x,const T *y,int dim)
01171 {
01172 if(dim==1) return(NUM::fabs(*y-*x));
01173 T sum=0;
01174 for(int i=0; i<dim; i++) sum+=sqr(y[i]-x[i]);
01175 return(sqrt(sum));
01176 }
01177
01178
01186 template<typename T>inline T FindMaximum(const T *a,int dim)
01187 {
01188 if(!dim) return(0);
01189 T max=a[0];
01190 for(int i=1; i<dim; i++)
01191 if(max<a[i]) max=a[i];
01192 return(max);
01193 }
01194
01200 template<class T>inline T FindMinimum(const T *a,int dim)
01201 {
01202 if(!dim) return(0);
01203 T min=a[0];
01204 for(int i=1; i<dim; i++)
01205 if(min>a[i]) min=a[i];
01206 return(min);
01207 }
01208
01216 template<class T>inline int FindMinimumIdx(const T *a,int dim)
01217 {
01218 if(!dim) return(-1);
01219 int midx=0;
01220 T min=a[0];
01221 for(int i=1; i<dim; i++)
01222 if(min>a[i])
01223 { min=a[i]; midx=i; }
01224 return(midx);
01225 }
01226
01227
01239 template<typename T>inline T NormalizeVector(T *x,int dim)
01240 {
01241 T len=NormEuclidic(x,dim),fact=T(1)/len;
01242 for(int i=0; i<dim; i++)
01243 { x[i]*=fact; }
01244 return(len);
01245 }
01246
01256 template<typename T>inline T NormalizeVector(T *dest,const T *src,int dim)
01257 {
01258 T len=NormEuclidic(src,dim),fact=T(1)/len;
01259 for(int i=0; i<dim; i++)
01260 { dest[i]=src[i]*fact; }
01261 return(len);
01262 }
01263
01265 template<typename T>inline T NormalizeVector2D(T *x)
01266 { T len=hypot(x[0],x[1]),fact=T(1)/len; x[0]*=fact; x[1]*=fact; return(len); }
01267
01269 template<typename T>inline void CrossProduct(T *dest,const T *a,const T *b)
01270 {
01271 dest[0] = a[1]*b[2] - a[2]*b[1];
01272 dest[1] = a[2]*b[0] - a[0]*b[2];
01273 dest[2] = a[0]*b[1] - a[1]*b[0];
01274 }
01275
01276
01283 template<typename T>inline T DotProduct(const T *a,const T*b,int dim)
01284 {
01285 T res=0;
01286 for(int i=0; i<dim; i++) res+=a[i]*b[i];
01287 return(res);
01288 }
01290 template<typename T>inline T DotProduct3D(const T *a,const T*b)
01291 { return(a[0]*b[0]+a[1]*b[1]+a[2]*b[2]); }
01292
01293
01304 template<typename T>inline T PolvEval(T x,const T *c,int n)
01305 {
01306 T r=c[n];
01307 while(n--) r=r*x+c[n];
01308 return(r);
01309 }
01310
01311
01326 template<typename T>inline int ArrayBinsearchInterval(T *array,int size,T value)
01327 {
01328 if(!size) return(0);
01329
01330 if(value<array[0]) return(-1);
01331 if(value>=array[size-1]) return(size);
01332 Assert(size>=2);
01333 int a=0,b=size-1;
01334 while(b-a>1)
01335 {
01336 int m=(a+b)/2;
01337 if(value>=array[m]) a=m;
01338 else b=m;
01339 }
01340 Assert(array[a]<=value);
01341 Assert(value<array[b]);
01342 return(a);
01343 }
01344
01345
01357 template<typename T>inline int TestOrderAscenting(const T *array,int n,
01358 T val_eps=1e-7)
01359 {
01360 if(!array) return(0);
01361 for(int i=1; i<n; i++)
01362 if(array[i]-array[i-1]<=val_eps)
01363 return(i);
01364 return(0);
01365 }
01366
01367 }
01368
01369 #endif