1 /* This function computes the fresnel F and G functions with dfloat accuracy
2 over -inf,inf. It divides the real line into 2 regions. The first (0,4) uses
3 a division of 1/100, and a taylor series. The second region (4,inf)
4 uses the asymptotic series. This routine could be improved by using
5 lazy evaluation to increase speed in the initialization.
8 load("fresnel_linear_values.mac")$
9 define_variable(FRESNEL_ASYMPTOTIC,4.0d0,any_check,
10 "Point to switch to asymptotic series")$
11 define_variable(FRESNEL_DIVISION,100,any_check,
12 "Number of divisions")$
13 define_variable(FRESNEL_X,0,any_check, "Array constant")$
14 define_variable(FRESNEL_F,1,any_check, "Array constant")$
15 define_variable(FRESNEL_G,2,any_check, "Array constant")$
16 define_variable(FRESNEL_A,3,any_check, "Array constant")$
17 array(fresnel_a,3,4*FRESNEL_DIVISION+1)$
18 define_variable(fresnel_Ftaylor, 8.33333333333334d-3 *
25 (x0 * (9.74090910340024d+2 * f0 - 3.0601968478528d+2 * g0 * x0^2)
26 - 2.79056490122698d+2)
27 + 4.65094150204496d+2 * g0)
29 (x0 * (4.87045455170012d+2 * f0 * x0 - 1.55031383401498d+2)
30 + 9.30188300408994d+2 * g0)
31 - 1.4804406601634d+2 * f0)
32 + x0 * (6.20125533605996d+2 * g0 * x0^2 - 5.9217626406536d+2 * f0)
33 + 1.25663706143592d+2)
34 + x0 * (1.88495559215388d+2 - 5.9217626406536d+2 * f0 * x0)
35 - 1.88495559215388d+2 * g0)
36 - 3.76991118430774d+2 * g0 * x0)
37 + 1.2d+2 * f0),any_check,"Taylor series for F about x0")$
38 define_variable(fresnel_Gtaylor, 8.33333333333334d-3 *
45 (4.87045455170012d+2 * g0 * x0^2 - 9.30188300408994d+2 * f0)
46 + 2.46740110027234d+2)
51 (3.0601968478528d+2 * f0 * x0 - 9.74090910340024d+1)
52 + 9.74090910340024d+2 * g0)
53 - 4.65094150204496d+2 * f0)
54 + 7.89568352087148d+1)
55 - 1.4804406601634d+2 * g0)
56 + x0 * (x0 * (1.97392088021786d+2 - 6.20125533605996d+2 * f0 * x0)
57 - 5.9217626406536d+2 * g0))
58 - 5.9217626406536d+2 * g0 * x0^2 + 1.88495559215388d+2 * f0)
59 + 3.76991118430774d+2 * f0 * x0 - 1.2d+2)
60 + 1.2d+2 * g0),any_check,"Taylor series for G about x0")$
62 fresnel_InitLinear():=block([i:0],
63 for l in fresnel_linear_values do (
64 fresnel_a[FRESNEL_X,i]:first(l),
65 block([x0:first(l),f0:second(l),g0:third(l)],
66 fresnel_a[FRESNEL_F,i]:
67 funmake(lambda,[[x],block([u:x-x0],ev(fresnel_Ftaylor))]),
68 fresnel_a[FRESNEL_G,i]:
69 funmake(lambda,[[x],block([u:x-x0],ev(fresnel_Gtaylor))])),
73 fresnel_init():=block(
76 fresnelF(z):=block([z:abs(z)],
77 if z < FRESNEL_ASYMPTOTIC then block([d:round(FRESNEL_DIVISION*z)],
78 fresnel_a[FRESNEL_F,d](z)
81 [ORDER:65,df:1,pz:dfloat(%pi*z),pz2:dfloat(%pi*z^2),pz2m,pzpz2,
83 fresnel_a[FRESNEL_A,0]:1/pz,
86 for m:1 thru ORDER do (
88 df:df*(4*m-3)*(4*m-1),
90 term:m1*dfloat((df)/(pz*pz2m)),
91 if abs(term) > abs(fresnel_a[FRESNEL_A,m-1]) then (n:(m-1),return(n)),
92 if abs(term/fresnel_a[FRESNEL_A,0]) < DFLOAT_EPSILON then
93 (fresnel_a[FRESNEL_A,m]:0.0d0,n:m,return(n))
94 else fresnel_a[FRESNEL_A,m]:term
96 sum(fresnel_a[FRESNEL_A,n-i],i,0,n)
99 fresnelG(z):=block([z:abs(z)],
100 if z < FRESNEL_ASYMPTOTIC then block([d:round(FRESNEL_DIVISION*z)],
101 fresnel_a[FRESNEL_G,d](z)
103 [ORDER:65,df:1,pz:dfloat(%pi*z),pz2:dfloat(%pi*z^2),pz2m,pzpz2,
105 fresnel_a[FRESNEL_A,0]:1/(pz*pz2),
108 for m:1 thru ORDER do (
110 df:df*(4*m-1)*(4*m+1),
112 term:m1*dfloat((df)/(pzpz2*pz2m)),
113 if abs(term) > abs(fresnel_a[FRESNEL_A,m-1]) then (n:(m-1),return(n)),
114 if abs(term/fresnel_a[FRESNEL_A,0]) < DFLOAT_EPSILON then
115 (fresnel_a[FRESNEL_A,m]:0.0d0,n:m,return(n))
116 else fresnel_a[FRESNEL_A,m]:term
118 sum(fresnel_a[FRESNEL_A,n-i],i,0,n)