home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / Normal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-04  |  4.7 KB  |  168 lines  |  [TEXT/KAHL]

  1. /*
  2. Normal.c
  3. statistical functions related to the normal distribution.
  4. Copyright (c) 1989,1990,1991,1992 Denis G. Pelli
  5. HISTORY:
  6. 1989    dgp wrote it.
  7. 4/8/90    dgp    changed the names of the routines. 
  8.             Made sure that domain error produces NAN.
  9. 6/90    dgp    added NormalSample()
  10. 7/30/91    dgp    now use NAN defined in VideoToolbox.h
  11. 12/28/91 dgp sped up NormalPdf() by calculating the scale factor only once
  12. 12/29/91 dgp extracted code to create new routine UniformSample.c
  13. 1/11/92    dgp    rewrote Normal()'s polynomial evaluation to halve the number of multiplies
  14.             Renamed NormalPDF() to NormalPdf().
  15. 1/19/92    dgp    defined the constants LOG2 and LOGPI in VideoToolbox.h
  16.             Added more domain tests, returning NAN if outside. 
  17.             Added more checks to main().
  18.             Wrote Normal2DPdf(),Normal2D(),InverseNormal2D(),and Normal2DSample().
  19. 2/1/92    dgp    Redefined Normal2DPdf(r) to now, more sensibly, treat r as the random
  20.             variable, rather than the implicit x and y, where r=sqrt(x^2+y^2). 
  21.             Previously, Normal2D(R)=Integrate[2 Pi r Normal2DPdf(r),{r,0,R}]
  22.             now Normal2D(R)=Integrate[Normal2DPdf(r),{r,0,R}]. There is no change
  23.             in Normal2D(). I suspect that Normal2D is in fact the Raleigh distribution,
  24.             and I will rename it if this is in fact the case.
  25. 11/13/92 dgp InverseNormal(0.0) now returns -INF, and InverseNormal(1) returns INF.
  26. */
  27. #include "VideoToolbox.h"
  28. #include <assert.h>
  29. #include <math.h>
  30.  
  31. #if 0
  32. #include <sane.h>
  33. extended DoubleToExtended(double x);
  34. double ExtendedToDouble(extended x80);
  35. void main()
  36. {
  37.     double x,y,sum,dx,a,b,mean,sd;
  38.     static double z[1000];
  39.     int i;
  40.     extended e,ee;
  41.     
  42.     Require(0);
  43.     srand(clock());
  44.     printf("%4s%15s%15s%20s%15s\n","x","NormalPdf(x)","Normal(x)","InverseNormal","Error");
  45.     for(x=-4.0;x<=4.0;x+=2.0){
  46.         printf("%4.1f%15.8f%15.8f%20.4f%15.4f\n",
  47.         x,NormalPdf(x),Normal(x),InverseNormal(Normal(x)),InverseNormal(Normal(x))-x);
  48.     }
  49.     sum=0.0;
  50.     dx=0.001;
  51.     for(x=-1.;x<0.;x+=dx)sum+=NormalPdf(x);
  52.     sum*=dx;
  53.     sum-=Normal(0.0)-Normal(-1.0);
  54.     printf("Partial integral of NormalPdf error %.5f\n",sum);
  55.     for(i=0;i<1000;i++)z[i]=NormalSample();
  56.     mean=Mean(z,1000,&sd);
  57.     printf("1000 samples mean %.2f sd %.2f\n",mean,sd);
  58.     printf("\n");
  59.  
  60.     printf("%4s%15s%15s%20s%15s\n","x","Normal2DPdf(x)","Normal2D(x)","InverseNormal2D","Error");
  61.     for(x=-1.;x<=5.0;x+=1.0){
  62.         printf("%4.1f%15.8f%15.8f%20.4f%15.4f\n",
  63.         x,Normal2DPdf(x),Normal2D(x),InverseNormal2D(Normal2D(x)),InverseNormal2D(Normal2D(x))-x);
  64.     }
  65.     sum=0.0;
  66.     dx=0.0001;
  67.     for(x=0;x<1.;x+=dx)sum+=Normal2DPdf(x);
  68.     sum*=dx;
  69.     sum-=Normal2D(1.0);
  70.     printf("Partial integral of Normal2DPdf error %.5f\n",sum);
  71.     for(i=0;i<1000;i++)z[i]=Normal2DSample();
  72.     mean=Mean(z,1000,&sd);
  73.     printf("1000 samples rms %.2f\n",sqrt(mean*mean+sd*sd));
  74.     printf("\n");
  75.     for(i=0;i<1000;i++){
  76.         x=NormalSample();
  77.         y=NormalSample();
  78.         z[i]=sqrt((x*x+y*y)/2.);
  79.     }
  80.     mean=Mean(z,1000,&sd);
  81.     printf("1000 (x,y) normal samples with sd 2^-0.5 have rms hypotenuse of %.2f\n",sqrt(mean*mean+sd*sd));
  82.     printf("\n");
  83.  
  84.     a=4.0*atan(1.0);
  85.     if(a!=PI)printf("4*atan(1)-PI %.19f\n",a-PI);
  86.     a=ExtendedToDouble(pi());
  87.     if(a!=PI)printf("Error: pi %.19f, pi-PI %.19f\n",a,a-PI);
  88.     a=log(a);
  89.     if(a!=LOGPI)printf("Error: log(PI) %.19f, error in LOGPI %.19f\n",a,LOGPI-a);
  90.     a=log(2.0);
  91.     if(a!=LOG2)printf("Error: log(2) %.19f, error in LOG2 %.19f\n",a,LOG2-a);
  92. }
  93. #endif
  94.  
  95. double NormalPdf(double x)
  96. /* Gaussian pdf. Zero mean and unit variance. */
  97. {
  98.     if(IsNan(x))return x;
  99.     return exp(-0.5*(x*x+(LOG2+LOGPI)));
  100. }
  101.  
  102. double Normal(x)
  103. double x;
  104. /*
  105. Cumulative normal distribution. From Abramowitz and Stegun Eq. (26.2.17).
  106. Error |e|<7.5 10^-8
  107. */
  108. {
  109.     register double P,t;
  110.     
  111.     if(x<0.0) return 1.0-Normal(-x);
  112.     t=1.0/(1.0+0.2316419*x);
  113.     P=(0.319381530+(-0.356563782+(1.781477937+(-1.821255978+1.330274429*t)*t)*t)*t)*t;
  114.     return 1.0-NormalPdf(x)*P;
  115. }
  116.  
  117. double InverseNormal(double p)
  118. /*
  119. Inverse of Normal(), based on Abramowitz and Stegun Eq. 26.2.23.
  120. Error |e|<4.5 10^-4.
  121. */
  122. {
  123.     register double t,x;
  124.     
  125.     if(IsNan(p))return p;
  126.     if(p<0.0)return NAN;
  127.     if(p==0.0)return -INF;
  128.     if(p>0.5) return -InverseNormal(1.0-p);
  129.     t=sqrt(-2.0*log(p));
  130.     x=t-(2.515517+(0.802853+0.010328*t)*t)/(1.0+(1.432788+(0.189269+0.001308*t)*t)*t);
  131.     return -x;
  132. }
  133.  
  134. double NormalSample(void)
  135. {
  136.     return InverseNormal(UniformSample());
  137. }
  138.  
  139. double Normal2DPdf(double r)
  140. /* Gaussian pdf over two dimensions. */
  141. /* The argument is taken to be the distance from the origin, [0,Inf]. */
  142. /* The rms is 1 */
  143. {
  144.     if(IsNan(r))return r;
  145.     if(r<=0.0)return 0.0;
  146.     return 2*r*exp(-r*r);
  147. }
  148.  
  149. double Normal2D(double r)
  150. /* Integral of Normal2DPdf() from zero to r. */
  151. {
  152.     if(IsNan(r))return r;
  153.     if(r<=0.0)return 0.0;
  154.     return 1.0-exp(-r*r);
  155. }
  156.  
  157. double InverseNormal2D(double p)
  158. {
  159.     if(IsNan(p))return p;
  160.     if(p<0.0 || p>1.0)return NAN;
  161.     return sqrt(-log(1.0-p));
  162. }
  163.  
  164. double Normal2DSample(void)
  165. /* rms is 1 */
  166. {
  167.     return InverseNormal2D(UniformSample());
  168. }