File: gauss.c

package info (click to toggle)
spd 1.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,572 kB
  • sloc: ansic: 25,938; fortran: 10,483; sh: 1,032; makefile: 75
file content (187 lines) | stat: -rw-r--r-- 5,191 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 *   Project: The SPD Image correction and azimuthal regrouping
 *                      http://forge.epn-campus.eu/projects/show/azimuthal
 *
 *   Copyright (C) 2005-2010 European Synchrotron Radiation Facility
 *                           Grenoble, France
 *
 *   Principal authors: P. Boesecke (boesecke@esrf.fr)
 *                      R. Wilcke (wilcke@esrf.fr)
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   and the GNU Lesser General Public License  along with this program.
 *   If not, see <http://www.gnu.org/licenses/>.
 */

# define GAUSS_VERSION      "gauss : V1.2 Peter Boesecke 2007-04-23"
/*+++------------------------------------------------------------------------
NAME
   gauss --- routines for gaussian distributions 

SYNOPSIS

   # include gauss.h

HISTORY
  2000-11-17 V1.0 Peter Boesecke creation
  2007-02-21 V1.1 PB SaxsDefinition.h is not needed any more
  2007-03-23 V1.2 PB GaussInit() -> GaussInit( void )
----------------------------------------------------------------------------*/

# define GAUSS_LEN 201  /* number of interpolation points */
# define GAUSS_RANGE 8  /* range of LUT in multiples of sigma */

# include "gauss.h"

static int    GaussDebugMode = 0;
static double GaussLut_X[GAUSS_LEN];
static double GaussLut_Y[GAUSS_LEN];
static int GaussLutInit = 0;
static double GaussS2Pi = 2.506628274631;    // sqrt(2.0*SAXS_PI);

void GaussDebug( int mode )
{ GaussDebugMode = mode; }

double GaussPhi( double X )
{ return( exp ( - X*X*0.5 ) );
} /* GausPhi */

/* initializes GaussLut with the integrated values Y of a Gaussian
   GaussPhi( X ) = exp(-Y^2/2), Y = Integral(0,X,GaussPhi(X) */
void GaussInit( void )
{ const int N = GAUSS_LEN-1;

  int i;

  double X1, X2;
  double Y1, Y2;
  double range = GAUSS_RANGE;
  double step;
  double value;

  step = range/N;

  X2 = 0.0; Y2 = GaussPhi( X2 );

  value = 0.0;

  GaussLut_X[0] = X2;
  GaussLut_Y[0] = value;

  for (i=1;i<=N;i++) {
    X1 = X2; Y1 = Y2;
    X2 = X2 + step; Y2 = GaussPhi( X2 );

    value += (Y1+Y2)*0.5*step;
 
    GaussLut_X[i] = X2;
    GaussLut_Y[i] = value;
    
    }

  GaussLutInit = 1;

} /* GaussInit */

void GaussPrintLut( FILE * out, double X[], double Y[] )
{ const int N=GAUSS_LEN-1;
  int i;

  fprintf( out, "\n%s\n\n", GAUSS_VERSION ); 
  for (i=0;i<=N;i++) {
    fprintf(out,"X[%u] = %10.5g, Y[%u] = %10.5g\n",
               i, GaussLut_X[i],i,GaussLut_Y[i]);
    }
} /* GaussPrintLut */

/* returns the interpolated values of the LUT 
   Xn = XX[n]; Yn = YY[n];

   Monoton increasing values are required:
   X1<X2 <=> Y1<Y2
   
         X < X0   -> Y = Y0 
   Xn <= X < Xn+1 -> Y = Yn + (Yn+1-Yn)/(Xn+1-Xn) * (X-Xn) 
   XN <= X        -> Y = YN                                           */
double Ipol_LUT2( double XX[], double YY[], double X )
{ double Y; 
  int i, N = GAUSS_LEN-1;

  if ( X < XX[0] ) Y = YY[0]; 
    else if ( XX[N] <= X ) Y = YY[N];
    else { for (i=1; i<=N; i++) {
             if (X < XX[i]) break;  
             }
           Y = YY[i-1] + (YY[i]-YY[i-1])/(XX[i]-XX[i-1]) * (X-XX[i-1]);
         }
  return( Y );

} /* Ipol_LUT2 */

/* Gauss(x) = 1.0/(sqrt(2*pi)*sigma) * exp(- x^2/(2*sigma^2) */
double Gauss( double x, double sigma )
{ return( (GaussS2Pi/sigma) * GaussPhi( x/sigma ) );
} /* Gauss */

/* IntGauss(x,sigma)=1.0/(sqrt(2*pi)*sigma)*Integral(-Inf,x,Gauss(x,sigma)) */
double IntGauss ( double x, double sigma ) 
{ double value;

  if (!GaussLutInit) {
    GaussInit();
    if (GaussDebugMode) GaussPrintLut( stdout , GaussLut_X , GaussLut_Y );
    }

  if (x<0) value = 0.5-(Ipol_LUT2(GaussLut_X, GaussLut_Y, -x/sigma))/GaussS2Pi;
    else value = 0.5+(Ipol_LUT2(GaussLut_X, GaussLut_Y, x/sigma))/GaussS2Pi;

  return( value );

} /* IntGauss */

/* InvIntGauss(y,sigma) = Inverted IntGauss */
double InvIntGauss ( double y, double sigma )
{ double value;

  if (!GaussLutInit) {
    GaussInit();
    if (GaussDebugMode) GaussPrintLut( stdout , GaussLut_X , GaussLut_Y );
    }

  if (y<0.5) value=(-Ipol_LUT2(GaussLut_Y,GaussLut_X,(0.5-y)*GaussS2Pi))*sigma;
    else value=(Ipol_LUT2(GaussLut_Y,GaussLut_X,(y-0.5)*GaussS2Pi))*sigma;

  return( value );

} /* InvIntGauss */

/* set random number seed */
void GaussNoiseSeed( unsigned int seed )
{  srand( seed );
} /* GaussNoiseSeed */

/* create gaussian distributed noise */
double GaussNoise( double sigma )
{
  int rannum = rand();
  double p;
  double value;

  /* create random numbers between 0 and 1 */
  p = rannum/(RAND_MAX+1.0); 

  /* project the range 0 to 1 to the x-range of the gauss distribution */
  value =  InvIntGauss ( p, sigma ); 
  return ( value );

} /* GaussNoise */