function H = hadamard(n,classname)
%MATLAB Code Generation Library Function

% Limitations:
%  1. n must be a fixed-size scalar

%   Copyright 1984-2014 The MathWorks, Inc.
%#codegen

eml_invariant(nargin > 0, ...
    'MATLAB:minrhs');
coder.internal.prefer_const(n);
eml_invariant(eml_is_const(n) || eml_option('VariableSizing'), ...
    'Coder:toolbox:hadamard_2', ...
    'IfNotConst','Fail');
coder.internal.assertValidSizeArg(n);
eml_invariant(isscalar(n), ...
    'Coder:toolbox:hadamard_3', ...
    'IfNotConst','Fail');
N = cast(n,coder.internal.unsignedClass(coder.internal.indexIntClass));
eml_invariant(N == n, ...
    'Coder:toolbox:hadamard_NmustBePosInt');
if nargin < 2
    classname = 'double';
end
H = coder.nullcopy(zeros(N,classname));
[m,e] = hadamard_case(N);
eml_invariant(m ~= 0, ...
    'MATLAB:hadamard:InvalidInput');
if m == 1 % n = 1 * 2^e;
    H(1) = ones(classname);
elseif m == 12
    H(1:12,1) = ones(classname);
    H(1,2:12) = ones(classname);
    H(2:12,2:12) = toeplitz( ...
        cast([-1 -1 1 -1 -1 -1 1 1 1 -1 1],classname), ...
        cast([-1 1 -1 1 1 1 -1 -1 -1 1 -1],classname));
elseif m == 20
    H(1:20,1) = 1;
    H(1,2:20) = 1;
    H(2:20,2:20) = hankel( ...
        cast([-1 -1 1 1 -1 -1 -1 -1 1 -1 1 -1 1 1 1 1 -1 -1 1],classname), ...
        cast([1 -1 -1 1 1 -1 -1 -1 -1 1 -1 1 -1 1 1 1 1 -1 -1],classname));
else
    % This can only happen when the eml_lib_assert above is elided.
    H(:) = coder.internal.nan;
    return
end
% Kronecker product construction.
for k = 1:e
    for j = 1:m
        for i = 1:m
            H(i,coder.internal.indexPlus(j,m)) = H(i,j);
            H(coder.internal.indexPlus(i,m),j) = H(i,j);
            H(coder.internal.indexPlus(i,m),coder.internal.indexPlus(j,m)) = -H(i,j);
        end
    end
    m = coder.internal.indexTimes(m,2);
end

%--------------------------------------------------------------------------

function p = islog2(n)
% Determines whether n is a power of 2, where n is an unsigned integer.
coder.internal.prefer_const(n);
p = n > zeros(class(n)) && ...
    eml_bitand(n,eml_minus(n,1,class(n),'spill')) == zeros(class(n));

%--------------------------------------------------------------------------

function e = ilog2(n)
% Computes log2(n), where n is an unsigned integer that is a power of 2.
coder.internal.prefer_const(n);
m = n;
e = zeros(coder.internal.indexIntClass);
while m > ones(coder.internal.indexIntClass)
    m = eml_rshift(m,ones('int8'));
    e = coder.internal.indexPlus(e,1);
end

%--------------------------------------------------------------------------

function [m,e] = hadamard_case(n)
% m*2^e = n, where n is an unsigned integer and, on success, m = 1, 12,
% or 20.  Returns m = 0 on failure.
coder.internal.prefer_const(n);
if islog2(n)
    % n = 2^e
    m = ones(coder.internal.indexIntClass);
    e = ilog2(n);
    return
end
TWELVE = cast(12,coder.internal.indexIntClass);
nd = eml_rdivide(n,TWELVE,class(n),'floor','spill');
if eml_times(nd,TWELVE,class(n),'spill') == n && islog2(nd)
    % n = 12*2^e
    m = TWELVE;
    e = ilog2(nd);
    return
end
TWENTY = cast(20,coder.internal.indexIntClass);
nd = eml_rdivide(n,TWENTY,class(n),'floor','spill');
if eml_times(nd,TWENTY,class(n),'spill') == n && islog2(nd)
    % n = 20*2^e
    m = TWENTY;
    e = ilog2(nd);
    return
end
m = zeros(coder.internal.indexIntClass);
e = zeros(coder.internal.indexIntClass);

%--------------------------------------------------------------------------
