PageRenderTime 41ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Class_Segmentation/vlfeat/toolbox/misc/vl_binsum.c

http://phd-workspace.googlecode.com/
C | 230 lines | 126 code | 36 blank | 68 comment | 43 complexity | ee4c64ef027d76fb49a020ed8e1af96f MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. /** @internal
  2. ** @file binsum.c
  3. ** @author Andrea Vedaldi
  4. ** @brief BINSUM - MEX
  5. **/
  6. /* AUTORIGHTS
  7. Copyright (C) 2007-09 Andrea Vedaldi and Brian Fulkerson
  8. This file is part of VLFeat, available under the terms of the
  9. GNU GPLv2, or (at your option) any later version.
  10. */
  11. #include <mexutils.h>
  12. void
  13. mexFunction(int nout, mxArray *out[],
  14. int nin, const mxArray *in[])
  15. {
  16. enum { IN_H = 0, IN_X, IN_B, IN_DIM } ;
  17. enum { OUT_Y = 0 } ;
  18. vl_size KH, KX, KB ;
  19. vl_index j ;
  20. const double *H_pt, *X_pt, *B_pt ;
  21. const double *B_end ;
  22. double *R_pt ;
  23. if (nin < 3) {
  24. mxuError(vlmxErrInvalidArgument,
  25. "At least three arguments are required") ;
  26. }
  27. if (nin > 4) {
  28. mxuError(vlmxErrInvalidArgument,
  29. "At most four arguments are accepted") ;
  30. }
  31. if (nout > 1) {
  32. mxuError(vlmxErrInvalidArgument,
  33. "At most one output argument is accepted") ;
  34. }
  35. if(! vlmxIsPlain (IN(H)) ||
  36. ! vlmxIsPlain (IN(X)) ||
  37. ! vlmxIsPlain (IN(B)) ) {
  38. mxuError(vlmxErrInvalidArgument,
  39. "All arguments must be plain arrays.") ;
  40. }
  41. KH = mxGetNumberOfElements(IN(H)) ; /* accumulator */
  42. KX = mxGetNumberOfElements(IN(X)) ; /* values */
  43. KB = mxGetNumberOfElements(IN(B)) ; /* accumulator indeces */
  44. H_pt = mxGetPr(IN(H)) ;
  45. X_pt = mxGetPr(IN(X)) ;
  46. B_pt = mxGetPr(IN(B)) ;
  47. B_end = B_pt + KB ;
  48. out[0] = mxDuplicateArray(IN(H)) ;
  49. R_pt = mxGetPr(out[0]) ;
  50. if ((KX != KB) && (KX > 1)) {
  51. mxuError(vlmxErrInvalidArgument,
  52. "X and B must have the same number of elements, or X must be a scalar.") ;
  53. }
  54. /* All dimensions mode ------------------------------------------- */
  55. if (nin == 3) {
  56. while (B_pt < B_end) {
  57. /* next bin to accumulate */
  58. j = (int)(*B_pt++) - 1;
  59. /* bin index out of bounds ?*/
  60. if(j < -1 || j >= KH) {
  61. mxuError(vlmxErrInconsistentData,
  62. "Index B(%" VL_FMT_INDEX " = %" VL_FMT_INDEX " out of bound",
  63. (vl_index)(B_pt - mxGetPr(IN(B))),
  64. j + 1) ;
  65. }
  66. /* accumulate (but skip null indeces) */
  67. if (j >= 0) {
  68. R_pt[j] += *X_pt ;
  69. }
  70. /* except for the scalar X case, keep X and B synchronized */
  71. if (KX > 1) ++ X_pt ;
  72. }
  73. }
  74. /* One dimension mode -------------------------------------------- */
  75. else {
  76. int k ;
  77. unsigned int d = (unsigned int)*mxGetPr(IN(DIM)) - 1 ;
  78. unsigned int HD = mxGetNumberOfDimensions(IN(H)) ;
  79. unsigned int XD = mxGetNumberOfDimensions(IN(X)) ;
  80. unsigned int BD = mxGetNumberOfDimensions(IN(B)) ;
  81. mwSize const* Hdims = mxGetDimensions(IN(H)) ;
  82. mwSize const* Xdims = mxGetDimensions(IN(X)) ;
  83. mwSize const* Bdims = mxGetDimensions(IN(B)) ;
  84. const double* B_brk ;
  85. const double* B_nbrk ;
  86. unsigned int srd ;
  87. /* We need to check a few more details about the matrices */
  88. if (d >= HD) {
  89. mxuError(vlmxErrInconsistentData,
  90. "DIM out of bound") ;
  91. }
  92. /*
  93. Here either B has the same number of dimensions of H, or B has
  94. exactly one dimension less and DIM=end. The latter is a
  95. special case due to the fact that MATLAB deletes singleton
  96. dimensions at the ends of arrays, so it would be impossible to
  97. operate with DIM=end and size(B,end)=1, which is a logically
  98. acceptable case.
  99. */
  100. if (HD != BD) {
  101. if (! d == HD - 1 && BD == HD-1) {
  102. mxuError(vlmxErrInconsistentData,
  103. "H and B must have the same number of dimensions.") ;
  104. }
  105. }
  106. if ((BD != XD) && (KX > 1)) {
  107. mxuError(vlmxErrInconsistentData,
  108. "X mut have the same number of dimensions of B or be a scalar.") ;
  109. }
  110. /* This will contain the stride required to advance to the next
  111. * element along dimension DIM. This is the product of all
  112. * dimensions < d. */
  113. srd = 1 ;
  114. for(k = 0 ; k < XD ; ++k) {
  115. if (KX > 1 && Xdims[k] != Bdims[k]) {
  116. mxuError(vlmxErrInconsistentData,
  117. "X and B have incompatible dimensions.") ;
  118. }
  119. if (k != d && (Bdims[k] != Hdims[k])) {
  120. mxuError(vlmxErrInconsistentData,
  121. "B and H have incompatible dimensions.") ;
  122. }
  123. if (k < d) {
  124. srd = srd * Bdims[k] ;
  125. }
  126. }
  127. /* We sum efficiently by a single pass of B_pt in memory order.
  128. * This however makes the algorithm a bit more involved. How the
  129. * sum is performed is easeir understood by an example. Consider
  130. * the case d = 3 and BD = 5. So elements in B are indexed as
  131. *
  132. * B[i0, i1, id, i4, i5] (note that id=i3)
  133. *
  134. * where the indexes (i0,i1,id,i4,i5) are scanned in column-major
  135. * orer. For each of such elements, we acces the element
  136. *
  137. * R[i0, i1, B[i0,i1,id,i4,i5], i4, i5]
  138. *
  139. * For greater efficiency, we do not compute the multi-indexes
  140. * explicity; instead we advance B_pt at each iteration and we
  141. * keep R_pt properly synchronized.
  142. *
  143. * In particular, at each iteration we want R_pt to point to
  144. *
  145. * R[i0, i1, 0, i4, i5]
  146. *
  147. * Therefore, whenever advancing B_pt correspnds to advancing
  148. *
  149. * a - i0, i1 : we advance R_pt
  150. * b - id : we advance R_pt and then we subtract srd to move id back
  151. * one position;
  152. * c - i4,i5 : we do the same as before, but then we need to add
  153. * srd * Hdims[d] * elements to move R_pt up one place
  154. * after dimension d.
  155. *
  156. * We can easily keep track of the three cases without computing
  157. * explicitly the indexs. In fact, case (a) occurs srd-1
  158. * consecutive steps and case (b) at the srd step. Similarly, case
  159. * (c) accurs at step srd * Bdims[d] steps. The pattern repeats
  160. * regularly.
  161. */
  162. KH = Hdims[d] ;
  163. B_brk = B_pt + srd ; /* next time case (b) */
  164. B_nbrk = B_pt + srd * Bdims [d] ; /* next time case (c) */
  165. while (B_pt < B_end) {
  166. /* next bin to accumulate */
  167. j = (int)(*B_pt) - 1;
  168. /* index out of bounds? */
  169. if(j < -1 || j >= KH) {
  170. mxuError(vlmxErrInconsistentData,
  171. "Index B(%" VL_FMT_INDEX " = %" VL_FMT_INDEX " out of bound",
  172. (vl_index)(B_pt - mxGetPr(IN(B))),
  173. j + 1) ;
  174. }
  175. /* accumulate (but skip null indeces) */
  176. if (j >= 0) {
  177. R_pt [j * srd] += *X_pt ;
  178. }
  179. /* next element */
  180. if (KX > 1) X_pt++ ;
  181. B_pt ++ ;
  182. R_pt ++ ;
  183. if (B_pt == B_brk) { /* case (b) occurs */
  184. B_brk += srd ; /* next time case (b) */
  185. R_pt -= srd ;
  186. if (B_pt == B_nbrk) { /* case (c) occurs */
  187. B_nbrk += srd * Bdims[d] ; /* next time case (c) */
  188. R_pt += srd * Hdims[d] ;
  189. }
  190. }
  191. }
  192. }
  193. }