00001
00002 #ifndef bsta_von_mises_txx_
00003 #define bsta_von_mises_txx_
00004
00005
00006
00007
00008
00009
00010 #include "bsta_von_mises.h"
00011 #include <vcl_cassert.h>
00012 #include <vcl_limits.h>
00013 #include <vnl/vnl_math.h>
00014
00015 namespace
00016 {
00017
00018 template <class T, unsigned n, unsigned index>
00019 struct bsta_von_mises_compute_dot
00020 {
00021 static inline T value(const vnl_vector_fixed<T,n>& v0,
00022 const vnl_vector_fixed<T,n>& v1)
00023 {
00024 return v0[index-1]*v1[index-1]
00025 + bsta_von_mises_compute_dot<T,n,index-1>::value(v0, v1);
00026 }
00027 };
00028
00029
00030
00031 template <class T, unsigned n>
00032 struct bsta_von_mises_compute_dot<T,n,0>
00033 {
00034 static inline T value(const vnl_vector_fixed<T,n>& ,
00035 const vnl_vector_fixed<T,n>& )
00036 { return 0; }
00037 };
00038
00039
00040
00041 template <class T>
00042 struct bsta_von_mises_compute_dot<T,1,1>
00043 {
00044 static inline T value(const T& v0, const T& v1)
00045 { return v0*v1; }
00046 };
00047
00048 double I0(double X)
00049 {
00050 double Y,P1,P2,P3,P4,P5,P6,P7,Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8,Q9,AX,BX;
00051 P1=1.0; P2=3.5156229; P3=3.0899424; P4=1.2067429;
00052 P5=0.2659732; P6=0.360768e-1; P7=0.45813e-2;
00053 Q1=0.39894228; Q2=0.1328592e-1; Q3=0.225319e-2;
00054 Q4=-0.157565e-2; Q5=0.916281e-2; Q6=-0.2057706e-1;
00055 Q7=0.2635537e-1; Q8=-0.1647633e-1; Q9=0.392377e-2;
00056 if (vcl_fabs(X) < 3.75) {
00057 Y=(X/3.75)*(X/3.75);
00058 return P1+Y*(P2+Y*(P3+Y*(P4+Y*(P5+Y*(P6+Y*P7)))));
00059 }
00060 else {
00061 AX=vcl_fabs(X);
00062 Y=3.75/AX;
00063 BX=vcl_exp(AX)/vcl_sqrt(AX);
00064 AX=Q1+Y*(Q2+Y*(Q3+Y*(Q4+Y*(Q5+Y*(Q6+Y*(Q7+Y*(Q8+Y*Q9)))))));
00065 return AX*BX;
00066 }
00067 }
00068 }
00069
00070 #if VCL_CAN_DO_PARTIAL_SPECIALIZATION
00071 template <class T>
00072 T bsta_von_mises<T,3>::prob_density( typename bsta_von_mises<T,3>::vector_type const& v) const
00073 {
00074 T dpt = bsta_von_mises_compute_dot<T,3,3>::value(mean_, v);
00075 double dp = static_cast<double>(dpt);
00076 double k = static_cast<double>(kappa_);
00077 double ex = vcl_exp(k*dp);
00078 double norm = k/(vcl_exp(k)-vcl_exp(-k));
00079 norm /= 2.0*vnl_math::pi;
00080 return static_cast<T>(norm*ex);
00081 }
00082
00083 template <class T>
00084 T bsta_von_mises<T,3>::probability(typename bsta_von_mises<T,3>::vector_type const& v,const T theta_max) const
00085 {
00086
00087
00088 vector_type nv = v;
00089 nv.normalize();
00090 double cos_gam = static_cast<double>(bsta_von_mises_compute_dot<T,3,3>::value(mean_, nv));
00091 if (cos_gam>1.0) cos_gam=1.0;
00092 if (cos_gam<-1.0) cos_gam=-1.0;
00093 double gam = vcl_acos(cos_gam);
00094 double sin_gam = vcl_sin(gam),cos_2_gam = vcl_cos(2.0*gam);
00095 double cos_4_gam = vcl_cos(4.0*gam), tan_gam = sin_gam/cos_gam;
00096 double cos_gam_3 = cos_gam*cos_gam*cos_gam;
00097 double cos_theta_m = vcl_cos(theta_max);
00098 double cos_2_theta_m = vcl_cos(2.0*theta_max);
00099 double kap = static_cast<double>(kappa_);
00100 double prob = 0.0;
00101 if (kap<25) {
00102 double e_kap = vcl_exp(kap);
00103 double e_2_kap = e_kap*e_kap;
00104 double e_kap_cos_gam = vcl_exp(kap*cos_gam);
00105 double e_kap_cgam_cthm = vcl_exp(kap*cos_gam*cos_theta_m);
00106 double t1 = -1.0/(64.0*(e_2_kap -1));
00107 double t2 = (e_kap_cos_gam - e_kap_cgam_cthm);
00108 double t3 = (e_kap_cos_gam - cos_2_theta_m*e_kap_cgam_cthm);
00109 double t3a = (e_kap_cos_gam - cos_theta_m*e_kap_cgam_cthm);
00110 double t4 = (-16 + kap*kap*(cos_4_gam -1.0)-48.0*cos_2_gam);
00111 double t5 = t2*t4/cos_gam_3;
00112 double t6 = kap*t3*sin_gam - 4.0*tan_gam*t3a;
00113 double t7 = 8.0*kap*tan_gam*t6;
00114 double t8 = e_kap*(t5+t7);
00115 prob = t1*t8;
00116 }
00117 else {
00118 double e_kap_cos_gam = vcl_exp(kap*(cos_gam-1.0));
00119 double e_kap_cgam_cthm = vcl_exp(kap*(cos_gam*cos_theta_m-1.0));
00120 double t1 = -1.0/(64.0);
00121 double t2 = (e_kap_cos_gam - e_kap_cgam_cthm);
00122 double t3 = (e_kap_cos_gam - cos_2_theta_m*e_kap_cgam_cthm);
00123 double t3a = (e_kap_cos_gam - cos_theta_m*e_kap_cgam_cthm);
00124 double t4 = (-16 + kap*kap*(cos_4_gam -1.0)-48.0*cos_2_gam);
00125 double t5 = t2*t4/cos_gam_3;
00126 double t6 = kap*t3*sin_gam - 4.0*tan_gam*t3a;
00127 double t7 = 8.0*kap*tan_gam*t6;
00128 double t8 = t5+t7;
00129 if (t8==0)
00130 prob = t8;
00131 else
00132 prob = t1*t8;
00133 }
00134 return static_cast<T>(prob);
00135 }
00136
00137 template <class T>
00138 T bsta_von_mises<T,2>::prob_density(typename bsta_von_mises<T,2>::vector_type const& v) const
00139 {
00140 T dpt = bsta_von_mises_compute_dot<T,2,2>::value(mean_, v);
00141 double dp = static_cast<double>(dpt);
00142 double k = static_cast<double>(kappa_);
00143 double ex = vcl_exp(k*dp);
00144 double i0 = I0(k);
00145 double norm = 1.0/i0;
00146 norm /= 2.0*vnl_math::pi;
00147 return static_cast<T>(norm*ex);
00148 }
00149 #endif //VCL_CAN_DO_PARTIAL_SPECIALIZATION
00150
00151
00152 #define BSTA_VON_MISES_INSTANTIATE(T,n) \
00153 template class bsta_von_mises<T,n >
00154
00155
00156 #endif // bsta_von_mises_txx_