contrib/brl/bbas/bsta/bsta_gaussian_sphere.txx
Go to the documentation of this file.
00001 // This is brl/bbas/bsta/bsta_gaussian_sphere.txx
00002 #ifndef bsta_gaussian_sphere_txx_
00003 #define bsta_gaussian_sphere_txx_
00004 //:
00005 // \file
00006 
00007 #include "bsta_gaussian_sphere.h"
00008 #include <vcl_cassert.h>
00009 #include <vcl_limits.h>
00010 #include <vnl/vnl_erf.h>
00011 
00012 namespace
00013 {
00014   //: Unrol the Mahalanobis distance calculation
00015   template <class T, unsigned n, unsigned index>
00016   struct bsta_gaussian_sphere_compute_dot
00017   {
00018     static inline T value(const vnl_vector_fixed<T,n>& d)
00019     {
00020       return d[index-1]*d[index-1]
00021            + bsta_gaussian_sphere_compute_dot<T,n,index-1>::value(d);
00022     }
00023   };
00024 
00025   //: base case
00026   // this is partial specialization: expect MSVC6 to complain
00027   template <class T, unsigned n>
00028   struct bsta_gaussian_sphere_compute_dot<T,n,0>
00029   {
00030     static inline T value(const vnl_vector_fixed<T,n>& /*d*/)
00031     { return 0; }
00032   };
00033 
00034   //: base case
00035   // this is partial specialization: expect MSVC6 to complain
00036   template <class T>
00037       struct bsta_gaussian_sphere_compute_dot<T,1,1>
00038   {
00039     static inline T value(const T& d)
00040     { return d*d; }
00041   };
00042 
00043 
00044   //: Unroll the determinant calculation
00045   template <class T, unsigned n, unsigned index>
00046   struct bsta_gaussian_sphere_determinant
00047   {
00048     static inline T value(const T& var)
00049     {
00050       return var * bsta_gaussian_sphere_determinant<T,n,index-1>::value(var);
00051     }
00052   };
00053 
00054   //: base case
00055   // this is partial specialization: expect MSVC6 to complain
00056   template <class T, unsigned n>
00057   struct bsta_gaussian_sphere_determinant<T,n,0>
00058   {
00059     static inline T value(const T& /*var*/) { return 1; }
00060   };
00061 } // namespace
00062 
00063 
00064 //: The squared Mahalanobis distance to this point
00065 template <class T, unsigned int n>
00066 T
00067 bsta_gaussian_sphere<T,n>::sqr_mahalanobis_dist(const vector_& pt) const
00068 {
00069   if (var_<=T(0))
00070     return vcl_numeric_limits<T>::infinity();
00071   vector_ d = bsta_gaussian<T,n>::mean_-pt;
00072   return bsta_gaussian_sphere_compute_dot<T,n,n>::value(d)/var_;
00073 }
00074 
00075 //: Unrol the compute probability calculation
00076 //  The general induction step
00077 template <class T, class vector_, unsigned n, unsigned index>
00078 struct bsta_gaussian_sphere_compute_probability_box
00079 {
00080   static inline T value(const vector_& min_minus_mean,
00081                         const vector_& max_minus_mean,
00082                         const T& var
00083                        )
00084   {
00085     if (var<=T(0))
00086       return vcl_numeric_limits<T>::infinity();
00087     double sigma_sq_2 = 2.0*static_cast<double>(var);
00088     double s2 = 1/vcl_sqrt(sigma_sq_2);
00089     double temp = vnl_erf(max_minus_mean[index]*s2);
00090     temp -= vnl_erf(min_minus_mean[index]*s2);
00091     T res = static_cast<T>(0.5*temp);
00092     res *= bsta_gaussian_sphere_compute_probability_box<T,vector_,n,index-1>::value(min_minus_mean,
00093                                                                                     max_minus_mean,
00094                                                                                     var);
00095     return res;
00096   }
00097 };
00098 
00099 //: base case
00100 //  This is partial specialization: expect MSVC6 to complain
00101 template <class T, class vector_, unsigned n>
00102 struct bsta_gaussian_sphere_compute_probability_box<T,vector_,n,0>
00103 {
00104   static inline T value(const vector_& min_minus_mean,
00105                         const vector_& max_minus_mean,
00106                         const T& var)
00107   {
00108     if (var<=T(0))
00109       return vcl_numeric_limits<T>::infinity();
00110     double sigma_sq_2 = 2.0*static_cast<double>(var);
00111     double s2 = 1/vcl_sqrt(sigma_sq_2);
00112     double temp = vnl_erf(max_minus_mean[0]*s2);
00113     temp -= vnl_erf(min_minus_mean[0]*s2);
00114     return static_cast<T>(0.5*temp);
00115   }
00116 };
00117 
00118 
00119 //: base case
00120 //  This is partial specialization: expect MSVC6 to complain
00121 template <class T, class vector_>
00122 struct bsta_gaussian_sphere_compute_probability_box<T,vector_,1,0>
00123 {
00124   static inline T value(const vector_& min_minus_mean,
00125                         const vector_& max_minus_mean,
00126                         const T& var)
00127   {
00128     if (var<=T(0))
00129       return vcl_numeric_limits<T>::infinity();
00130     double sigma_sq_2 = 2.0*static_cast<double>(var);
00131     double s2 = 1/vcl_sqrt(sigma_sq_2);
00132     double temp = vnl_erf(max_minus_mean*s2);
00133     temp -= vnl_erf(min_minus_mean*s2);
00134     return static_cast<T>(0.5*temp);
00135   };
00136 };
00137 
00138 //: The probability that a sample lies inside a n-d bounding box
00139 //  \note min_pt and max_pt are the corners of the box
00140 template <class T, unsigned int n>
00141 T bsta_gaussian_sphere<T,n>::probability(const vector_& min_pt,
00142                                          const vector_& max_pt) const
00143 {
00144   vector_ min_minus_mean = min_pt-bsta_gaussian<T,n>::mean_;
00145   vector_ max_minus_mean = max_pt-bsta_gaussian<T,n>::mean_;
00146   return bsta_gaussian_sphere_compute_probability_box<T, vector_, n, n-1>::value(min_minus_mean,
00147                                                                                  max_minus_mean,
00148                                                                                  var_);
00149 }
00150 
00151 //: The determinant of the covariance matrix
00152 template <class T, unsigned int n>
00153 void
00154 bsta_gaussian_sphere<T,n>::compute_det()
00155 {
00156   det_covar_ = bsta_gaussian_sphere_determinant<T,n,n>::value(var_);
00157   assert(det_covar_ >= 0);
00158 }
00159 
00160 
00161 //: Unrol the sampling calculation
00162 //  The general induction step
00163 template <class T, class vector_, unsigned n, unsigned index>
00164 struct var_from_dist
00165 {
00166   static inline vector_ value(const T& var, vnl_random& rng)
00167   {
00168     T s = (T)(vcl_sqrt(var)*rng.normal());
00169     vector_ res(T(0));
00170     res[index] = s;
00171     res += var_from_dist<T,vector_,n,index-1>::value(var, rng);
00172     return res;
00173   }
00174 };
00175 
00176 //: base case
00177 //  This is partial specialization: expect MSVC6 to complain
00178 template <class T, class vector_, unsigned n>
00179 struct var_from_dist<T,vector_,n,0>
00180 {
00181   static inline vector_ value(const T& var, vnl_random& rng)
00182   {
00183     T s = (T)(vcl_sqrt(var)*rng.normal());
00184     vector_ res(T(0));
00185     res[0] = s;
00186     return res;
00187   };
00188 };
00189 
00190 
00191 //: base case
00192 //  This is partial specialization: expect MSVC6 to complain
00193 template <class T, class vector_>
00194 struct var_from_dist<T,vector_,1,0>
00195 {
00196   static inline vector_ value(const T& var, vnl_random& rng)
00197   {
00198     T s = (T)(vcl_sqrt(var)*rng.normal());
00199     vector_ res(s);
00200     return res;
00201   };
00202 };
00203 
00204 
00205 //: sample
00206 template <class T, unsigned int n>
00207 typename bsta_gaussian_sphere<T,n>::vector_ bsta_gaussian_sphere<T,n>::sample(vnl_random& rng) const
00208 {
00209   vector_ mean = bsta_gaussian<T,n>::mean_;
00210   vector_ var = var_from_dist<T, vector_, n, n-1>::value(var_, rng);
00211   return mean+var;
00212 }
00213 
00214 #define BSTA_GAUSSIAN_SPHERE_INSTANTIATE(T,n) \
00215 template class bsta_gaussian_sphere<T,n >
00216 
00217 
00218 #endif // bsta_gaussian_sphere_txx_