View Raw SPL
/*****************************************************************************
*                                                                            *
*   ROWRANDOMIZE.SPL Copyright (C) 2023 DSP Development Corporation          *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:          Randy Race                                              *
*                                                                            *
*   Synopsis:        Randomly reorder rows of an input array                 *
*                                                                            *
*   Revisions:        5 Apr 2023  RRR  Creation                              *
*                                                                            *
*****************************************************************************/

#if @HELP_ROWRANDOMIZE

    ROWRANDOMIZE

    Purpose: Randomize the row order of an array.

    Syntax:  ROWRANDOMIZE(s, idx)

             (r, k) = ROWRANDOMIZE(s, idx)

                 s - A series or array, the input to randomize.

               idx - An optional series, the indices of a previous
                     randomize used to unscramble the input.


    Returns: A series or array, the randomly row reordered array.

             (r, k) = ROWRANDOMIZE(s) returns the randomly row reordered
             array and the indices used to perform the reordering. The
             returned indices can be used to restore the result to the
             original order.

    Example:
             W1: 1..5
             W2: rowrandomize(w1)

             W1 contains the series {1, 2, 3, 4, 5}.

             W2 contains the series {5, 4, 2, 1, 3}. The actual result may
             differ.

    Example:
             W1: 1..5
             W2: (r, k) = rowrandomize(w1);r
             W3: rowrandomize(w2, k)

             W1 contains the series {1, 2, 3, 4, 5}.

             W2 contains the series {5, 4, 2, 1, 3}. The actual result may
             differ.

             W3 contains the series {1, 2, 3, 4, 5}, the original series.

    Example:
             W1: ravel(1..12, 4)
             W2: (r, k) = rowrandomize(w1);r
             W3: rowrandomize(w2, k)

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

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

             The actual result in W2 may differ.

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

             The rows of each column of W1 are independently randomly
             reordered in W2 and restored in W3.

    Remarks:
             ROWRANDOMIZE randomly reorders the elements of each row of
             a series or array. The rows of each column are independently
             reordered.

             See COLRANDOMIZE to reorder the columns of an array.

             See RANDOMIZE to reorder the elements of an array.

    See Also:
             Colrandomize
             Randperm
             Randomize

#endif


/* randomize rows - each column randomized independently */
ITERATE rowrandomize(s, idx = {})
{
        if ((argc < 1) || not(isarray(s)) || not(isarray(idx)))
        {
                error(sprintf("%s - input series required", __FUNC__))
        }

        if (isempty(idx))
        {
                /* generate permuted row indices */
                idx = randperm(length(s));
        }
        else
        {
                /* unscramble given row indices */
                idx = grade(idx, 1);
        }

        if (outargc > 1)
        {
                return(s[idx], idx);
        }
        else
        {
                return(s[idx]);
        }
}