histo.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. [N, X] = histo(MTX, NBINS_OR_BINSIZE, BIN_CENTER)
  3. >>> See histo.m for documentation <<<
  4. EPS, ported from OBVIUS, 3/97.
  5. */
  6. #define V4_COMPAT
  7. #include <matrix.h> /* Matlab matrices */
  8. #include <mex.h>
  9. #include <stddef.h> /* NULL */
  10. #include <math.h> /* ceil */
  11. #define notDblMtx(it) (!mxIsNumeric(it) || !mxIsDouble(it) || mxIsSparse(it) || mxIsComplex(it))
  12. #define PAD 0.49999 /* A hair below 1/2, to avoid roundoff errors */
  13. #define MAXBINS 20000
  14. void mexFunction(int nlhs, /* Num return vals on lhs */
  15. mxArray *plhs[], /* Matrices on lhs */
  16. int nrhs, /* Num args on rhs */
  17. const mxArray *prhs[] /* Matrices on rhs */
  18. )
  19. {
  20. register double temp;
  21. register int binnum, i, size;
  22. register double *im, binsize;
  23. register double origin, *hist, mn, mx, mean;
  24. register int nbins;
  25. double *bincenters;
  26. const mxArray *arg0,*arg1,*arg2;
  27. double *mxMat;
  28. if (nrhs < 1 ) mexErrMsgTxt("requires at least 1 argument.");
  29. /* ARG 1: MATRIX */
  30. arg0 = prhs[0];
  31. if notDblMtx(arg0) mexErrMsgTxt("MTX arg must be a real non-sparse matrix.");
  32. im = mxGetPr(arg0);
  33. size = (int) mxGetM(arg0) * mxGetN(arg0);
  34. /* FIND min, max, mean values of MTX */
  35. mn = *im; mx = *im; binsize = 0;
  36. for (i=1; i<size; i++)
  37. {
  38. temp = im[i];
  39. if (temp < mn)
  40. mn = temp;
  41. else if (temp > mx)
  42. mx = temp;
  43. binsize += temp;
  44. }
  45. mean = binsize / size;
  46. /* ARG 3: BIN_CENTER */
  47. if (nrhs > 2)
  48. {
  49. arg2 = prhs[2];
  50. if notDblMtx(arg2) mexErrMsgTxt("BIN_CENTER arg must be a real scalar.");
  51. if (mxGetM(arg2) * mxGetN(arg2) != 1)
  52. mexErrMsgTxt("BIN_CENTER must be a real scalar.");
  53. mxMat= mxGetPr(arg2);
  54. origin = *mxMat;
  55. }
  56. else
  57. origin = mean;
  58. /* ARG 2: If positive, NBINS. If negative, -BINSIZE. */
  59. if (nrhs > 1)
  60. {
  61. arg1 = prhs[1];
  62. if notDblMtx(arg1) mexErrMsgTxt("NBINS_OR_BINSIZE arg must be a real scalar.");
  63. if (mxGetM(arg1) * mxGetN(arg1) != 1)
  64. mexErrMsgTxt("NBINS_OR_BINSIZE must be a real scalar.");
  65. mxMat= mxGetPr(arg1);
  66. binsize = *mxMat;
  67. }
  68. else
  69. {
  70. binsize = 101; /* DEFAULT: 101 bins */
  71. }
  72. /* --------------------------------------------------
  73. Adjust origin, binsize, nbins such that
  74. mx <= origin + (nbins-1)*binsize + PAD*binsize
  75. mn >= origin - PAD*binsize
  76. -------------------------------------------------- */
  77. if (binsize < 0) /* user specified BINSIZE */
  78. {
  79. binsize = -binsize;
  80. origin -= binsize * ceil((origin-mn-PAD*binsize)/binsize);
  81. nbins = (int) ceil((mx-origin-PAD*binsize)/binsize) + 1;
  82. }
  83. else /* user specified NBINS */
  84. {
  85. nbins = (int) (binsize + 0.5); /* round to int */
  86. if (nbins == 0)
  87. mexErrMsgTxt("NBINS must be greater than zero.");
  88. binsize = (mx-mn)/(nbins-1+2*PAD); /* start with lower bound */
  89. i = ceil((origin-mn-binsize/2)/binsize);
  90. if ( mn < (origin-i*binsize-PAD*binsize) )
  91. binsize = (origin-mn)/(i+PAD);
  92. else if ( mx > (origin+(nbins-1-i)*binsize+PAD*binsize) )
  93. binsize = (mx-origin)/((nbins-1-i)+PAD);
  94. origin -= binsize * ceil((origin-mn-PAD*binsize)/binsize);
  95. }
  96. if (nbins > MAXBINS)
  97. {
  98. mexPrintf("nbins: %d, MAXBINS: %d\n",nbins,MAXBINS);
  99. mexErrMsgTxt("Number of histo bins has exceeded maximum");
  100. }
  101. /* Allocate hist and xvals */
  102. plhs[0] = (mxArray *) mxCreateDoubleMatrix(1,nbins,mxREAL);
  103. if (plhs[0] == NULL) mexErrMsgTxt("Error allocating result matrix");
  104. hist = mxGetPr(plhs[0]);
  105. if (nlhs > 1)
  106. {
  107. plhs[1] = (mxArray *) mxCreateDoubleMatrix(1,nbins,mxREAL);
  108. if (plhs[1] == NULL) mexErrMsgTxt("Error allocating result matrix");
  109. bincenters = mxGetPr(plhs[1]);
  110. for (i=0, temp=origin; i<nbins; i++, temp+=binsize)
  111. bincenters[i] = temp;
  112. }
  113. for (i=0; i<size; i++)
  114. {
  115. binnum = (int) ((im[i] - origin)/binsize + 0.5);
  116. if ((binnum < nbins) && (binnum >= 0))
  117. (hist[binnum]) += 1.0;
  118. else
  119. printf("HISTO warning: value %f outside of range [%f,%f]\n",
  120. im[i], origin-0.5*binsize, origin+(nbins-0.5)*binsize);
  121. }
  122. return;
  123. }