View Raw SPL
/*****************************************************************************
*                                                                            *
*   CIRCSHIFT.SPL Copyright (C) 2012 DSP Development Corporation             *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:       Randy Race                                                 *
*                                                                            *
*   Synopsis:     Circular shift a series                                    *
*                                                                            *
*   Revisions:     9 Jan 2012  RRR  Creation                                 *
*                                                                            *
*****************************************************************************/

#if @HELP_CIRCSHIFT

    CIRCSHIFT

    Purpose: Performs a circular shift of a series.

    Syntax:  CIRCSHIFT(s, n, m)

               s - A series, the input series.

               n - An integer, the positive or negative shift size.

               m - Optional. An integer, the column shift value if the
                   input is an array.

    Returns: A series, the shifted result.

    Example:
             W1: 1..5
             W2: circshift(w1, 2)
             W3: circshift(w1, -2)

             W1 == {1, 2, 3, 4, 5}
             W2 == {4, 5, 1, 2, 3}
             W3 == {3, 4, 5, 1, 2}

    Example:
             W1: {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
             W2: circshift(w1, 2)
             W3: circshift(w1, -2)
             W4: circshift(w1, 2, -1)

             W1 == {{1, 2, 3},
                    {4, 5, 6},
                    {7, 8, 9}}

             W2 == {{4, 5, 6},
                    {7, 8, 9},
                    {1, 2, 3}}

             W3 == {{7, 8, 9},
                    {1, 2, 3},
                    {4, 5, 6}}

             W4 == {{5, 6, 4},
                    {8, 9, 7},
                    {2, 3, 1}}
    Remarks:
             For a series, a positive shift size shifts the series right
             and a negative shift size shifts left.

             For an array, a positive shift size shifts the array down and
             a negative shift size shifts the array up. If the column shift
             is specified, a positive values shifts the columns right and
             a negative value shifts the columns left.

    See Also:
             Delay
             Extract
#endif


/* perform a circular shift */
circshift(s, n, m)
{
        local L, idx;

        if (argc < 3)
        {
                if (argc < 2)
                {
                        if (argc < 1) error("circshift - input series required");

                        n = 0;
                }

                m = 0;
        }

        if (isarray(n))
        {
                m = (length(n) > 1) ? n[2] : 0;
                n = n[1];
        }

        L = length(s);

        /* handles positive and negative shifts */
        n %= L;

        /* shift rows */
        if (n > 0)
        {
                /* shift */
                s = {extract(s, L - n + 1, -1), extract(s, 1, L - n)};
        }

        L = numcols(s);
        m %= L;

        /* shift columns */
        if (m > 0 && L > 1)
        {
                /* column shift indices */
                idx = {(L - m + 1)..L, 1..(L - m)};
                s = s[.., idx];
        }

        return(s);
}