View Raw SPL
/*****************************************************************************
*                                                                            *
*   MAGIC.SPL      Copyright (C) 2002 DSP Development Corporation            *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:       Randy Race                                                 *
*                                                                            *
*   Synopsis:     Generates an NxN magic square                              *
*                                                                            *
*   Revisions:    28 Aug 2002  RRR  Creation, adaptation of PD source        *
*                                                                            *
*****************************************************************************/



#if @HELP_MAGIC

    MAGIC

    Purpose: Generates an NxN magic square.

    Syntax:  MAGIC(n)

               n - An integer, number of output rows and columns


    Returns: A square matrix.

    Example:
             a = magic(3)

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

             colsum(a)    == {{15, 15, 15}}
             colsum(a')   == {{15, 15, 15}}
             sum(diag(a)) == 15


Remarks:
             A magic square is a square matrix where the sum of each row
             equals the sum of each column and also equals the sum of the
             main diagonal.

             MAGIC(2) does not produce a true magic square since a 2x2
             magic square does not exist.

             For n <= 0, MAGIC returns the empty matrix.

See Also:
             Colsum
             Diag
#endif


/* return a nxn magic square */
magic(n)
{
        local A, shift, c, r, I, J, m, k;

        if (argc < 1) error("magic - input size required");

        n = castint(n);

        if (n <= 0)
        {
                A = {};
        }
        else if (n == 2)
        {
                A = {{1, 3}, {4, 2}};
        }
        else if (n % 2 == 1)
        {
                A          = zeros(n * n, 1);
                shift      = floor((0..n * n - 1) / n);
                c          = mod((1..n * n) - shift + (n - 3) / 2, n);
                r          = mod((n * n.. - 1..1) + 2 * shift, n);
                A[c*n+r+1] = 1..n * n;
                A          = reshape(A, n, n);
        }
        else if (n % 4 == 0)
        {
                A       = reshape(1..n * n, n, n)';
                I       = {1..4..n, 4..4..n};
                J       = rev(I);
                A[I, I] = A[J, J];
                I       = { 2..4..n, 3..4..n };
                J       = rev(I);
                A[I, I] = A[J, J];
        }
        else if (n % 4 == 2)
        {
                m = n / 2;
                A = magic(m);
                A = { {A, A + 2*m*m}, {A + 3*m*m, A + m*m} };
                k = (m - 1) / 2;
                
                if (k > 1)
                {
                        I = 1..m;
                        J = { 2..k, n - k + 2..n };
                        A[{I, I+m}, J] = A[{I+m, I}, J];
                }
                
                I = {1..k, k + 2..m};
                A[{I, I+m}, 1] = A[{I+m, I}, 1];
                
                I = k + 1;
                A[{I, I+m}, I] = A[{I+m, I}, I];
        }

        setdeltax(A, 1.0);
        setdeltay(A, 1.0);

        /* set to tableview */
        setplotstyle(A, 4);

        return(A);
}