#include<math.h> #include"complex.h" #defineEPS6.0e-8#defineEULER0.57721566#defineMAXIT100#definePIBY21.5707963 π /2.#defineFPMIN1.0e-30#defineTMIN2.0#defineTRUE1#defineONEComplex(1.0,0.0)voidcisi(float x,float* ci,float* si) {voidnrerror(char error_text[]);int i, k, odd;float a, err, fact, sign, sum, sumc, sums, t, term; fcomplex h, b, c, d, del; t =fabs(x);if (t ==0.0) {* si =0.0;* ci =-1.0/ FPMIN;return; }if (t > TMIN) { b =Complex(1.0, t); c =Complex(1.0/ FPMIN,0.0); d = h =Cdiv(ONE, b);for (i =2; i <= MAXIT; i++) { a =-(i -1) * (i -1); b =Cadd(b, Complex(2.0,0.0)); d =Cdiv(ONE, Cadd(RCmul(a, d), b)); c =Cadd(b, Cdiv(Complex(a,0.0), c)); del =Cmul(c, d); h =Cmul(h, del);if (fabs(del.r -1.0)+fabs(del.i)< EPS) break; }if (i > MAXIT) nrerror("cf failed in cisi"); h =Cmul(Complex(cos(t),-sin(t)), h);* ci =-h.r;* si = PIBY2 +h.i; } else {if (t <sqrt(FPMIN)) { sumc =0.0; sums = t; } else { sum = sums = sumc =0.0; sign = fact =1.0; odd =TRUE;for (k =1; k <= MAXIT; k++) { fact *= t / k; term = fact / k; sum += sign * term; err = term /fabs(sum);if (odd) { sign =-sign; sums = sum; sum = sumc; } else { sumc = sum; sum = sums; }if (err < EPS) break; odd =!odd; }if (k > MAXIT) nrerror("maxits exceeded in cisi"); }* si = sums;* ci = sumc +log(t)+ EULER; }if (x <0.0) * si =-( * si); }
道森积分
道森积分 F(x) 定义为
F(x)=e−x2∫0xet2dt
该函数还可以通过以下方式与复杂的误差函数相关:
F(z)=2iπe−z2[1−erfc(−iz)]
F(z) 的一个显着近似是
F(z)=limh→0π1∑n odd ne−(z−nh)2
上面等式的不同寻常之处在于,随着 h 变小,其精度呈指数级增长,因此相当适中的 h 值(以及相应的级数相当快的收敛)给出了非常准确的近似值。首先方便的是移动求和索引以将其大约集中在指数项的最大值上。定义 n0 为最接近 x / h 的偶数,且 x0≡n0h、x′≡x−x0和 n′≡n−n0,于是
F(x)≈π1∑n′=−Nn′ odd Nn′+n0e−(x′−n′h)2
其中,当 h 足够小且 N 足够大时,近似等式是准确的。如果我们注意到这一点,这个公式的计算可以大大加快