1 | /*Written by Mathieu Morlighem April 19th 2019*/
|
---|
2 |
|
---|
3 | /*includes*/
|
---|
4 | #include <mex.h>
|
---|
5 | #include <pthread.h>
|
---|
6 | #include <math.h> //for isnan
|
---|
7 | #include <cstring> // for strcmp
|
---|
8 | #define f(m,n)\
|
---|
9 | data[n*dataM+m] //Warning: matrix is transposed!
|
---|
10 |
|
---|
11 | /*Inputs{{{*/
|
---|
12 | #define DATAX (mxArray*)prhs[0]
|
---|
13 | #define DATAY (mxArray*)prhs[1]
|
---|
14 | #define DATA (mxArray*)prhs[2]
|
---|
15 | #define INTERPX (mxArray*)prhs[3]
|
---|
16 | #define INTERPY (mxArray*)prhs[4]
|
---|
17 | #define METHOD (mxArray*)prhs[5]
|
---|
18 | /*}}}*/
|
---|
19 | /*Outputs{{{*/
|
---|
20 | #define INTERP (mxArray**)&plhs[0]
|
---|
21 | /*}}}*/
|
---|
22 | /*threading structs{{{*/
|
---|
23 | typedef struct{
|
---|
24 | void* usr;
|
---|
25 | int my_thread;
|
---|
26 | int num_threads;
|
---|
27 | } pthread_handle;
|
---|
28 |
|
---|
29 | typedef struct{
|
---|
30 | int dataM;
|
---|
31 | int dataN;
|
---|
32 | double* datax;
|
---|
33 | double* datay;
|
---|
34 | double* data;
|
---|
35 | int interpN;
|
---|
36 | double* interpx;
|
---|
37 | double* interpy;
|
---|
38 | double* interp;
|
---|
39 | int method;
|
---|
40 | } AppStruct; /*}}}*/
|
---|
41 | /*Prototypes{{{*/
|
---|
42 | void FetchMatrixPointer(double** pmatrix,int *pM,int *pN,const mxArray* dataref);
|
---|
43 | void FetchVectorPointer(double** pvector,int *pN,const mxArray* dataref);
|
---|
44 | void FetchString(char** pstring,const mxArray* dataref);
|
---|
45 | void WriteMatrix(mxArray** pdataref,double* matrix,int M,int N);
|
---|
46 | void WriteVector(mxArray** pdataref,double* vector,int N);
|
---|
47 | void* InterpFromGridt(void* vpthread_handle);
|
---|
48 | void LaunchThread(void* function(void*), void* usr,int num_threads);
|
---|
49 | bool binary_search_increasing(int* pindex,double target,double* list,int n);
|
---|
50 | bool binary_search_decreasing(int* pindex,double target,double* list,int n);
|
---|
51 | void dataderivatives(double* A,double* x,double* y,double* data,int M,int N, int m0, int m1,int m2,int m3, int n0, int n1,int n2,int n3);
|
---|
52 | /*}}}*/
|
---|
53 |
|
---|
54 | void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){/*{{{*/
|
---|
55 |
|
---|
56 | double *datax = NULL;
|
---|
57 | double *datay = NULL;
|
---|
58 | double *data = NULL;
|
---|
59 | int dataM,dataN;
|
---|
60 | double *interpx = NULL;
|
---|
61 | double *interpy = NULL;
|
---|
62 | double *interp = NULL;
|
---|
63 | int interpM,interpN;
|
---|
64 |
|
---|
65 | int num_threads = 20;
|
---|
66 | int test1,test2,test3,test4;
|
---|
67 | int method = 1; // 0 = nearest, 1 = bilinear, 2 = bicubic
|
---|
68 |
|
---|
69 | /*Check arguments to avoid crash*/
|
---|
70 | if(nlhs>1 || (nrhs<5 || nrhs>6)) mexErrMsgTxt("Wrong usage");
|
---|
71 |
|
---|
72 | /*Get variables from matlab to C*/
|
---|
73 | FetchVectorPointer(&datax,&dataN,DATAX);
|
---|
74 | FetchVectorPointer(&datay,&dataM,DATAY);
|
---|
75 | FetchMatrixPointer(&data ,&test1,&test2,DATA);
|
---|
76 | FetchMatrixPointer(&interpx,&interpM,&interpN,INTERPX);
|
---|
77 | FetchMatrixPointer(&interpy,&test3,&test4,INTERPY);
|
---|
78 | if(!dataM*dataN) mexErrMsgTxt("data is empty");
|
---|
79 | if(!interpM*interpN) mexErrMsgTxt("no interpolation requested");
|
---|
80 | if(test1!=dataM) mexErrMsgTxt("x should have as many elements as there are columns in the data");
|
---|
81 | if(test2!=dataN) mexErrMsgTxt("y should have as many elements as there are lines in the data");
|
---|
82 | if(test3!=interpM) mexErrMsgTxt("interpolation locations (x,y) do not have the same size");
|
---|
83 | if(test4!=interpN) mexErrMsgTxt("interpolation locations (x,y) do not have the same size");
|
---|
84 | if(nrhs==6){
|
---|
85 | char* method_string = NULL;
|
---|
86 | FetchString(&method_string,METHOD);
|
---|
87 | if(strcmp(method_string,"nearest")==0) method = 0;
|
---|
88 | else if(strcmp(method_string,"linear")==0) method = 1;
|
---|
89 | else if(strcmp(method_string,"cubic")==0) method = 2;
|
---|
90 | else{
|
---|
91 | mexErrMsgTxt("Method not supported yet");
|
---|
92 | }
|
---|
93 |
|
---|
94 | mxFree(method_string);
|
---|
95 | }
|
---|
96 |
|
---|
97 | /*Check inputs*/
|
---|
98 | if(true){
|
---|
99 | for(int i=0;i<interpM*interpN;i++){
|
---|
100 | if(isnan(interpx[i])) mexErrMsgTxt("NaN found in interpx");
|
---|
101 | if(isnan(interpy[i])) mexErrMsgTxt("NaN found in interpy");
|
---|
102 | }
|
---|
103 | }
|
---|
104 | if(method==3){
|
---|
105 | if(datax[1]-datax[0]<0) mexErrMsgTxt("x needs to be increasing for cubic interpolation");
|
---|
106 | if(datay[1]-datay[0]<0) mexErrMsgTxt("y needs to be increasing for cubic interpolation");
|
---|
107 | }
|
---|
108 |
|
---|
109 | /*Allocate output*/
|
---|
110 | interp=(double*)mxMalloc(interpM*interpN*sizeof(double));
|
---|
111 |
|
---|
112 | /*Multithreaded core*/
|
---|
113 | AppStruct usr;
|
---|
114 | usr.dataM = dataM;
|
---|
115 | usr.dataN = dataN;
|
---|
116 | usr.datax = datax;
|
---|
117 | usr.datay = datay;
|
---|
118 | usr.data = data;
|
---|
119 | usr.interpN = interpM*interpN;
|
---|
120 | usr.interpx = interpx;
|
---|
121 | usr.interpy = interpy;
|
---|
122 | usr.interp = interp;
|
---|
123 | usr.method = method;
|
---|
124 | LaunchThread(InterpFromGridt,(void*)&usr,num_threads);
|
---|
125 |
|
---|
126 | /*Write output vector*/
|
---|
127 | WriteMatrix(INTERP,interp,interpM,interpN);
|
---|
128 |
|
---|
129 | /*Clean-up and return*/
|
---|
130 | /*Do not erase pointers!*/
|
---|
131 | return;
|
---|
132 | }/*}}}*/
|
---|
133 |
|
---|
134 | /*InterpFromGridt{{{*/
|
---|
135 | void* InterpFromGridt(void* vpthread_handle){
|
---|
136 |
|
---|
137 | /*recover this thread info*/
|
---|
138 | pthread_handle *handle = (pthread_handle*)vpthread_handle;
|
---|
139 | int my_thread = handle->my_thread;
|
---|
140 | int num_threads = handle->num_threads;
|
---|
141 |
|
---|
142 | /*Recover struct*/
|
---|
143 | AppStruct *usr = (AppStruct*)handle->usr;
|
---|
144 | int dataM = usr->dataM;
|
---|
145 | int dataN = usr->dataN;
|
---|
146 | double *datax = usr->datax;
|
---|
147 | double *datay = usr->datay;
|
---|
148 | double *data = usr->data;
|
---|
149 | int interpN = usr->interpN;
|
---|
150 | double *interpx = usr->interpx;
|
---|
151 | double *interpy = usr->interpy;
|
---|
152 | double *interp = usr->interp;
|
---|
153 | int method = usr->method;
|
---|
154 |
|
---|
155 | /*Intermediary*/
|
---|
156 | double xprime,yprime;
|
---|
157 | double x,y,x0,x1,x2,x3,y0,y1,y2,y3;
|
---|
158 | double Q11,Q12;
|
---|
159 | double Q21,Q22;
|
---|
160 | double A[16];
|
---|
161 | int m,n,m0,m1,m2,m3,n0,n1,n2,n3;
|
---|
162 | int oldm=-1,oldn=-1;
|
---|
163 |
|
---|
164 | /*Is our matrix inverted?*/
|
---|
165 | bool invertx = (datax[1]-datax[0])<0 ? true:false;
|
---|
166 | bool inverty = (datay[1]-datay[0])<0 ? true:false;
|
---|
167 |
|
---|
168 | for(int idx=my_thread;idx<interpN;idx+=num_threads){
|
---|
169 |
|
---|
170 | x=interpx[idx];
|
---|
171 | y=interpy[idx];
|
---|
172 |
|
---|
173 | /*Find indices m and n into y and x, for which y(m)<=y_grids<=y(m+1) and x(n)<=x_grid<=x(n+1)*/
|
---|
174 | if(invertx) binary_search_decreasing(&n,x,datax,dataN);
|
---|
175 | else binary_search_increasing(&n,x,datax,dataN);
|
---|
176 | if(inverty) binary_search_decreasing(&m,y,datay,dataM);
|
---|
177 | else binary_search_increasing(&m,y,datay,dataM);
|
---|
178 |
|
---|
179 | if(n>=0 && n<dataN && m>=0 && m<dataM){
|
---|
180 |
|
---|
181 | /* Q12 Q22
|
---|
182 | * y2 x---------+-----x
|
---|
183 | * | | |
|
---|
184 | * | |P |
|
---|
185 | * |---------+-----|
|
---|
186 | * | | |
|
---|
187 | * | | |
|
---|
188 | * y1 x---------+-----x Q21
|
---|
189 | * x1 x2
|
---|
190 | *
|
---|
191 | */
|
---|
192 | if(invertx){
|
---|
193 | n1=n+1; n2=n;
|
---|
194 | }
|
---|
195 | else{
|
---|
196 | n1=n; n2=n+1;
|
---|
197 | }
|
---|
198 | if(inverty){
|
---|
199 | m1=m+1; m2=m;
|
---|
200 | }
|
---|
201 | else{
|
---|
202 | m1=m; m2=m+1;
|
---|
203 | }
|
---|
204 |
|
---|
205 | x1 = datax[n1]; x2 = datax[n2];
|
---|
206 | y1 = datay[m1]; y2 = datay[m2];
|
---|
207 |
|
---|
208 | if(method==0){
|
---|
209 | /*Nearest neighbor interpolation*/
|
---|
210 | if(x > (x1+x2)/2.){
|
---|
211 | if(y > (y1+y2)/2.)
|
---|
212 | interp[idx] = f(m2,n2);
|
---|
213 | else
|
---|
214 | interp[idx] = f(m1,n2);
|
---|
215 | }
|
---|
216 | else{
|
---|
217 | if(y > (y1+y2)/2.)
|
---|
218 | interp[idx] = f(m2,n1);
|
---|
219 | else
|
---|
220 | interp[idx] = f(m1,n1);
|
---|
221 | }
|
---|
222 | continue;
|
---|
223 | }
|
---|
224 | else if(method==1){
|
---|
225 | /*Bilinear interpolation*/
|
---|
226 | if(Q11==-9999 || Q12==-9999 || Q21==-9999 || Q22==-9999){
|
---|
227 | interp[idx] = -9999;
|
---|
228 | continue;
|
---|
229 | }
|
---|
230 |
|
---|
231 | interp[idx] =
|
---|
232 | +f(m1,n1)*(x2-x)*(y2-y)/((x2-x1)*(y2-y1))
|
---|
233 | +f(m1,n2)*(x-x1)*(y2-y)/((x2-x1)*(y2-y1))
|
---|
234 | +f(m2,n1)*(x2-x)*(y-y1)/((x2-x1)*(y2-y1))
|
---|
235 | +f(m2,n2)*(x-x1)*(y-y1)/((x2-x1)*(y2-y1));
|
---|
236 | }
|
---|
237 | else{
|
---|
238 | /*Bicubic interpolation*/
|
---|
239 | if(invertx){n0=n+2; n3=n-1;}
|
---|
240 | else{ n0=n-1; n3=n+2; }
|
---|
241 | if(inverty){ m0=m+2; m3=m-1; }
|
---|
242 | else{ m0=m-1; m3=m+2; }
|
---|
243 |
|
---|
244 | if(n0<0 || n3>=dataN || m0<0 || m3>=dataM){
|
---|
245 | interp[idx] = -9999;
|
---|
246 | continue;
|
---|
247 | }
|
---|
248 |
|
---|
249 | /*Local coordinates (between 0 and 1)*/
|
---|
250 | xprime = (x - datax[n1])/(datax[n2]-datax[n1]);
|
---|
251 | yprime = (y - datay[m1])/(datay[m2]-datay[m1]);
|
---|
252 |
|
---|
253 | /*Get derivatives at current pixel*/
|
---|
254 | if(oldm!=m || oldn!=n){
|
---|
255 | dataderivatives(&A[0],datax,datay,data,dataM,dataN,m0,m1,m2,m3,n0,n1,n2,n3);
|
---|
256 | oldm = m;
|
---|
257 | oldn = n;
|
---|
258 | }
|
---|
259 |
|
---|
260 | double a00 = A[0];
|
---|
261 | double a10 = A[4];
|
---|
262 | double a20 = -3*A[0]+3*A[1]-2*A[4]-A[5];
|
---|
263 | double a30 = 2*A[0]-2*A[1]+A[4]+A[5];
|
---|
264 | double a01 = A[8];
|
---|
265 | double a11 = A[12];
|
---|
266 | double a21 = -3*A[8]+3*A[9]-2*A[12]-A[13];
|
---|
267 | double a31 = 2*A[8]-2*A[9]+A[12]+A[13];
|
---|
268 | double a02 = -3*A[0]+3*A[2]-2*A[8]-A[10];
|
---|
269 | double a12 = -3*A[4]+3*A[6]-2*A[12]-A[14];
|
---|
270 | double a22 = 9*A[0]-9*A[1]-9*A[2]+9*A[3]+6*A[4]+3*A[5]-6*A[6]-3*A[7]+6*A[8]-6*A[9]+3*A[10]-3*A[11]+4*A[12]+2*A[13]+2*A[14]+A[15];
|
---|
271 | double a32 =-6*A[0]+6*A[1]+6*A[2]-6*A[3]-3*A[4]-3*A[5]+3*A[6]+3*A[7]-4*A[8]+4*A[9]-2*A[10]+2*A[11]-2*A[12]-2*A[13]-A[14]-A[15];
|
---|
272 | double a03 = 2*A[0]-2*A[2]+A[8]+A[10];
|
---|
273 | double a13 = 2*A[4]-2*A[6]+A[12]+A[14];
|
---|
274 | double a23 =-6*A[0]+6*A[1]+6*A[2]-6*A[3]-4*A[4]-2*A[5]+4*A[6]+2*A[7]-3*A[8]+3*A[9]-3*A[10]+3*A[11]-2*A[12]-A[13]-2*A[14]-A[15] ;
|
---|
275 | double a33 = 4*A[0]-4*A[1]-4*A[2]+4*A[3]+2*A[4]+2*A[5]-2*A[6]-2*A[7]+2*A[8]-2*A[9]+2*A[10]-2*A[11]+A[12]+A[13]+A[14]+A[15];
|
---|
276 |
|
---|
277 | x1= xprime;
|
---|
278 | x2= x1*x1;
|
---|
279 | x3= x2*x1;
|
---|
280 | y1= yprime;
|
---|
281 | y2= y1*y1;
|
---|
282 | y3= y2*y1;
|
---|
283 | interp[idx] = (a00+a01*y1+a02*y2+a03*y3)+(a10+a11*y1+a12*y2+a13*y3)*x1+(a20+a21*y1+a22*y2+a23*y3)*x2+(a30+a31*y1+a32*y2+a33*y3)*x3;
|
---|
284 | }
|
---|
285 | }
|
---|
286 | else{
|
---|
287 | interp[idx] = -9999.;
|
---|
288 | }
|
---|
289 | }
|
---|
290 | //if(my_thread==0) printf("\r interpolation progress = %5.1f%%\n",100.);
|
---|
291 |
|
---|
292 | return NULL;
|
---|
293 | }/*}}}*/
|
---|
294 | /*binary_search_increasing {{{*/
|
---|
295 | bool binary_search_increasing(int* pindex,double target,double* list,int n){
|
---|
296 |
|
---|
297 | /*output*/
|
---|
298 | int index; //index, if found
|
---|
299 | bool found=false; //found=0 if target is not found, 1 otherwise.
|
---|
300 |
|
---|
301 | /*intermediary*/
|
---|
302 | int n0 = 0;
|
---|
303 | int n1 = int(n/2);
|
---|
304 | //int n1 = int((target-list[0])/(list[1]-list[0]));
|
---|
305 | int n2 = n-1;
|
---|
306 |
|
---|
307 | if(target<list[n0]){
|
---|
308 | found = true;
|
---|
309 | index = -1;
|
---|
310 | }
|
---|
311 | else if(target>list[n2]){
|
---|
312 | found = true;
|
---|
313 | index = n;
|
---|
314 | }
|
---|
315 | else{
|
---|
316 | while(!found){
|
---|
317 | /*did we find the target?*/
|
---|
318 | if(list[n1]<=target && list[n1+1]>=target){
|
---|
319 | found = true;
|
---|
320 | index = n1;
|
---|
321 | break;
|
---|
322 | }
|
---|
323 | if(target < list[n1]){
|
---|
324 | n2 = n1;
|
---|
325 | n1 = n0 + int((n2-n0)/2);
|
---|
326 | }
|
---|
327 | else{
|
---|
328 | n0 = n1;
|
---|
329 | n1 = n0 + int((n2-n0)/2);
|
---|
330 | }
|
---|
331 | }
|
---|
332 | }
|
---|
333 |
|
---|
334 | /*Assign output pointers:*/
|
---|
335 | *pindex=index;
|
---|
336 |
|
---|
337 | /*Return result: */
|
---|
338 | return found;
|
---|
339 | }/*}}}*/
|
---|
340 | /*binary_search_decreasing{{{*/
|
---|
341 | bool binary_search_decreasing(int* pindex,double target,double* list,int n){
|
---|
342 |
|
---|
343 | /*output*/
|
---|
344 | int index; //index, if found
|
---|
345 | bool found=false; //found=0 if target is not found, 1 otherwise.
|
---|
346 |
|
---|
347 | /*intermediary*/
|
---|
348 | int n0 = 0;
|
---|
349 | int n1 = int(n/2);
|
---|
350 | //int n1 = int((target-list[0])/(list[0]-list[1]));
|
---|
351 | int n2 = n-1;
|
---|
352 |
|
---|
353 | if (target>list[n0]){
|
---|
354 | found = true;
|
---|
355 | index = -1;
|
---|
356 | }
|
---|
357 | else if(target<list[n2]){
|
---|
358 | found = true;
|
---|
359 | index = n;
|
---|
360 | }
|
---|
361 | else{
|
---|
362 | while(!found){
|
---|
363 | /*did we find the target?*/
|
---|
364 | if(list[n1]>=target && list[n1+1]<=target){
|
---|
365 | found = true;
|
---|
366 | index = n1;
|
---|
367 | break;
|
---|
368 | }
|
---|
369 | if(target > list[n1]){
|
---|
370 | n2 = n1;
|
---|
371 | n1 = n0 + int((n2-n0)/2);
|
---|
372 | }
|
---|
373 | else{
|
---|
374 | n0 = n1;
|
---|
375 | n1 = n0 + int((n2-n0)/2);
|
---|
376 | }
|
---|
377 | }
|
---|
378 | }
|
---|
379 |
|
---|
380 | /*Assign output pointers:*/
|
---|
381 | *pindex=index;
|
---|
382 |
|
---|
383 | /*Return result: */
|
---|
384 | return found;
|
---|
385 | }/*}}}*/
|
---|
386 | /*dataderivatives{{{*/
|
---|
387 | void dataderivatives(double* A,double* x,double* y,double* data,int dataM,int dataN,
|
---|
388 | int m0, int m1,int m2,int m3, int n0, int n1,int n2,int n3){
|
---|
389 |
|
---|
390 | /* i+1 + +-------+ f(1,1)
|
---|
391 | * | | |
|
---|
392 | * | |f(0,0) |
|
---|
393 | * i + +-------+ f(1,0)
|
---|
394 | * +--+-------+-----> x
|
---|
395 | * j j+1
|
---|
396 | */
|
---|
397 |
|
---|
398 |
|
---|
399 | /*Function at corners*/
|
---|
400 | A[0] = f(m1,n1); // f(0,0)
|
---|
401 | A[1] = f(m1,n2); // f(1,0)
|
---|
402 | A[2] = f(m2,n1); // f(0,1)
|
---|
403 | A[3] = f(m2,n2); // f(1,1)
|
---|
404 |
|
---|
405 | /*x component of the gradient*/
|
---|
406 | A[4] = .5*(f(m1,n2) - f(m1,n0));///(x[n2]-x[n0]); // dfdx(0,0)
|
---|
407 | A[5] = .5*(f(m1,n3) - f(m1,n1));///(x[n3]-x[n1]); // dfdx(1,0)
|
---|
408 | A[6] = .5*(f(m2,n2) - f(m2,n0));///(x[n2]-x[n0]); // dfdx(0,1)
|
---|
409 | A[7] = .5*(f(m2,n3) - f(m2,n1));///(x[n3]-x[n1]); // dfdx(1,1)
|
---|
410 |
|
---|
411 | /*y component of the gradient*/
|
---|
412 | A[ 8] = .5*(f(m2,n1) - f(m0,n1));///(y[m2]-y[m0]); // dfdy(0,0)
|
---|
413 | A[ 9] = .5*(f(m2,n2) - f(m0,n2));///(y[m2]-y[m0]); // dfdy(1,0)
|
---|
414 | A[10] = .5*(f(m3,n1) - f(m1,n1));///(y[m3]-y[m1]); // dfdy(0,1)
|
---|
415 | A[11] = .5*(f(m3,n2) - f(m1,n2));///(y[m3]-y[m1]); // dfdy(1,1)
|
---|
416 |
|
---|
417 | /*cross-component of the gradient*/
|
---|
418 | A[12] = .25*( (f(m2,n2) - f(m2,n0)) - (f(m0,n2) - f(m0,n0)) );///( (x[n2]-x[n0])*(y[m2]-y[m0]) ); // d2f/dxdy (0,0)
|
---|
419 | A[13] = .25*( (f(m2,n3) - f(m2,n1)) - (f(m0,n3) - f(m0,n1)) );///( (x[n3]-x[n1])*(y[m2]-y[m0]) ); // d2f/dxdy (1,0)
|
---|
420 | A[14] = .25*( (f(m3,n2) - f(m3,n0)) - (f(m1,n2) - f(m1,n0)) );///( (x[n2]-x[n0])*(y[m3]-y[m1]) ); // d2f/dxdy (0,1)
|
---|
421 | A[15] = .25*( (f(m3,n3) - f(m3,n1)) - (f(m1,n3) - f(m1,n1)) );///( (x[n3]-x[n1])*(y[m3]-y[m1]) ); // d2f/dxdy (1,1)
|
---|
422 | }/*}}}*/
|
---|
423 | /*LaunchThread{{{*/
|
---|
424 | void LaunchThread(void* function(void*), void* usr,int num_threads){
|
---|
425 |
|
---|
426 | int i;
|
---|
427 | int *status = NULL;
|
---|
428 | pthread_t *threads = NULL;
|
---|
429 | pthread_handle *handles = NULL;
|
---|
430 |
|
---|
431 | /*dynamically allocate: */
|
---|
432 | threads=(pthread_t*)mxMalloc(num_threads*sizeof(pthread_t));
|
---|
433 | handles=(pthread_handle*)mxMalloc(num_threads*sizeof(pthread_handle));
|
---|
434 |
|
---|
435 | for(i=0;i<num_threads;i++){
|
---|
436 | handles[i].usr=usr;
|
---|
437 | handles[i].my_thread =i;
|
---|
438 | handles[i].num_threads=num_threads;
|
---|
439 | }
|
---|
440 |
|
---|
441 | if(num_threads==1){
|
---|
442 | function(handles);
|
---|
443 | }
|
---|
444 | else{
|
---|
445 | for(i=0;i<num_threads;i++){
|
---|
446 | if(pthread_create(threads+i,NULL,function,(void*)(handles+i))){
|
---|
447 | mexErrMsgTxt("pthread_create error");
|
---|
448 | }
|
---|
449 | }
|
---|
450 | for(i=0;i<num_threads;i++){
|
---|
451 | if(pthread_join(threads[i],(void**)&status)){
|
---|
452 | mexErrMsgTxt("pthread_join error");
|
---|
453 | }
|
---|
454 | }
|
---|
455 | }
|
---|
456 |
|
---|
457 | /*Free ressources:*/
|
---|
458 | mxFree(threads);
|
---|
459 | mxFree(handles);
|
---|
460 | }/*}}}*/
|
---|
461 | /*FetchMatrixPointer {{{*/
|
---|
462 | void FetchMatrixPointer(double** pmatrix,int *pM,int *pN,const mxArray* dataref){
|
---|
463 |
|
---|
464 | double *matrix=NULL;
|
---|
465 | double *values=NULL;
|
---|
466 | int N,M;
|
---|
467 |
|
---|
468 | if(mxIsEmpty(dataref) ){
|
---|
469 | M=N=0;
|
---|
470 | matrix=NULL;
|
---|
471 | }
|
---|
472 | else if (mxIsDouble(dataref) ){
|
---|
473 | M=mxGetM(dataref);
|
---|
474 | N=mxGetN(dataref);
|
---|
475 | matrix=(double*)mxGetPr(dataref);
|
---|
476 | }
|
---|
477 | else{
|
---|
478 | mexErrMsgTxt("matrix type not supported");
|
---|
479 | }
|
---|
480 |
|
---|
481 | *pmatrix=matrix;
|
---|
482 | if (pN)*pN=N;
|
---|
483 | if (pM)*pM=M;
|
---|
484 | }/*}}}*/
|
---|
485 | /*FetchVectorPointer {{{*/
|
---|
486 | void FetchVectorPointer(double** pvector,int *pN,const mxArray* dataref){
|
---|
487 |
|
---|
488 | double *vector=NULL;
|
---|
489 | double *values=NULL;
|
---|
490 | int N;
|
---|
491 |
|
---|
492 | if(mxIsEmpty(dataref) ){
|
---|
493 | N=0;
|
---|
494 | vector=NULL;
|
---|
495 | }
|
---|
496 | else if (mxIsDouble(dataref) ){
|
---|
497 | if(mxGetM(dataref)!=1 && mxGetN(dataref)!=1){
|
---|
498 | mexErrMsgTxt("input is a matrix and not a vector");
|
---|
499 | }
|
---|
500 | N=mxGetN(dataref)*mxGetM(dataref);
|
---|
501 | vector=(double*)mxGetPr(dataref);
|
---|
502 | }
|
---|
503 | else{
|
---|
504 | mexErrMsgTxt("vector type not supported");
|
---|
505 | }
|
---|
506 |
|
---|
507 | *pvector=vector;
|
---|
508 | if (pN)*pN=N;
|
---|
509 | }/*}}}*/
|
---|
510 | /*FetchString{{{*/
|
---|
511 | void FetchString(char** pstring,const mxArray* dataref){
|
---|
512 |
|
---|
513 | char* outstring=NULL;
|
---|
514 |
|
---|
515 | /*Ok, the string should be coming directly from the matlab workspace: */
|
---|
516 | if (!mxIsClass(dataref,"char")){
|
---|
517 | mexErrMsgTxt("input data_type is not a string!");
|
---|
518 | }
|
---|
519 | else{
|
---|
520 | /*Recover the string:*/
|
---|
521 | int stringlen;
|
---|
522 |
|
---|
523 | stringlen = mxGetM(dataref)*mxGetN(dataref)+1;
|
---|
524 | outstring = (char*)mxMalloc(stringlen*sizeof(char));
|
---|
525 | mxGetString(dataref,outstring,stringlen);
|
---|
526 | }
|
---|
527 |
|
---|
528 | /*Assign output pointers:*/
|
---|
529 | *pstring=outstring;
|
---|
530 | return;
|
---|
531 | }/*}}}*/
|
---|
532 | /*WriteMatrix {{{*/
|
---|
533 | void WriteMatrix(mxArray** pdataref,double* matrix,int M,int N){
|
---|
534 |
|
---|
535 | mxArray* dataref=NULL;
|
---|
536 |
|
---|
537 | if(matrix){
|
---|
538 | /*data is a double* pointer. set pointer and invert sizes*/
|
---|
539 | dataref = mxCreateDoubleMatrix(0,0,mxREAL);
|
---|
540 | mxSetM(dataref,(mwSize)M);
|
---|
541 | mxSetN(dataref,(mwSize)N);
|
---|
542 | mxSetPr(dataref,(double*)matrix);
|
---|
543 | }
|
---|
544 | else{
|
---|
545 | dataref = mxCreateDoubleScalar(0.0);
|
---|
546 | }
|
---|
547 | *pdataref=dataref;
|
---|
548 | }
|
---|
549 | /*}}}*/
|
---|
550 | /*WriteVector {{{*/
|
---|
551 | void WriteVector(mxArray** pdataref,double* vector,int N){
|
---|
552 |
|
---|
553 | mxArray* dataref=NULL;
|
---|
554 |
|
---|
555 | if(vector){
|
---|
556 | /*data is a double* pointer. Copy into a vector: */
|
---|
557 | dataref = mxCreateDoubleMatrix(0,0,mxREAL);
|
---|
558 | mxSetM(dataref,(mwSize)N);
|
---|
559 | mxSetN(dataref,(mwSize)1);
|
---|
560 | mxSetPr(dataref,(double*)vector);
|
---|
561 | }
|
---|
562 | else{
|
---|
563 | dataref = mxCreateDoubleScalar(0.0);
|
---|
564 | }
|
---|
565 | *pdataref=dataref;
|
---|
566 | }
|
---|
567 | /*}}}*/
|
---|