function y = my_logsum_fast( log_x, opt_log_y ) % function y = my_logsum_fast( log_x ) % % log_x : vector ( or matrix )containing log(xi) % y : scalar ( or row ), estimation of log(sum over i of xi) % % In case of a matrix we sum each column. % % Note that : % my_logsum_fast( [] ) returns -Inf % my_logsum_fast( [ -Inf -Inf ] ) returns -Inf % my_logsum_fast( [ -Inf -Inf 2 ] ) returns 2 % % An explanation of the implementation is given in "logsum_matlab.pdf". % % % function y = my_logsum_fast( log_x, log_y ) % % Term-by-term log summation of two matrices of same dimension and % size. Returns Y, a matrix of same size as LOG_X and LOG_Y: % y = log( exp( log_x ) + exp( log_y ) ) % % % -- by G. Lathoud, 2005-08-26 if nargin < 1 error( 'logsum needs at least one input argument' ); end if any( isnan( log_x(:) ) ) error( [ mfilename ' log_x must not contain any NaN value!' ] ); end if nargin > 1 if any( isnan( opt_log_y(:) ) ) error( [ mfilename ' opt_log_y must not contain any NaN value!' ] ); end % Two matrices siz_x = size( log_x ); siz_y = size( opt_log_y ); if length( siz_x ) ~= length( siz_y ) error( 'logsum: the two matrices must have same dimension and same size!' ); end if ~all( siz_x == siz_y ) error( 'logsum: the two matrices must have same dimension and same size!' ); end if ~any( siz_x ) % Empty matrices y = log_x; return; end M = max( log_x, opt_log_y ); y = M + log( 1 + exp( min( log_x, opt_log_y ) - M ) ); ind = find( ( log_x == -Inf ) & ( opt_log_y == -Inf ) ); y( ind ) = -Inf; ind = find( ( log_x == +Inf ) & ( opt_log_y == +Inf ) ); y( ind ) = +Inf; % Return output value return; end siz = size( log_x ); n = length( find( siz > 1 ) ); if n > 2 error( [ mfilename ': can only deal with 2-D matrices.' ] ); end if n == 0 % Nothing to do if isempty( log_x ) % Same convention as MATLAB sum( [] ) returning 0. y = -Inf; else y = log_x; end return; end if n == 1 % Vector log_x = log_x(:); end % General case: matrix n_terms = size( log_x, 1 ); % Start with the smallest value log_x = sort( log_x, 1 ); % We do it in a hierarchical manner % At each iteration (k = 0...k_max), % we sum as many pairs of terms as possible k_max = log2( n_terms ); % An explanation of the implementation is given in "logsum_matlab.pdf". for k = 0:k_max p_k = ceil( n_terms * (2^-k) ); q_k = floor( p_k * 0.5 ); t_k = 1 + ( 0:q_k-1 ) * 2 ^ (k+1); u_k = t_k + 2^k; tmp_t = log_x( t_k, : ); tmp_u = log_x( u_k, : ); ind1 = find( ( tmp_t == -Inf ) & ( tmp_u == -Inf ) ); ind2 = find( ( tmp_t == +Inf ) & ( tmp_u == +Inf ) ); ind3 = find( ( tmp_t == +Inf ) & ( tmp_u == -Inf ) ); ind4 = find( ( tmp_t == -Inf ) & ( tmp_u == +Inf ) ); tmp_t = tmp_u + log( 1 + exp( tmp_t - tmp_u ) ); tmp_t( ind1 ) = -Inf; tmp_t( ind2 ) = +Inf; tmp_t( ind3 ) = +Inf; tmp_t( ind4 ) = +Inf; log_x( t_k, : ) = tmp_t; end % Return the result y = log_x( 1,: );