home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Author: James Painter
- ** Purpose: Data structure and access routines for discrete integration
- ** (1D)
- **
- ** Copyright (c), 1988 GRAIL, University of Washington
- **
- ** $Revision: 1.3 $
- ** $Date: 89/01/25 20:17:02 $
- ** $Locker: jamie $
- ** $Log: Cdf.c,v $
- * Revision 1.3 89/01/25 20:17:02 jamie
- * *** empty log message ***
- *
- * Revision 1.3 89/01/11 21:27:02 jamie
- * *** empty log message ***
- *
- * Revision 1.2 88/10/20 20:39:55 jamie
- * *** empty log message ***
- *
- * Revision 1.1 88/10/18 21:38:34 jamie
- * Initial revision
- *
- */
-
- #include <stdio.h>
- #include "Math.h"
-
- /* -------------------------------------------------------------------
- Define the size of the table
- ------------------------------------------------------------------- */
- #define SIZE 4096
-
- /* ---------------------------------------------------------------------
- Define the Cdf table itself. It is allocated dynamically and accessed
- via an indirection table.
- ---------------------------------------------------------------------- */
- static double *Cdf;
-
-
- /* ----------------------------------------------------------------------
- The number of radius of the filter
- The filter covers -FilterSupport to +FilterSupport
- ---------------------------------------------------------------------- */
- static double FilterSupport = 3.0;
-
- /************************
- a univariate Gaussian pdf
- ************************/
- double
- Gauss(x)
- double x;
- {
- static double normalizing_factor = 0.398942280401433;
- /* 1.0 / sqrt( 2.0*M_PI) */ ;
-
- return ( normalizing_factor*exp(-(x*x)/2.0) );
- }
-
-
- double sinc(x)
- double x;
- {
- double z = M_PI*x;
-
- return (fabs(z) < 1.0E-20) ? 1.0 : sin(z) / z;
- }
-
- /*
- * univariate scaled Sinc function
- */
- double
- ScaledSincFunction(x)
- double x;
- {
- extern double CutOff;
- double scale = 2.0*CutOff;
-
- return scale*sinc( scale*x );
- }
-
- /*
- * univariate windowed, truncated Sinc function
- */
- double
- WindowedSincFunction(x)
- double x;
- {
- extern int window;
- double weight = (window) ? sinc(x/FilterSupport) : 1.0;
-
- return (fabs(x) > FilterSupport) ? 0 : (ScaledSincFunction(x) * weight);
- }
-
-
- void
- SetFilterSupport( support )
- double support;
- {
- FilterSupport = support;
- }
-
- /*
- Ten point gaussian-legendre quadrature.
- Reference "Numerical Recipes": p 122"
- */
- double
- qguass( Fcn, a, b )
- double (*Fcn)();
- double a, b;
- {
- register int j;
-
- double xm, xr, dx, result = 0.0;
- static double x[] = { /* Abscissas */
- .1488743389, .4333953941, .6794095682, .8650633666, .9739065285,
- };
- static double w[] = { /* Weights */
- .2955242247, .2692667193, .2190863625, .1494513491, .0666713443,
- };
-
- xm = 0.5*(b+a);
- xr = 0.5*(b-a);
- for(j=0; j<5; j++) {
- dx = xr*x[j];
- result += w[j]*( (*Fcn)(xm+dx) + (*Fcn)(xm-dx) );
- }
- return result*xr;
- }
-
- /* -----------------------------------------------------------------------
- Build the cumulative density function and store it as a table.
- Integration is approximated by Gauss-Legendre integration
- ------------------------------------------------------------------------ */
- void
- BuildCdf( Fcn)
- double (*Fcn)();
- {
- double x,xDelta, previous;
- int c;
-
- /* Allocate memory for the table */
- Cdf = (double *) malloc( SIZE * sizeof(double) );
-
- if (Cdf == (double *) 0L )
- {
- fprintf( stderr, "BuildCdf: No memory!\n" );
- return;
- }
-
- /* We get an extra entry in our table for free sine there is no point
- ** in storing the zero entry of the Cdf.
- */
- x = -FilterSupport;
- xDelta = (2*FilterSupport) / (SIZE + 1.0);
- previous = 0.0;
- for(c=0; c < SIZE; c++)
- {
- /* Integrate from x to x+delta and add to previous total */
- previous += qguass( Fcn, x, x+xDelta );
- x = -FilterSupport + c*xDelta;
- Cdf[c] = previous;
- }
- }
-
-
- /* Access the Cdf with bounds checking. */
- #define TableAccess(c) \
- ( \
- (c < 0) ? \
- 0.0 : \
- Cdf [ (c >= SIZE) ? SIZE-1 : c ] \
- )
-
- /* ------------------------------------------------------------------------
- Lookup a value in the (1-d) Cdf. linear interpolation is used to get
- values in-between table values. The range of the table is
- from -FilterSupport to FilterSupport in each direction.
- Extrapolation is not done. Instead the last entry is held.
- ------------------------------------------------------------------------- */
- double
- CdfLookup( x )
- double x;
- {
- double u, um;
- int iu, iv;
- double a, b;
-
- /* Map the input into table row and column indicies. */
- u = SIZE * (x + FilterSupport) / (2.0*FilterSupport) - 1;
-
- /* Take the floor */
- iu = (int) u;
-
- /* Find the frational part */
- u = u - iu;
- um = 1.0 - u;
-
- /* Get the two values we will interpolate between */
- a = TableAccess(iu) ;
- b = TableAccess(iu+1);
-
- /* Do the interpolation */
- return (um*a + u*b);
- }
-
-
-
-
-