function [xout,it]=ecam(X,xin,it_max,a)

%
% Memória Associativa com Capacidade Exponencial (ECAM)
%
% Comando: [xout,it]=ecam(X,xin,it_max,a) 
% 
% Entradas:
%         X - Matriz contendo as memórias fundamentais como coluna,
%       xin - Padrão de entrada,
%    it_max - Número máximo de iteração (padrão: it_max=N, núm. de neurônios),
%         a - Coeficiente da exponencial (padrão: a=exp(1/N))
%   
% Saídas:
%      xout - Padrão recordado pela memória associativa,
%        it - Número de iterações efetuadas,
%


% Número de neurônios da rede,
N=size(X,1);

% Define o número máximo de iterações,
if nargin<3
   it_max=N;
end

% Define o coeficiente a;
if nargin<4
   a=1/N;
else
   a=log(a);
   
end
 
% it, conta o numero de iterações,
it=0;
% Usado como critério de parada:
Erro=1;
% Calcular até convergir ou até o número máximo de iterações,
while (Erro>1.e-4)&(it<it_max)
    % Conta o número da iterações,
    it=it+1;
    % xout, será o resultado no final da iteração, i.e., xout=x(t+1).
    xout=xin;
    % Escolhe uma seqüência de índices aleatoriamente,
    ind=randperm(N);
    % Para cada índice da seqüência gerada aleatoriamente, faça:
    for i=1:N
        % Calcula a ativação do neurônio com certo índice,
        u=X(ind(i),:)*exp(a*(X'*xout));
        xout(ind(i))=sign(u);
        % Calcula a saída do neurônio e atualiza xout.
        % Se u=0, então x(t+1)_i = x(t)_i,
        if abs(u)<1.e-9 % Evitar erros de arredondamento! 
           xout(ind(i))=xin(ind(i));
        end
    end
    % Calcula o erro entre x(t) e x(t+1);
    Erro=norm(xout-xin);
    % Atualiza x(t+1).
    xin=xout;
end