]> Creatis software - CreaPhase.git/blob - octave_packages/m/special-matrix/magic.m
update packages
[CreaPhase.git] / octave_packages / m / special-matrix / magic.m
1 ## Copyright (C) 1999-2012 Paul Kienzle
2 ##
3 ## This file is part of Octave.
4 ##
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
9 ##
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING.  If not, see
17 ## <http://www.gnu.org/licenses/>.
18
19 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {} magic (@var{n})
21 ##
22 ## Create an @var{n}-by-@var{n} magic square.  A magic square is an arrangement
23 ## of the integers @code{1:n^2} such that the row sums, column sums, and
24 ## diagonal sums are all equal to the same value.
25 ##
26 ## Note: @var{n} must be greater than 2 for the magic square to exist.
27 ## @end deftypefn
28
29 function A = magic(n)
30
31   if (nargin != 1)
32     print_usage ();
33   endif
34
35   if (n != fix (n) || n < 0 || n == 2)
36     error ("magic: N must be a positive integer not equal to 2");
37   endif
38
39   if (n == 0)
40
41     A = [];
42
43   elseif (mod (n, 2) == 1)
44
45     shift = floor ((0:n*n-1)/n);
46     c = mod ([1:n*n] - shift + (n-3)/2, n);
47     r = mod ([n*n:-1:1] + 2*shift, n);
48     A(c*n+r+1) = 1:n*n;
49     A = reshape (A, n, n);
50
51   elseif (mod (n, 4) == 0)
52
53     A = reshape (1:n*n, n, n)';
54     I = [1:4:n, 4:4:n];
55     J = fliplr (I);
56     A(I,I) = A(J,J);
57     I = [2:4:n, 3:4:n];
58     J = fliplr (I);
59     A(I,I) = A(J,J);
60
61   elseif (mod (n, 4) == 2)
62
63     m = n/2;
64     A = magic (m);
65     A = [A, A+2*m*m; A+3*m*m, A+m*m];
66     k = (m-1)/2;
67     if (k > 1)
68       I = 1:m;
69       J = [2:k, n-k+2:n];
70       A([I,I+m],J) = A([I+m,I],J);
71     endif
72     I = [1:k, k+2:m];
73     A([I,I+m],1) = A([I+m,I],1);
74     I = k + 1;
75     A([I,I+m],I) = A([I+m,I],I);
76
77   endif
78
79 endfunction
80
81
82 %!test
83 %! for i=3:30
84 %!   A = magic (i);
85 %!   assert (norm(diff([sum(diag(A)),sum(diag(flipud(A))),sum(A),sum(A')])),0);
86 %! endfor
87
88 %!assert (isempty (magic (0)))
89 %!assert (magic(1), 1)
90
91 %% Test input validation
92 %!error magic ()
93 %!error magic (1, 2)
94 %!error <N must be a positive integer not equal to 2> magic (1.5)
95 %!error <N must be a positive integer not equal to 2> magic (-1)
96 %!error <N must be a positive integer not equal to 2> magic (2)
97