function dico = dico_decorr(dico, mu, amp)
    %DICO_DECORR decorrelate a dictionary
    %   Parameters:
    %   dico: the dictionary
    %   mu: the coherence threshold
    %   amp: the amplitude coefficients, only used to decide which atom to
    %   project
    %
    %   Result:
    %   dico: a dictionary close to the input one with coherence mu.
    
    % compute atom weights
    if nargin > 2
        rank = sum(amp.*amp, 2);
    else
        rank = randperm(length(dico));
    end
    
    % several decorrelation iterations might be needed to reach global
    % coherence mu. niter can be adjusted to needs.
    niter = 1;
    while niter < 5 && ...
            max(max(abs(dico'*dico -eye(length(dico))))) > mu + 10^-6
        % find pairs of high correlation atoms
        colors = dico_color(dico, mu);
        
        % iterate on all pairs
        nbColors = max(colors);
        for c = 1:nbColors
            index = find(colors==c);
            if numel(index) == 2
                % decide which atom to change (the one with lowest weight)
                if rank(index(1)) < rank(index(2))
                    index = fliplr(index);
                end
                
                % update the atom
                corr = dico(:,index(1))'*dico(:,index(2));
                alpha = sqrt((1-mu*mu)/(1-corr*corr));
                beta = corr*alpha-mu*sign(corr);
                dico(:,index(2)) = alpha*dico(:,index(2))...
                    -beta*dico(:,index(1));
            end
        end
        niter = niter+1;
    end
end

