/**************************************************************************
 * Piotr's Image&Video Toolbox      Version 2.2
 * Copyright 2009 Piotr Dollar.  [pdollar-at-caltech.edu]
 * Please email me if you find bugs, or have suggestions or questions!
 * Licensed under the Lesser GPL [see external/lgpl.txt]
 *************************************************************************/
#include "mex.h"
typedef unsigned char uchar;

/**************************************************************************
 * Construct 3-D RGB histogram of colors in B [n x 3].
 * Efficient implementation possible for the following reasons:
 *  1) We know that histogram is 3 dimensional.
 *  2) All values in B are between [0,2^nBits)
 *  3) Bins are restricted to powers of 2 (nBins=2^nBits)
 * Finding the bin index is simply a matter of dividing/multiplying by
 * powers of 2, which can be done efficiently with the left and right shift
 * operators. See also histc2c.c in toolbox for more general histogramming
 * implementation. This is about 5x faster. Note: nBins = 2^nBits = 1<<nBits
 *************************************************************************/
void ktHistcRgb( double* h, uchar* B, double* wtMask, int n, int nBits ) {
  int i, indFlat, nBits2=nBits+nBits;
  for( i=0; i<n; i++ ) {
    indFlat = B[i] + (B[i+n]<<nBits) + (B[i+n+n]<<nBits2);
    h[ indFlat ] += wtMask[i];
  }
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  int n, nBits, dims[3]; uchar *B; double *wtMask, *h;
  
  /* PRHS=[B, wtMask, nBits]; PLHS=[h] */
  if( nrhs != 3) mexErrMsgTxt("Three input arguments required.");
  if( nlhs > 1) mexErrMsgTxt("Too many output arguments.");
  
  /* extract inputs */
  n = mxGetM( prhs[0] );
  B = (uchar*) mxGetData(prhs[0]);
  wtMask = mxGetPr(prhs[1]);
  nBits = (int) mxGetScalar(prhs[2]);
  
  /* create outputs-- nBins = 2^nBits */
  dims[0]=dims[1]=dims[2]=1<<nBits;
  plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
  h = mxGetPr( plhs[0] );
  
  /* call main function */
  ktHistcRgb( h, B, wtMask, n, nBits );
}
