function   H = lasc_pooling(encoder, idx_patch, code_patch, allLength)
% H = lasc_pooling(encoder,idx_patch,code_patch,AllLength)
% perform pooling on the code matrix.
% 
%             H: final representation of one block in SPM.
%       encoder: dictionary which calculated by 'trainEncoder.m'.
%   codes_patch: structural body with first- and second-order LASC code matrix of 
%                the descriptors. Each of them is LxN which N is #descriptors.
%     idx_patch: actived indices of atoms in the dictionary, Nx(knn) in size.
%     allLength: length of the final representation.
% 
% -------------------------------------------------------------------------
% For theoretical and technical details, please refer to the following paper:
%
% Peihua Li, Xiaoxiao Lu, Qilong Wang, "From Dictionary of Visual 
% Words to Subspaces: Locality-constrained Affine Subspace Coding", CVPR 2015.
%
% Please cite the paper above if you use the code.
% For questions, please contact: Xiaoxiao Lu (Email: shaw@mail.dlut.edu.cn)
%                                Qilong Wang (Email: wangqilong.415@163.com)
%                                Peihua Li   (Email: peihuali at dlut dot edu dot cn)
% -------------------------------------------------------------------------
                
H = zeros(1,allLength);
cum_pcaNum = cumsum(encoder.pca.pcaNum);
cum_pcaNum = [ 0; cum_pcaNum ];

for i = 1:encoder.numWords
    curr_idx = find(idx_patch == i);
    curr_idx = mod(curr_idx,size(code_patch.first, 2));
    curr_idx (curr_idx == 0) = size(code_patch.first, 2);
    curr_num = length(curr_idx);
    if curr_num > 0
        lo = cum_pcaNum(i)+1;
        hi = cum_pcaNum(i+1);
        code_sets1 = code_patch.first(lo:hi, curr_idx);
        code_pool1 = mean(code_sets1,2)';
        H(lo:hi) = code_pool1./(norm(code_pool1)+eps);
        code_sets2 = code_patch.second(lo:hi, curr_idx);
        code_pool2 = mean(code_sets2,2)'; 
        H(cum_pcaNum(end)+lo : cum_pcaNum(end)+hi) = code_pool2./(norm(code_pool2)+eps);
    end
end

end

