View Raw SPL
/*****************************************************************************
*                                                                            *
*   FRESNELC.SPL Copyright (C) 2008 DSP Development Corporation              *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Evaluates the cos form of the Fresnel Integral C(x)         *
*                                                                            *
*   Revisions:   25 Mar 2008  RRR  Creation, from J. N. McElwaine            *
*                                                                            *
*****************************************************************************/

#include 

#if @HELP_FRESNELC

    FRESNELC

    Purpose: Evaluates the Fresnel Cosine Integral

    Syntax:  FRESNELC(x, xc)

                x - A real or series, the integration limit.

               xc - Optional real, the cutoff limit that determines
                    the integration method. Defaults to 1.8.

    Returns:
             A real or series, the value of C(x), the integration of
             cos(pi/2 * t^2) from 0 to x.

             (fc, fg) = FRESNELC(x, xc) returns both the integral and
             derivative.

    Example:
             fresnelc(1)

             returns 0.779893, the value of the integration of
             cos(pi/2 * t^2) for t = 0.0 to 1.0.

    Example:
             fresnelc({0.1, 0.2, 1, 2})


             returns {0.099998, 0.199921, 0.779893, 0.488253}
             the values of the integral with limits 0.1, 0.2, 1.0 and 2.0.

    Example:
             fresnelc(-0.5..0.01..0.5)

             returns 1001 samples of the Fresnel Cosine Integral from -5 to 5.

    Remarks:
             FRESNELC approximates C(x), the integration of
             cos(pi/2 * t^2) for t = 0 to x.

             For abs(x) < xc, a power series about x = 0 is used
             yielding an accuracy better than 5e-16.

             For abs(x) > xc, a minimax rational approximation based on
             auxilliary functions described in [1] is used yielding an 
             accuracy better than 1e-9.

             If the integral limit x is a series, the result is a series.

             See FRESNELS to evaluate the sine form of the Fresnel
             integral.

             FRESNELC was developed from an algorithm by J. N. McElwaine.

  See Also:
             ERF
             FRESNELS
             GAMMA
             GAMMALN

  References:
             [1] Abramowitz and Stegun
                 Handbook of Mathematical Functions (9th printing 1970)
                 US Gov. Printing Office

                 Section 7.3 p300

#endif


/* approximate cosine Fresnel integral */
fresnelc(x, xc)
{
        local sgnx, f1, f2, s, ss, is, fc, ff, fg, sx, cx, scalar = FALSE;

        // Cut point for switching between power series and rational approximation
        if (argc < 2)
        {
                if (argc < 1)
                {
                        x = 1.0;
                }
                
                xc = 1.8;
        }

        if (isscalar(x))
        {
                scalar = TRUE;
                x = {x};
        }

        sgnx = sign(x);
        x    = abs(x);

        f1 = find(x <= xc);
        f2 = find(x >  xc);

        s  = pi / 2 * x[f1] ^ 2;
        ss = s ^ 2;

        is = sqrt(2 / pi) / x[f2];

        fc = zeros(length(x), 1);
        ff = fc;
        fg = fc;

        // Approximations for x < 1.6 accurate to eps
        fc[f1] = x[f1] * (1 + (-.1 + (.46296296296296296296e-2 + (-.10683760683760683761e-3 + (.14589169000933706816e-5 + (-.13122532963802805073e-7 + (.83507027951472395917e-10 + (-.39554295164585257634e-12 + (.14483264643598137265e-14 + (-.42214072888070882330e-17 + (.10025164934907719167e-19 + (-.19770647538779051748e-22 + (.32892603491757517328e-25 + (-.46784835155184857737e-28 + .57541916439821717722e-31 * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss);
        ff[f2] = sqrt(2 / pi) * is * (0.36634901025764670680 + (0.84695666222194589182 + (-3.7301273487349839902 + (10.520237918558456228 + (-10.472617402497801126 + 4.4169634834911107719 * is) * is) * is) * is) * is) / (.73269802661202980832 + (1.6939102288852613619 + (-7.4599994789665215344 + (21.032436583848862358 + (-20.269535575486282590 + 8.9995024877628789836 * is) * is) * is) * is) * is);
        fg[f2] = sqrt(2 / pi) * is ^ 3 * (.10935692320079194659 + (.72025533055541994934 + (-2.5630322339412334317 + (7.2404268469720856874 + (-7.0473933910697823445 + 2.9315207450903789503 * is) * is) * is) * is) * is) / (.43742772185339366619 + (2.8810049959848098312 + (-10.250672312139277005 + (28.912791022417600679 + (-25.740131167525284201 + 15.145134363709932380 * is) * is) * is) * is) * is);

        s  = pi / 2 * x[f2] ^ 2;
        cx = cos(s);
        sx = sin(s);

        fc[f2] = 1 / 2 + ff[f2] * sx - fg[f2] * cx;

        fc = fc * sgnx;

        if (scalar)
        {
                fc = castreal(fc);
        }
        else
        {
                setdeltax(fc, deltax(x));
                setxoffset(fc, xoffset(x));
        }

        return(fc);
}