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

#if @HELP_RANDOMIZE

    RANDOMIZE

    Purpose: Randomizes the order of the elements of an array.

    Syntax:  RANDOMIZE(s, idx)

             (r, k) = RANDOMIZE(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 reordered array.

             (r, k) = RANDOMIZE(s) returns the randomly 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: randomize(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) = randomize(w1);r
             W3: randomize(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) = randomize(w1);r
             W3: randomize(w2, k)

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

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

             The actual result in W2 may differ.

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

             The elements of W1 are randomly reordered in W2 and restored in
             W3.

    Remarks:
             RANDOMIZE randomly reorders the elements of a series or array.
             The elements are reordered by row and by column.

             See ROWRANDOMIZE to reorder the rows of an array.

             See COLRANDOMIZE to reorder the columns of an array.

             See RANDSAMPLE to return K random samples from a population.

    See Also:
             Colrandomize
             Randperm
             Randsample
             Rowrandomize

#endif


/* randomize array elements */
randomize(s, idx = {})
{
        local r;

        if ((argc < 1) || not(isarray(s)) || not(isarray(idx)))
        {
                error(sprintf("%s - input series required", __FUNC__));
        }

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

        if (numcols(s) == 1)
        {
                /* faster for single column */
                r = s[idx];
        }
        else
        {
                /* copy */
                r = s;

                /* preserve shape */
                r[..] = s[idx];
        }

        if (outargc > 1)
        {
                return(r, idx);
        }
        else
        {
                return(r);
        }
}