function [databasecode, querycode] = trainBPCA(X, Xtest,num_bits)

% zero-mean data
sample_mean = mean(X, 1);
X = bsxfun(@minus, X, sample_mean);
Xtest = bsxfun(@minus, Xtest, sample_mean);

%%% pca projection
SamplingRate = 0.3;   % Sample about 30 percent of all the features to train hashing code every time
SamplingBits = 16; % or 32, different parameters for different datasets
% nbits = [16 32 48 64 80 96 112 128 256]; 
nbits = num_bits;

[n, dim] = size(X);

for numBits = nbits
    databasecode = [];
    querycode = [];
    tic
    for i = 1:(numBits/SamplingBits)
        ind = randperm(n);
        ind = ind(1:ceil(n*SamplingRate));
        traindata = X(ind,:);
        
        % Random Rotation, very important for some datasets
        R = orth(randn(SamplingBits,SamplingBits));

        npca = SamplingBits;
        [eigVec, eigVal] = eigs(cov(traindata), npca);
        Y = X * eigVec * R > 0; 
        tY = Xtest * eigVec * R> 0; 

        % store the code
        databasecode = [databasecode, Y];
        querycode = [querycode, tY];
    end
    toc
    databasecode = databasecode > 0;
    querycode = querycode > 0;
end