source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vlutil/toolbox/whistc.mex.c @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 5.0 KB
Line 
1/* file:        whistc.c
2** description: MEX weighted histc function.
3** author:      Andrea Vedaldi
4**/
5
6/* AUTORIGHTS
7Copyright (C) 2006 Andrea Vedaldi
8     
9This file is part of VLUtil.
10
11VLUtil is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2, or (at your option)
14any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software Foundation,
23Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24*/
25
26/* 2006-2-17  NaN entries are correctly handled. See m-file for
27              further infos.
28*/
29
30/** @file
31 ** @brief HISTC MEX function implementation.
32 **/
33
34#include"mex.h"
35#include<stdlib.h>
36#include<math.h>
37
38/** WHISTC(X,W,EDGES)
39 **/
40#define min(a,b) ((a<b)?a:b)
41#define max(a,b) ((a<b)?b:a)
42
43typedef struct 
44{
45  double x ;
46  double w ; 
47} pairs_t ; 
48
49/** Compares pairs of values. For natural ordering (ascending), it
50 ** returns
51 **
52 ** - < 0  if a < b
53 ** - = 0  if a == b
54 ** - > 0  if a > b
55 **
56 ** We move NaNs to the end of the sorted sequence. In this way, they
57 ** will be scanned when filling the tail of the histogram and
58 ** skipped.
59 **/
60int 
61cmp_pairs(const void* a, const void* b) 
62{
63  pairs_t* pa = (pairs_t*) a;
64  pairs_t* pb = (pairs_t*) b;
65  bool nana = isnan(pa->x) ;
66  bool nanb = isnan(pb->x) ;
67  if(!nana && !nanb) {
68    double diff = pa->x - pb->x ;
69    if(diff < 0) return -1  ;
70    else if(diff > 0) return +1 ;
71    else return 0 ;
72  } else {
73    /* consider nans to be bigger than any */
74    if(nana && nanb) return 0 ; /* both NaNs are euqal */
75    if(nanb) return -1 ; /* only b is NaN and thus it is bigger */
76    return 1 ; /* only a is NaN and this it is bigger */
77  }
78}
79
80/** @brief MEX driver.
81 ** @param nout number of MATLAB output arguments.
82 ** @param out MATLAB output arguments.
83 ** @param nin number of MATLAB input arguments.
84 ** @param in MATLAB input arguments.
85 **/ 
86void
87mexFunction(int nout, mxArray *out[], 
88            int nin, const mxArray *in[])
89{
90  int M, N, NE ;
91  double* Xpt ;
92  double* Wpt ; 
93  double* EDGESpt ;
94  double* RESpt ;
95  enum {X=0, W, EDGES} ;
96
97  /** -----------------------------------------------------------------
98   **                                               Check the arguments
99   ** -------------------------------------------------------------- */
100  if (nin != 3) {
101    mexErrMsgTxt("Three arguments required.");
102  } else if (nout > 1) {
103    mexErrMsgTxt("Too many output arguments.");
104  }
105
106  if (!mxIsDouble(in[X]) || 
107      !mxIsDouble(in[W]) ||
108      !mxIsDouble(in[W])) {
109    mexErrMsgTxt("The arguments must be real matrices.") ;
110  }
111
112  M = mxGetM(in[X]) ;
113  N = mxGetN(in[X]) ;
114  if( M != mxGetM(in[W]) ||
115      N != mxGetN(in[W]) ) {
116    mexErrMsgTxt("X and W must have the same dimension.") ;
117  }
118
119  if(min( mxGetM(in[EDGES]), mxGetN(in[EDGES]) ) != 1) {
120    mexErrMsgTxt("EDGES must be a vector.") ;
121  }
122 
123  NE = max(mxGetM(in[EDGES]), mxGetN(in[EDGES])) ;
124
125  if(NE < 2) {
126    mexErrMsgTxt("At least two edges are required.\n") ;
127  }
128 
129  Xpt = mxGetPr(in[X]) ;
130  Wpt = mxGetPr(in[W]) ;
131  EDGESpt = mxGetPr(in[EDGES]) ;
132
133  {
134    double x = EDGESpt[0] ;
135    int j ;
136    int ok = 1 ; 
137    for(j = 1 ; j < NE ; ++j) {
138      ok &= (x < EDGESpt[j]) ;
139      x = EDGESpt[j] ;
140    }
141    if(!ok) mexErrMsgTxt("EDGES must be increasing.") ;
142  }
143
144  /*if(nout == 0) return ;*/
145
146  /* If the input is a vector, make it a column. */
147  if(M == 1) {
148    M = N ; 
149    N = 1 ;
150  }
151
152  /* Alloc the result. */
153  out[0] = mxCreateDoubleMatrix(NE, N, mxREAL) ;
154  RESpt = mxGetPr(out[0]) ; 
155
156  /** -----------------------------------------------------------------
157   **                                                        Do the job
158   ** -------------------------------------------------------------- */
159  {
160    pairs_t* pairs = mxMalloc(sizeof(pairs_t)*M) ;
161    int e, i, j ;
162    double c = 0 ;
163    double* RESiterator = RESpt ;
164    double* Xiterator = Xpt ;
165    double* Witerator = Wpt ;
166
167    for(j = 0 ; j < N ; ++j) {             
168      e = 0;
169
170      for(i = 0 ; i < M ; ++i) {
171        pairs[i].x = *Xiterator++ ;
172        pairs[i].w = *Witerator++  ;
173      }
174
175      qsort(pairs, M, sizeof(pairs_t), cmp_pairs) ;
176
177      /* Head */
178      for(i = 0 ; pairs[i].x < EDGESpt[e] ; ++i) ;
179
180      /* Body */
181      while(i < M) {
182        c = 0 ;
183        e += 1 ;
184        if(e == NE) break ;
185
186        for( ;  pairs[i].x < EDGESpt[e] && i < M ; ++i)
187          c += pairs[i].w ;
188
189        RESiterator[e-1] = c ;
190      }
191
192      /* Tail */
193      c = 0 ;
194      for( ; pairs[i].x == EDGESpt[NE-1] && i < M ; ++i)
195        c += pairs[i].w ;
196      RESiterator[NE-1] = c ;
197
198      /* Next column */
199      RESiterator += NE ;
200    }
201   
202    mxFree(pairs) ;                     
203  }
204  return ;
205}
206
207
Note: See TracBrowser for help on using the repository browser.