#pragma once #include #include #include #include #include "lib_begin.h" namespace cgv{ namespace math { //returns the abs(a)*sign(b) template T sign(const T&a, const T&b) { if(b < 0) return -std::abs(a) ; else return std::abs(a); } namespace detail { template T erf_fitting_function(const T& u) { return (T) ( - 1.26551223 + u*(1.00002368 + u*(0.37409196 + u*(0.09678418 + u*(-0.18628806 + u*(0.27886807 + u*(-1.13520398 + u*(1.48851587 + u*(-0.82215223 + u*0.17087277))))))))); } } /// evaluate the error function erf(x) = 2/sqrt(Pi)*int(exp(-y^2),y=0..x) template T erf(const T& x) { if (x < 0) return -erf(-x); T u = 1/(1 + (T)0.5*x); T ans = u*exp(-x*x + detail::erf_fitting_function(u)); return 1 - ans; } /// evaluate the complementary error function erfc(x) = 1-erf(x) template T erfc(const T& x) { return 1-erf(x); } /// evaluate the cummulative normal distribution function template T Phi(const T& x) { return (T)(0.5*erfc(-x*sqrt(0.5))); } /// evaluate the inverse of the error function Phi^(-1)(p), p=0..1 template T inv_Phi(const T& p) { static T a[] = {(T)-3.969683028665376e+01,(T) 2.209460984245205e+02,(T) -2.759285104469687e+02,(T) 1.383577518672690e+02,(T) -3.066479806614716e+01,(T) 2.506628277459239e+00}; static T b[] = {(T)-5.447609879822406e+01,(T) 1.615858368580409e+02,(T) -1.556989798598866e+02,(T) 6.680131188771972e+01,(T) -1.328068155288572e+01}; static T c[] = {(T)-7.784894002430293e-03,(T)-3.223964580411365e-01,(T)-2.400758277161838e+00,(T)-2.549732539343734e+00,(T) 4.374664141464968e+00,(T) 2.938163982698783e+00}; static T d[] = {(T)7.784695709041462e-03,(T)3.224671290700398e-01,(T)2.445134137142996e+00,(T)3.754408661907416e+00}; if (p <= 0) return -std::numeric_limits::infinity(); if (p >= 1) return std::numeric_limits::infinity(); T x; if (p < (T)0.02425) { T q = sqrt(-(T)2.0*log(p)); x = (((((c(1)*q+c(2))*q+c(3))*q+c(4))*q+c(5))*q+c(6)) / ((((d(1)*q+d(2))*q+d(3))*q+d(4))*q+1); } else if (p <= (T)0.97575) { T q = p - (T)0.5; T r = q*q; x = (((((a(1)*r+a(2))*r+a(3))*r+a(4))*r+a(5))*r+a(6))*q / (((((b(1)*r+b(2))*r+b(3))*r+b(4))*r+b(5))*r+1); } else { T q = sqrt(-(T)2.0*log(1-p)); x = -(((((c(1)*q+c(2))*q+c(3))*q+c(4))*q+c(5))*q+c(6)) / ((((d(1)*q+d(2))*q+d(3))*q+d(4))*q+1); } return x; } //return -1 if v is negative and 1 if v >= 0 template T sign(const T& v) { return (v < 0) ? (T)-1 : (T)1; } /// compute volume of unit n-ball living in n-dimensional space with n>=1; results are cached for O(1) runtime extern CGV_API double compute_unit_ball_volume(unsigned n); /// compute volume of n-ball of radius R living in n-dimensional space with n>=1; results are cached for O(1) runtime extern CGV_API double compute_ball_volume(unsigned n, double R); /// compute surface area of a unit n-ball living in n-dimensional space with n>=2 (this is a n-1 dimensional area); results are cached for O(1) runtime extern CGV_API double compute_unit_sphere_area(unsigned n); /// compute surface area of a n-ball of radius R living in n-dimensional space with n>=2 (this is a n-1 dimensional area); results are cached for O(1) runtime extern CGV_API double compute_sphere_area(unsigned n, double R); //returns v*v template T sqr(const T& v) { return v*v; } //return the maximum of a and b template T maximum(const T& a, const T&b) { return a > b ? a : b; } //return minimum of a and b template T minimum(const T &a, const T&b) { return a < b ? a : b; } //return the maximum of a, b and c template T maximum(const T& a, const T&b, const T& c) { if(a > b) { return a > c ? a : c; } else { return b > c ? b : c; } } //return the minimum of a, b and c template T minimum(const T& a, const T&b, const T& c) { if(a < b) { return a < c ? a : c; } else { return b < c ? b : c; } } //convert angles measured in degree to angles measured in rad template T deg2rad(const T& deg) { return (T)(deg *3.14159/180.0); } //convert angles measured in rad to angles measured in degree template T rad2deg(const T& rad) { return (T)(rad*180.0/3.14159); } //ln(gamma(x)) extern CGV_API double gamma_ln(const double xx); //factorial of n (n!) extern CGV_API double fac(const int n); //returns ln(n!) extern CGV_API double fac_ln(const int n); //beta function extern CGV_API double beta(const double z, const double w); //binomial coefficient n over k extern CGV_API double nchoosek(const int n, const int k); //returns 0 if v < th otherwise 1 template T thresh(const T v,const T th) { if(v < th) return (T)0; else return (T)1; } } } #include