inline Complex PlasmaDispersion(Complex z) { static const double SQRT_PI = 1.7724538509055160272981674833411451; Complex Z; Complex z2 = z*z; // sometimes imaginary part is too high, due to test functions, limit if(cimag(z) > 25.) z = creal(z) + 25.I; // Use asymptotic expansions for large values |z| >> 1 // See definition in NRL Plasma Formulary if(creal(z*z) > 100) { const double x = creal(z); const double y = cimag(z); const double sigma = (y > 0.) ? 0 : (( y == 0) ? 1. : 2.); Complex z4 = z2*z2; Complex z6 = z4*z2; Z = 1.0I * SQRT_PI * sigma * cexp(-z2) - 1./z * ( 1. + 1./(2.*z2) + 3./(4.*z4) + 15./(8.*z6)); } else Z = 1.0I * SQRT_PI * cexp(- z2) * cerfc(- 1.0I * z); return Z; };
int main(void) { const int n = 50000000; { float re, im, rer, imr; re = 0.5, im = 0.5; cerff(re, im, &rer, &imr); printf("cerf (%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); cerfcf(re, im, &rer, &imr); printf("cerfc(%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); re = -0.5, im = 0.5; cerff(re, im, &rer, &imr); printf("cerf (%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); cerfcf(re, im, &rer, &imr); printf("cerfc(%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); double t0 = clock(); for (int i=0; i < n; i++) cerff(re, im, &rer, &imr); double t1 = clock(); printf("cerff: %.3f Mcalls/sec\n", n/((t1-t0)/CLOCKS_PER_SEC)/1000000); } { double re, im, rer, imr; re = 0.5, im = 0.5; cerf(re, im, &rer, &imr); printf("cerf (%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); cerfc(re, im, &rer, &imr); printf("cerfc(%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); re = -0.5, im = 0.5; cerf(re, im, &rer, &imr); printf("cerf (%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); cerfc(re, im, &rer, &imr); printf("cerfc(%21.14e,%21.14e) = (%21.14e, %21.14e)\n", re, im, rer, imr); double t0 = clock(); for (int i=0; i < n; i++) cerf(re, im, &rer, &imr); double t1 = clock(); printf("cerf: %.3f Mcalls/sec\n", n/((t1-t0)/CLOCKS_PER_SEC)/1000000); } }