2
Copyright (C) 2003 by Sean David Fleming
4
sean@power.curtin.edu.au
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of the GNU General Public License
8
as published by the Free Software Foundation; either version 2
9
of the License, or (at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
The GNU GPL can also be found at http://www.gnu.org
31
#define T_STEP_INV 1.0/T_STEP
49
gettimeofday(&tv, NULL);
54
usec = tv.tv_usec + 1000000*tv.tv_sec;
59
/************************************/
60
/* initialize the trig lookup table */
61
/************************************/
69
s_size = PI/T_STEP + 1;
70
s_data = (gdouble *) g_malloc(s_size * sizeof(gdouble));
73
printf("Initializing table: %d points\n", s_size);
77
for (a=0.0 ; a<=PI ; a+= T_STEP)
83
g_assert(i == s_size);
86
/********************/
87
/* SINE replacement */
88
/********************/
89
gdouble tbl_sin(gdouble angle)
92
gdouble s,a,s1,s2,rem;
94
/* enforce range [0, 2PI] */
97
/* determine quadrant */
105
/* setup angle and sign accordingly */
118
/* init retrieval indices */
119
idx2 = idx = (gint) (T_STEP_INV * a);
125
g_assert(idx < s_size);
128
/* get the two values */
129
s1 = *(s_data+idx) * s;
130
s2 = *(s_data+idx2) * s;
131
/* weighted average */
132
rem = T_STEP_INV * a - (gint) (T_STEP_INV * a);
133
s = (rem*s2 + (1.0-rem)*s1);
138
/**********************/
139
/* COSINE replacement */
140
/**********************/
141
gdouble tbl_cos(gdouble angle)
143
return(tbl_sin(angle + PI/2.0));
146
/***************************/
147
/* constrain angle [0,2pi] */
148
/***************************/
149
void ca_rad(gdouble *angle)
155
*angle -= (gdouble) m*2.0*PI;
161
/***************************/
162
/* constrain angle [0,360] */
163
/***************************/
164
void ca_deg(gdouble *angle)
170
*angle -= (gdouble) m*360.0;
176
/********************/
177
/* SQRT replacement */
178
/********************/
179
/* NB: s [0.1, 1.0] */
180
gdouble fast_sqrt(gdouble s)
186
r = 0.188030699 + 1.48359853*s - 1.0979059*s*s + 0.430357353*s*s*s;
192
while (ds > FRACTION_TOLERANCE);
200
/**************************************************/
201
/* test if approx sqrt is faster than system sqrt */
202
/**************************************************/
205
/* TODO - test if it is faster */
209
/*******************/
210
/* numerical setup */
211
/*******************/
218
/********************/
219
/* rounding routine */
220
/********************/
221
gdouble decimal_round(gdouble x, gint dp)
239
gdouble gammln(gdouble xx)
243
static gdouble cof[6]={76.18009173,-86.50532033,24.01409822,
244
-1.231739516,0.120858003e-2,-0.536382e-5};
247
tmp -= (x+0.5)*log(tmp);
249
for (j=0 ; j<=5 ; j++)
254
return -tmp+log(2.50662827465*ser);
260
void gcf(gdouble *gammcf, gdouble a, gdouble x, gdouble *gln)
263
gdouble gold=0.0,g,fac=1.0,b1=1.0;
264
gdouble b0=0.0,anf,ana,an,a1,a0=1.0;
268
for (n=1 ; n<=ITMAX ; n++)
272
a0 = (a1+a0*ana)*fac;
273
b0 = (b1+b0*ana)*fac;
281
if (fabs((g-gold)/g) < EPS)
283
*gammcf = exp(-x+a*log(x)-(*gln))*g;
289
g_assert_not_reached();
295
void gser(gdouble *gamser, gdouble a, gdouble x, gdouble *gln)
304
g_assert_not_reached();
312
for (n=1 ; n<=ITMAX ; n++)
317
if (fabs(del) < fabs(sum)*EPS)
319
*gamser = sum*exp(-x+a*log(x)-(*gln));
323
g_assert_not_reached();
331
gdouble gammp(gdouble a, gdouble x)
333
gdouble gamser,gammcf,gln;
340
gser(&gamser,a,x,&gln);
345
gcf(&gammcf,a,x,&gln);
353
gdouble gammq(gdouble a, gdouble x)
355
gdouble gamser,gammcf,gln;
362
gser(&gamser,a,x,&gln);
367
gcf(&gammcf,a,x,&gln);
375
gdouble erf(gdouble x)
379
val = gammp(0.5, x*x);
387
/********************************/
388
/* complementary error function */
389
/********************************/
390
gdouble erfc(gdouble x)
395
val = 1.0 + gammp(0.5, x*x);
397
val = gammq(0.5, x*x);
405
void sort(gint size, gdouble *array)
414
for (i=1 ; i<size ; i++)
416
/* TODO - direction flag for ascending or descending */
417
if (array[i-1] > array[i])
419
/* swap elements in array */
421
array[i-1] = array[i];
423
/* elements were swapped */
433
gdouble min(gint size, gdouble *x)
442
for (i=1; i<size ; i++)
452
gdouble max(gint size, gdouble *x)
461
for (i=1; i<size ; i++)
468
/************************************/
469
/* numerical recipes - spline setup */
470
/************************************/
471
void spline(double *x, double *y, int n, double yp1, double ypn, double *y2)
474
double p, qn, sig, un, *u;
476
/* allocate 1 extra double as some people insist on starting at 1 */
477
u = g_malloc(n*sizeof(double));
484
u[1] = (3.0/(x[2]-x[1]))*((y[2]-y[1])/(x[2]-x[1])-yp1);
487
for (i=2 ; i<=n-1 ; i++)
489
sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]);
492
u[i] = (y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]);
493
u[i] = (6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p;
501
un = (3.0/(x[n]-x[n-1]))*(ypn-(y[n]-y[n-1])/(x[n]-x[n-1]));
504
y2[n] = (un-qn*u[n-1])/(qn*y2[n-1]+1.0);
506
for (k=n-1 ; k>=1 ; k--)
507
y2[k] = y2[k]*y2[k+1]+u[k];
512
/********************************************/
513
/* numerical recipes - spline interpolation */
514
/********************************************/
515
void splint(double *xa, double *ya, double *y2a, int n, double x, double *y)
534
printf("splint(): bad xa input.\n");
539
*y = a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2a[klo]+(b*b*b-b)*y2a[khi])*(h*h) / 6.0;
542
/****************************************/
543
/* numerical recipes - Cooley-Tukey FFT */
544
/****************************************/
545
#define SWAP(a, b) tempr=(a) ; (a) = (b) ; (b) = tempr;
546
void fft(gdouble *x, gint nn, gint isign)
548
gint n, mmax, m, j, istep, i;
549
gdouble wtemp, wr, wpr, wpi, wi, theta;
550
gdouble tempr, tempi;
551
gdouble *data = --x; /* silly fortran programmers */
556
for (i=1 ; i<n ; i+=2)
560
SWAP(data[j], data[i]);
561
SWAP(data[j+1], data[i+1]);
564
while (m >= 2 && j > m)
576
theta = 2.0 * PI / (isign * mmax);
577
wtemp = sin(0.5*theta);
578
wpr = -2.0 * wtemp * wtemp;
582
for (m=1 ; m<mmax ; m+=2 )
584
for (i=m ; i<=n ; i+=istep)
587
tempr = wr * data[j] - wi * data[j+1];
588
tempi = wr * data[j+1] - wi * data[j];
589
data[j] = data[i] - tempr;
590
data[j+1] = data[i+1] - tempi;
594
wr = (wtemp = wr) * wpr - wi * wpi + wr;
595
wi = wi * wpr + wtemp * wpi + wi;