function [k,pk,nk,A] = cn_node_degree_distribution(A)
% complex networks: node degree distribution
% 
%  [k,pk,nk] = cn_node_degree_distribution(A)      %  in-degree
%  [k,pk,nk] = cn_node_degree_distribution(A')     % out-degree
% 
%  [k,pk,nk] = cn_node_degree_distribution(D<th)  % distance matrix D and threshold th
%  [k,pk,nk] = cn_node_degree_distribution(C>th)  % similarity (e.g., correlation) matrix C
%                                               
%  [k,pk,nk,A] = ... returns modified A (removed diagonal elements ...) 
%
%  A is a adjacency matrix (true/false): 
%        a_ij must be 1 if there is an edges from 
%        node i to node j, 0 otherwise
%  diagonal elements are ignored
%
%   k - node degree
%  nk - number of connections per degree k
%  pk - probability (normalized such that sum(nk) is 1)
%
%  Example: 
%    A=rand(1000,1000)>0.7 % random graph model
%    [k,pk,nk] = cn_node_degree_distribution(A);
%    loglog(k,nk,'.')
%    xlabel('node degree k'); ylabel('number of nodes');
%

% Author: Matthias Scholz,  www.network-science.org
% Date  : October 17, 2008
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

A=logical(A);

% if matrix is not symmetric: fill up with zeros (to make A symmetric)
    [dim,num]=size(A);
    if dim~=num, 
      A(num,dim)=false;
      fprintf(1,'\n WARNING: matrix is not symmetric\n\n')
    end
    
% set diagonal elements zero 
% (in case of correlation, all entries would be '1' otherwise)
    % A=A-diag(diag(A));  % Error 'Out of memory' for large matrices  
    for i=1:size(A,1), A(i,i)=false; end  % faster    


k_all=full(sum(A)); % node in-degree, 'full' in case of sparse matrix A



[nk,k]=hist(k_all,0:1:max(k_all));
 k= k(2:end); % remove k=0 
nk=nk(2:end); % remove nk for k=0

pk=nk/sum(nk); % normalized: propability (0,1) 


      