core/vnl/vnl_sample.cxx
Go to the documentation of this file.
00001 // This is core/vnl/vnl_sample.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vnl_sample.h"
00007 #include <vnl/vnl_math.h>
00008 
00009 #include <vcl_cmath.h>
00010 #include <vxl_config.h>
00011 
00012 #if VXL_STDLIB_HAS_DRAND48
00013 # include <stdlib.h> // dont_vxl_filter
00014 #else
00015 // rand() is not always a good random number generator,
00016 // so use a simple congruential random number generator when drand48 not available - PVr
00017 static unsigned long vnl_sample_seed = 12345;
00018 #endif
00019 
00020 # include <vcl_ctime.h>
00021 
00022 void vnl_sample_reseed()
00023 {
00024 #if VXL_STDLIB_HAS_SRAND48
00025   srand48( vcl_time(0) );
00026 #elif !VXL_STDLIB_HAS_DRAND48
00027   vnl_sample_seed = (unsigned long)vcl_time(0);
00028 #endif
00029 }
00030 
00031 void vnl_sample_reseed(int seed)
00032 {
00033 #if VXL_STDLIB_HAS_SRAND48
00034   srand48( seed );
00035 #elif !VXL_STDLIB_HAS_DRAND48
00036   vnl_sample_seed = seed;
00037 #endif
00038 }
00039 
00040 double vnl_sample_uniform(double a, double b)
00041 {
00042 #if VXL_STDLIB_HAS_DRAND48
00043   double u = drand48(); // uniform on [0, 1)
00044 #else
00045 // rand() is not always a good random number generator,
00046 // so use a simple congruential random number generator when drand48 not available - PVr
00047   vnl_sample_seed = (vnl_sample_seed*16807)%2147483647L;
00048   double u = double(vnl_sample_seed)/2147483647L; // uniform on [0, 1)
00049 #endif
00050   return (1.0 - u)*a + u*b;
00051 }
00052 
00053 void vnl_sample_normal_2(double *x, double *y)
00054 {
00055   double u     = vnl_sample_uniform(1, 0); // not (0,1): should not return 0
00056   double theta = vnl_sample_uniform(0, 2 * vnl_math::pi);
00057 
00058   double r = vcl_sqrt(-2*vcl_log(u));
00059 
00060   if (x) *x = r * vcl_cos(theta);
00061   if (y) *y = r * vcl_sin(theta);
00062 }
00063 
00064 double vnl_sample_normal(double mean, double sigma)
00065 {
00066   double x;
00067   vnl_sample_normal_2(&x, 0);
00068   return mean + sigma * x;
00069 }
00070 
00071 // Implementation of Bernoulli sampling by Peter Vanroose
00072 int vnl_sample_bernoulli(double q)
00073 {
00074   // quick return if possible:
00075   if (q==0.0) return 0;
00076   if (q==1.0) return 1;
00077   if (q<0.0 || q>1.0) return -1;
00078   // q should be the probability of returning 0:
00079   return (vnl_sample_uniform(0.0, 1.0/q) >= 1.0) ? 1 : 0;
00080 }
00081 
00082 // Implementation of binomial sampling by Peter Vanroose
00083 int vnl_sample_binomial(int n, double q)
00084 {
00085   // Returns a random "k" value, between 0 and n, viz. the sum of n random
00086   // and independent drawings from a Bernoulli distribution with parameter q.
00087 
00088   if (n <= 0 || q<0.0 || q>1.0) return -1; // That is: when the input makes no sense, return nonsense "-1".
00089   if (q==0.0) return 0;
00090   if (q==1.0) return n;
00091   int k = 0;
00092   for (int i=n-1; i>=0; --i) {
00093     k += vnl_sample_bernoulli(q);
00094   }
00095   return k;
00096 }