contrib/brl/bbas/bsta/bsta_gaussian_indep.txx
Go to the documentation of this file.
00001 // This is brl/bbas/bsta/bsta_gaussian_indep.txx
00002 #ifndef bsta_gaussian_indep_txx_
00003 #define bsta_gaussian_indep_txx_
00004 //:
00005 // \file
00006 
00007 #include "bsta_gaussian_indep.h"
00008 #include <vcl_limits.h>
00009 #include <vnl/vnl_erf.h>
00010 
00011 namespace
00012 {
00013   //: Unrol the mahalanobis distance calculation
00014   template <class T, unsigned n, unsigned index>
00015   struct bsta_gaussian_indep_compute_sqr_mahalanobis
00016   {
00017     static inline T value(const vnl_vector_fixed<T,n>& d,
00018                           const vnl_vector_fixed<T,n>& covar)
00019     {
00020       return d[index-1]*d[index-1]/covar[index-1]
00021         + bsta_gaussian_indep_compute_sqr_mahalanobis<T,n,index-1>::value(d,covar);
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_indep_compute_sqr_mahalanobis<T,n,0>
00029   {
00030     static inline T value(const vnl_vector_fixed<T,n>& /*d*/,
00031                           const vnl_vector_fixed<T,n>& /*covar*/)
00032     { return 0; }
00033   };
00034 
00035 
00036   //: Unrol the determinant calculation
00037   template <class T, unsigned n, unsigned index>
00038   struct bsta_gaussian_indep_determinant
00039   {
00040     static inline T value(const vnl_vector_fixed<T,n>& covar)
00041     {
00042       return covar[index-1]*bsta_gaussian_indep_determinant<T,n,index-1>::value(covar);
00043     }
00044   };
00045 
00046   //: base case
00047   //  This is partial specialization: expect MSVC6 to complain
00048   template <class T, unsigned n>
00049   struct bsta_gaussian_indep_determinant<T,n,0>
00050   {
00051     static inline T value(const vnl_vector_fixed<T,n>& /*covar*/)
00052     { return 1; }
00053   };
00054 };
00055 
00056 
00057 //: The squared Mahalanobis distance to this point
00058 template <class T, unsigned int n>
00059 T
00060 bsta_gaussian_indep<T,n>::sqr_mahalanobis_dist(const vnl_vector_fixed<T,n>& pt) const
00061 {
00062   if (det_covar_<=T(0))
00063     return vcl_numeric_limits<T>::infinity();
00064   vnl_vector_fixed<T,n> d = bsta_gaussian<T,n>::mean_-pt;
00065   return bsta_gaussian_indep_compute_sqr_mahalanobis<T,n,n>::value(d,diag_covar_);
00066 }
00067 
00068 
00069 //: The determinant of the covariance matrix
00070 template <class T, unsigned int n>
00071 void
00072 bsta_gaussian_indep<T,n>::compute_det()
00073 {
00074   det_covar_ = bsta_gaussian_indep_determinant<T,n,n>::value(diag_covar_);
00075 }
00076 
00077 //: Unrol the compute probability calculation
00078 //  The general induction step
00079 template <class T, unsigned n, unsigned index>
00080 struct bsta_gaussian_indep_compute_probability_box
00081 {
00082   static inline T value(const vnl_vector_fixed<T,n>& min_minus_mean,
00083                         const vnl_vector_fixed<T,n>& max_minus_mean,
00084                         const vnl_vector_fixed<T,n>& covar
00085                        )
00086   {
00087     if (covar[index]<=T(0))
00088       return vcl_numeric_limits<T>::infinity();
00089     double sigma_sq_2 = 2.0*static_cast<double>(covar[index]);
00090     double s2 = 1/vcl_sqrt(sigma_sq_2);
00091     double temp = vnl_erf(max_minus_mean[index]*s2);
00092     temp -= vnl_erf(min_minus_mean[index]*s2);
00093     T res = static_cast<T>(0.5*temp);
00094     res *= bsta_gaussian_indep_compute_probability_box<T,n,index-1>::value(min_minus_mean,
00095                                                                            max_minus_mean,
00096                                                                            covar);
00097     return res;
00098   }
00099 };
00100 
00101 //: base case
00102 //  This is partial specialization: expect MSVC6 to complain
00103 template <class T, unsigned n>
00104 struct bsta_gaussian_indep_compute_probability_box<T,n,0>
00105 {
00106   static inline T value(const vnl_vector_fixed<T,n>& min_minus_mean,
00107                         const vnl_vector_fixed<T,n>& max_minus_mean,
00108                         const vnl_vector_fixed<T,n>& covar)
00109   {
00110     if (covar[0]<=T(0))
00111       return vcl_numeric_limits<T>::infinity();
00112     double sigma_sq_2 = 2.0*static_cast<double>(covar[0]);
00113     double s2 = 1/vcl_sqrt(sigma_sq_2);
00114     double temp = vnl_erf(max_minus_mean[0]*s2);
00115     temp -= vnl_erf(min_minus_mean[0]*s2);
00116     return static_cast<T>(0.5*temp);
00117   };
00118 };
00119 
00120 //: The probability that a sample lies inside a n-d bounding box
00121 //  \note min_pt and max_pt are the corners of the box
00122 template <class T, unsigned int n>
00123 T bsta_gaussian_indep<T,n>::probability(const vnl_vector_fixed<T,n>& min_pt,
00124                                         const vnl_vector_fixed<T,n>& max_pt) const
00125 {
00126   vnl_vector_fixed<T,n> min_minus_mean = min_pt-bsta_gaussian<T,n>::mean_;
00127   vnl_vector_fixed<T,n> max_minus_mean = max_pt-bsta_gaussian<T,n>::mean_;
00128   return bsta_gaussian_indep_compute_probability_box<T, n, n-1>::value(min_minus_mean,
00129                                                                        max_minus_mean,
00130                                                                        diag_covar_);
00131 }
00132 
00133 //: Gradient vector at this point
00134 template <class T, unsigned int n>
00135 vnl_vector_fixed<T,n> bsta_gaussian_indep<T,n>::gradient(const vnl_vector_fixed<T,n>& pt) const
00136 {
00137   T pd = prob_density(pt);
00138   vnl_vector_fixed<T,n> h((pt[0]-this->mean_[0])/diag_covar_[0], (pt[1] - this->mean_[1])/diag_covar_[1], (pt[2] - this->mean_[2])/diag_covar_[2]);
00139   return -pd * h;
00140 }
00141 
00142 
00143 #define BSTA_GAUSSIAN_INDEP_INSTANTIATE(T,n) \
00144 template class bsta_gaussian_indep<T,n >
00145 
00146 
00147 #endif // bsta_gaussian_indep_txx_