MathFunctions.C

Go to the documentation of this file.
00001 /*!@file Util/MathFunctions.C Miscellaneous math functions */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Util/MathFunctions.C $
00035 // $Id: MathFunctions.C 14590 2011-03-10 22:25:43Z lior $
00036 //
00037 
00038 #include "Util/MathFunctions.H"
00039 #include "Util/log.H"
00040 #include <cmath>
00041 #include <sys/types.h> // for getpid()
00042 #include <unistd.h>    // for getpid()
00043 
00044 // ######################################################################
00045 bool isFinite(const byte& arg) { return true; }
00046 bool isFinite(const int16& arg) { return true; }
00047 bool isFinite(const int32& arg) { return true; }
00048 
00049 #if !defined(MISSING_ISINF)
00050 bool isFinite(const float& arg) { return !isinf(arg); }
00051 bool isFinite(const double& arg) { return !isinf(arg); }
00052 #elif defined(HAVE_STD_ISFINITE)
00053 bool isFinite(const float& arg) { return std::isfinite(arg); }
00054 bool isFinite(const double& arg) { return std::isfinite(arg); }
00055 #elif defined(HAVE_ISFINITE)
00056 bool isFinite(const float& arg) { return isfinite(arg); }
00057 bool isFinite(const double& arg) { return isfinite(arg); }
00058 #elif defined(HAVE___ISFINITEF)
00059 // Use built-in functions, e.g. on Mac OSX
00060 bool isFinite(const float& arg) { return __isfinitef(arg); }
00061 bool isFinite(const double& arg) { return __isfinited(arg); }
00062 #else
00063 bool isFinite(const float& arg) { return true; }
00064 bool isFinite(const double& arg) { return true; }
00065 #endif
00066 
00067 // #####################################################################
00068 void initRandomNumbers()
00069 {
00070 #ifdef HAVE_SRAND48
00071   srand48(time(0) + getpid() * 123);
00072 #endif
00073   srand(time(0) + getpid() * 345);
00074 }
00075 
00076 // #####################################################################
00077 void initRandomNumbersZero()
00078 {
00079 #ifdef HAVE_SRAND48
00080   srand48(0);
00081 #endif
00082   srand(0);
00083 }
00084 
00085 // #####################################################################
00086 double randomDouble()
00087 {
00088 #ifdef HAVE_SRAND48
00089   return drand48();
00090 #else
00091   return double(rand()) / (double(RAND_MAX) + 1.0);
00092 #endif
00093 }
00094 
00095 // #####################################################################
00096 double randomDoubleFromNormal(const double s)
00097 {
00098         double sum = 0;
00099         for(int i=0; i<12; i++){
00100                 sum += randomDouble()*2*s - s;
00101         }
00102         return sum/2;
00103 }
00104 
00105 // #####################################################################
00106 int randomUpToIncluding(const int n)
00107 {
00108   return randomUpToNotIncluding(n + 1);
00109 }
00110 
00111 // #####################################################################
00112 int randomUpToNotIncluding(const int n)
00113 {
00114   // NOTE: we don't do (RAND%n) because the low-order bits of the
00115   // random number may be less random than the high-order bits
00116 
00117   const int result = int(randomDouble() * n);
00118 
00119   // randomDouble() is supposed to be in [0.0, 1.0), but just in case
00120   // randomDouble()*n happens to equal n due to floating-point
00121   // weirdness, let's return n-1 to fulfill the "NotIncluding" part of
00122   // our contract:
00123   if (result == n)
00124     return n-1;
00125 
00126   return result;
00127 }
00128 
00129 // #####################################################################
00130 double ran2 (int& idum)
00131 {
00132   const int IM1 = 2147483563, IM2 = 2147483399;
00133   const double AM = (1.0/IM1);
00134   const int IMM1 = IM1-1;
00135   const int IA1 = 40014, IA2 = 40692, IQ1 = 53668, IQ2 = 52774;
00136   const int IR1 = 12211, IR2 = 3791, NTAB = 32;
00137   const int NDIV = 1+IMM1/NTAB;
00138   const double EPS = 3.0e-16, RNMX = 1.0-EPS;
00139 
00140   int j, k;
00141   static int idum2 = 123456789, iy = 0;
00142   static int iv[NTAB];
00143   double temp;
00144 
00145   if (idum <= 0) {
00146     idum = (idum == 0 ? 1 : -idum);
00147     idum2=idum;
00148     for (j=NTAB+7;j>=0;j--) {
00149       k=idum/IQ1;
00150       idum=IA1*(idum-k*IQ1)-k*IR1;
00151       if (idum < 0) idum += IM1;
00152       if (j < NTAB) iv[j] = idum;
00153     }
00154     iy=iv[0];
00155   }
00156   k=idum/IQ1;
00157   idum=IA1*(idum-k*IQ1)-k*IR1;
00158 
00159   if (idum < 0) idum += IM1;
00160   k=idum2/IQ2;
00161   idum2=IA2*(idum2-k*IQ2)-k*IR2;
00162   if (idum2 < 0) idum2 += IM2;
00163   j=iy/NDIV;
00164   iy=iv[j]-idum2;
00165   iv[j] = idum;
00166   if (iy < 1) iy += IMM1;
00167   if ((temp=AM*iy) > RNMX) return RNMX;
00168   else return temp;
00169 }
00170 
00171 // ######################################################################
00172 int getIdum(const bool useRandom)
00173 {
00174   if (useRandom)
00175     return -(time(NULL) + 17 * getpid());
00176   else
00177     return -123456;
00178 }
00179 
00180 // ######################################################################
00181 double gasdev (int& idum) {
00182   static int iset = 0;
00183   static double gset;
00184 
00185   double fac, rsq, v1, v2;
00186   if (idum < 0) iset = 0;
00187   if (iset == 0) {
00188     do {
00189       v1 = 2.0*ran2(idum)-1.0;
00190       v2 = 2.0*ran2(idum)-1.0;
00191       rsq = v1*v1 + v2*v2;
00192     } while (rsq >= 1.0 || rsq == 0.0);
00193 
00194     fac = std::sqrt(-2.0*std::log(rsq)/rsq);
00195     gset = v1*fac; iset = 1;
00196     return v2*fac;
00197   } else {
00198     iset = 0;
00199     return gset;
00200   }
00201 }
00202 
00203 // ######################################################################
00204 double expdev(int& idum)
00205 {
00206   double dum;
00207   do dum = ran2(idum); while (dum == 0.0);
00208   return -log(dum);
00209 }
00210 
00211 /* Lanczos method for real x > 0;
00212  * gamma=7, truncated at 1/(z+8)
00213  * [J. SIAM Numer. Anal, Ser. B, 1 (1964) 86]
00214  */
00215 double lngamma(double x)
00216 {
00217 
00218 #ifdef HAVE_LGAMMA
00219   return lgamma(x);
00220 #else
00221 
00222   // ripped from GSL (see above).
00223   /* coefficients for gamma=7, kmax=8  Lanczos method */
00224   static const double lanczos_7_c[9] = {
00225     0.99999999999980993227684700473478,
00226     676.520368121885098567009190444019,
00227     -1259.13921672240287047156078755283,
00228     771.3234287776530788486528258894,
00229     -176.61502916214059906584551354,
00230     12.507343278686904814458936853,
00231     -0.13857109526572011689554707,
00232     9.984369578019570859563e-6,
00233     1.50563273514931155834e-7
00234   };
00235 
00236   x -= 1.0; /* Lanczos writes z! instead of Gamma(z) */
00237 
00238   double Ag = lanczos_7_c[0];
00239   for (int k = 1; k <= 8; k++) { Ag += lanczos_7_c[k] / (x+k); }
00240 
00241   /* (x+0.5)*log(x+7.5) - (x+7.5) + LogRootTwoPi_ + log(Ag(x)) */
00242   const double term1 = (x + 0.5) * log((x + 7.5) / M_E);
00243   const double term2 = D_LOG_SQRT_2_PI + log(Ag);
00244   return term1 + (term2 - 7.0);
00245 #endif
00246 }
00247 
00248 // ripped from GSL (see above). Compute probability of getting a value
00249 // k from a Poisson distribution with mean mu:
00250 double poisson(const unsigned int k, const double mu)
00251 {
00252   double lf = lngamma(k+1);
00253   return exp(log(mu) * k - lf - mu);
00254 }
00255 
00256 //computes the AUC, inspired by ROC, between two data sets
00257 //the intended use is to compare human eye movements to a random
00258 //model
00259 double AUC(const float* model, const float* rand,
00260                                 size_t sm, size_t sr,
00261                                 const double step)
00262 {
00263         //if ((max(model) > 1.0F) || (max(rand) > 1.0F)
00264         //|| (min(model) < 0.0F) || (min(rand) < 0.0F))
00265         //LFATAL("Vectors must be normalized");
00266 
00267     double auc = 0.0;
00268     double last_tp = 1.0;
00269     double last_fp = 1.0;
00270 
00271     for (double thresh = 0.0; thresh <= 1.0+step; thresh+=step)
00272     {
00273         uint tp = 0;
00274         uint fp = 0;
00275         for (size_t jj = 0; jj < sm; ++jj)
00276             if (model[jj] >= thresh)
00277                 tp++;
00278 
00279         for (size_t jj = 0; jj < sr; ++jj)
00280             if (rand[jj] >= thresh)
00281                 fp++;
00282 
00283         double fpr = (double)fp/(double)sr;
00284         double tpr = (double)tp/(double)sm;
00285 
00286         auc+= ( (last_fp - fpr) * (tpr) ) +
00287             ( 0.5 * (last_fp - fpr) * (last_tp - tpr) );
00288 
00289         last_tp = tpr;
00290         last_fp = fpr;
00291     }
00292     return auc;
00293 }
00294 
00295 Point2D<float> getEllipseFromCov(const Image<double>& cov)
00296 {
00297   ASSERT(cov.getWidth() == 2 && cov.getHeight() == 2);
00298 
00299   //Using matlab Compute the Mahalanobis radius of the ellipsoid that encloses
00300   //the desired probability mass.
00301   //k = chi2inv(p, 2); where p = 0.9
00302 
00303   double k = 4.605170185988091; //From matlab 
00304 
00305   //Compute the eigen values
00306   double trace = (cov.getVal(0,0) + cov.getVal(1,1))/2;
00307 
00308   double a = cov.getVal(0,0) - trace;
00309   double b = cov.getVal(0,1);
00310 
00311   double ab2 = sqrt((a*a) + (b*b));
00312 
00313   double l1 = ab2 + trace;
00314   double l2 = -ab2 + trace;
00315 
00316   return Point2D<float>(k*sqrt(l1), k*sqrt(l2));
00317 
00318 }
00319 
00320 
00321 // ######################################################################
00322 /* So things look consistent in everyone's emacs... */
00323 /* Local Variables: */
00324 /* indent-tabs-mode: nil */
00325 /* End: */
Generated on Sun May 8 08:42:26 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3