View Raw SPL
/*****************************************************************************
*                                                                            *
*   CUMTRAPZ.SPL  Copyright (C) 2009-2015 DSP Development Corporation        *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Integration using the trapezoidal rule                      *
*                                                                            *
*   Revisions:   17 Nov 2009  RRR  Creation - from TRAPZ.SPL                 *
*                29 Sep 2015  RRR  difference equation with initial conds    *
*                                                                            *
*****************************************************************************/

#include 

#if @HELP_CUMTRAPZ

    CUMTRAPZ

    Purpose: Calculates the integral of a series using the trapezoidal rule.

    Syntax:  CUMTRAPZ(series)

              series - An interval or XY series, the input data.

    Alternative Syntax:  

              CUMTRAPZ(xseries, yseries)

              xseries - A series, the X values.

              yseries - A series, the Y values.

    Returns: A series

    Example:
             W1: {0, 2, 4, 6, 8, 10}
             W2: integ(w1)
             W3: cumtrapz(w1)

             W2 == {0.0, 1.3, 4.0, 9.3, 16.0, 25.3}

             W3 == {0.0, 1.0, 4.0, 9.0, 16.0, 25.0}

             W2 contains the integrated series using Simpson's rule and
             W3 contains the integrated series using the Trapezoidal rule.

    Example:
             y1 = gnorm(1000, .001);
             a1 = cumtrapz(y1);
             a2 = trapz(y1);

             Series a1 contains the cumulative area of y1 and scalar a2
             contains the value of the total area of y1.  Note that
             a1[end] == a2, the last point of the cumulative area
             equals the total area.

    Remarks:
             For series S, the trapezoidal rule calulates the running sum
             of:
                        deltax * (S[i+1] + S[i]) / 2.

    See Also:
             Area
             Integ
             Trapz
#endif


/* trapezoidal rule */
ITERATE cumtrapz(x, y)
{
        local t, dx, vu, b, have_x;

        /*
         *  calculate:
         *
         *  dx * sum( S[i] + (S[i] - S[i-1])/2 )
         *
         *  by using the moving average without end padding for XY series
         *  or a difference equation for interval series;
         */

        if (argc < 2)
        {
                if (argc < 1) error("cumtrapz - input series required");
                
                s      = refseries(x);
                have_x = FALSE;
        }
        else
        {
                s      = refseries(y);
                have_x = TRUE;
        }

        /* vertical units */
        vu = getvunits(integ(extract(s, 1, 2)));

        if (isxy(s) || have_x)
        {
                t = movavg(s, 2, 0);

                /* zero first point */
                t[1] = 0.0;

                /* XY series */
                if (not(have_x)) x = xvals(s);

                /* delta x's */
                dx = extract(x - delay(x, 1), 1, length(s));

                /* sum */
                t = partsum(dx * t);

                /* get correct length */
                t = extract(t, 1, length(s));

                /* units */
                setvunits(t, vu);

                /* return XY series */
                t = xy(x, t);
        }
        else
        {
                /* difference equation with proper initial condition */
                b = 0.5 * deltax(s);
                t = filteq({b, b}, {1, -1}, s, {-s[1]*b});

                /* units */
                setvunits(t, vu);
        }

        return(t);
}