21
int is_aligned(void *p, int N)
23
return (uintptr_t)p % N == 0;
26
void mexFunction( int nlhs, mxArray *plhs[],
27
int nrhs, const mxArray *prhs[])
29
/* prhs[0] int n_voxels */
30
/* prhs[1] int n_proj */
31
/* prhs[2] float cor */
33
/* prhs[4] float detector_size */
34
/* prhs[5] float pixel_size */
35
/* prhs[6] float cor_offset */
36
/* prhs[7] float detector_offset_u */
37
/* prhs[8] float detector_offset_v */
38
/* prhs[9] float detector_offset_z */
39
/* prhs[10] float s */
40
/* prhs[11] float u_detector */
41
/* prhs[12] float v_detector */
42
/* prhs[13] float n_detector_r */
43
/* prhs[14] float projections */
44
/* prhs[15] float slice_x */
45
/* prhs[16] float slice_y */
46
/* prhs[17] float slice_coord_z */
47
/* prhs[18] int n_threads */
49
int n_proj, n_threads;
51
Ipp32f cor, d, detector_size, pixel_size, cor_offset, detector_offset_u, detector_offset_v, detector_offset_z;
52
Ipp32f *source = NULL, *u_detector = NULL, *v_detector = NULL, *n_detector = NULL;
53
Ipp32f *projections = NULL;
54
Ipp32f *slice_x = NULL, *slice_y = NULL, *slice_coord_z = NULL;
55
Ipp32f *out_volume = NULL;
58
struct thread_info *t_info;
63
/*/////////// PARSE INPUT /////////////////*/
65
/* radiograph and slice size */
66
/* check n_voxels data type */
67
if (mxGetNumberOfElements(prhs[0])!=1 || !mxIsInt32(prhs[0]))
69
mexErrMsgTxt("mex: Input n_voxels is not scalar or int32.");
72
n_elements = (int)mxGetScalar(prhs[0]);
74
if (n_elements % 16 != 0)
76
printf("n_elements has to be multiple of 16 since IPPI uses 64 bytes alignment");
81
/* number of projections */
82
/* check n_proj data type */
83
if (mxGetNumberOfElements(prhs[1])!=1 || !mxIsInt32(prhs[1]))
85
mexErrMsgTxt("mex: Input n_proj is not scalar or int32.");
88
n_proj = (int)mxGetScalar(prhs[1]);
91
/* source to rotation distance */
92
/* check input cor data type */
93
if (!mxIsSingle(prhs[2]) || mxIsComplex(prhs[2]) || mxGetNumberOfElements(prhs[2])!=1)
95
mexErrMsgTxt("mex: Input cor must be scalar and have type single.");
98
cor = (Ipp32f)mxGetScalar(prhs[2]);
100
/* source to detector distance */
101
/* check input d data type */
102
if (!mxIsSingle(prhs[3]) || mxIsComplex(prhs[3]) || mxGetNumberOfElements(prhs[3])!=1)
104
mexErrMsgTxt("mex: Input d must be scalar and have type single.");
107
d = (Ipp32f)mxGetScalar(prhs[3]);
110
/* physical size of detector (assumed to be square) */
111
/* check input detector_size data type */
112
if (!mxIsSingle(prhs[4]) || mxIsComplex(prhs[4]) || mxGetNumberOfElements(prhs[4])!=1)
114
mexErrMsgTxt("mex: Input detector_size must be scalar and have type single.");
117
detector_size = (Ipp32f)mxGetScalar(prhs[4]);
120
/* physical pixel size */
121
/* check input pixel_size data type */
122
if (!mxIsSingle(prhs[5]) || mxIsComplex(prhs[5]) || mxGetNumberOfElements(prhs[5])!=1)
124
mexErrMsgTxt("mex: Input pixel_size must be scalar and have type single.");
127
pixel_size = (Ipp32f)mxGetScalar(prhs[5]);
131
/* check input cor_offset data type */
132
if (!mxIsSingle(prhs[6]) || mxIsComplex(prhs[6]) || mxGetNumberOfElements(prhs[6])!=1)
134
mexErrMsgTxt("mex: Input cor_offset must be scalar and have type single.");
137
cor_offset = (Ipp32f)mxGetScalar(prhs[6]);
140
/* detector offset in U direction */
141
/* check input detector_offset_u data type */
142
if (!mxIsSingle(prhs[7]) || mxIsComplex(prhs[7]) || mxGetNumberOfElements(prhs[7])!=1)
144
mexErrMsgTxt("mex: Input detector_offset_u must be scalar and have type single.");
147
detector_offset_u = (Ipp32f)mxGetScalar(prhs[7]);
150
/* detector offset in V direction */
151
/* check input detector_offset_v data type */
152
if (!mxIsSingle(prhs[8]) || mxIsComplex(prhs[8]) || mxGetNumberOfElements(prhs[8])!=1)
154
mexErrMsgTxt("mex: Input detector_offset_v must be scalar and have type single.");
157
detector_offset_v = (Ipp32f)mxGetScalar(prhs[8]);
160
/* detector offset along magnification line */
161
/* check input detector_offset_z data type */
162
if (!mxIsSingle(prhs[9]) || mxIsComplex(prhs[9]) || mxGetNumberOfElements(prhs[9])!=1)
164
mexErrMsgTxt("mex: Input detector_offset_z must be scalar and have type single.");
167
detector_offset_z = (Ipp32f)mxGetScalar(prhs[9]);
170
/* source position */
171
/* check input source data type */
172
if (!mxIsSingle(prhs[10]) || mxIsComplex(prhs[10]) || mxGetNumberOfElements(prhs[10])!=3)
174
mexErrMsgTxt("mex: Input source must be type single and contain 3 elements.");
177
source = (Ipp32f *)mxGetData(prhs[10]);
181
printf("Cannot get source");
186
/* detector coordinate frame */
187
/* check input u_detector data type */
188
if( !mxIsSingle(prhs[11]) || mxIsComplex(prhs[11]) || mxGetNumberOfElements(prhs[11])!=3)
190
mexErrMsgTxt("mex: Input u_detector must be type single and contain 3 elements.");
193
/* check input v_detector data type */
194
if( !mxIsSingle(prhs[12]) || mxIsComplex(prhs[12]) || mxGetNumberOfElements(prhs[12])!=3)
196
mexErrMsgTxt("mex: Input v_detector must be type single and contain 3 elements.");
199
/* check input n_detector data type */
200
if( !mxIsSingle(prhs[13]) || mxIsComplex(prhs[13]) || mxGetNumberOfElements(prhs[13])!=3)
202
mexErrMsgTxt("mex: Input n_detector must be type single and contain 3 elements.");
205
u_detector = (Ipp32f *)mxGetData(prhs[11]);
207
if (u_detector == NULL)
209
printf("Cannot get u_detector");
213
v_detector = (Ipp32f *)mxGetData(prhs[12]);
215
if (u_detector == NULL)
217
printf("Cannot get v_detector");
221
n_detector = (Ipp32f *)mxGetData(prhs[13]);
223
if (n_detector == NULL)
225
printf("Cannot get n_detector");
230
/* volume with projections, x-y-angle */
231
/* check input projections data type */
232
if (!mxIsSingle(prhs[14]) || mxIsComplex(prhs[14]))
234
mexErrMsgTxt("mex: Input projections array must be type single.");
237
/* check that number of elements in projections is equal to n_voxels x n_voxels x n_proj */
238
if ((mxGetNumberOfElements(prhs[14]) != (long)n_elements * n_elements * n_proj))
240
mexErrMsgTxt("mex: Input projections must be a n_elements x n_elements x n_proj array.");
243
projections = (Ipp32f *)mxGetData(prhs[14]);
245
if (projections == NULL) {
246
printf("Can not get projections");
250
/* check if dataset is aligned by 32 bytes */
251
if (is_aligned(projections, (int)alignment) == 0)
253
printf("Projections have to be aligned by 32 bytes\n");
259
/* check input slice_x data type */
260
if ( !mxIsSingle(prhs[15]) || mxIsComplex(prhs[15]))
262
mexErrMsgTxt("mex: Input slice_x array must be type single.");
265
/* check that number of rows and columns in slice_x is equal to n_voxels */
266
if(mxGetM(prhs[15]) != n_elements || mxGetN(prhs[15]) != n_elements)
268
mexErrMsgTxt("mex: Input slice_x must be a n_voxels x n_elements array.");
271
/* check input slice_y data type */
272
if( !mxIsSingle(prhs[16]) || mxIsComplex(prhs[16]))
274
mexErrMsgTxt("mex: Input slice_y array must be type single.");
277
/* check that number of rows and columns in slice_y is equal to n_voxels */
278
if(mxGetM(prhs[16]) != n_elements || mxGetN(prhs[16]) != n_elements)
280
mexErrMsgTxt("mex: Input slice_y must be a n_voxels x n_elements array.");
283
/* check input slice_coord_z data type */
284
if( !mxIsSingle(prhs[17]) || mxIsComplex(prhs[17]))
286
mexErrMsgTxt("mex: Input slice_coord_z array must be type single.");
289
/* check that number of elements in slice_coord_z is equal to n_voxels */
290
if(mxGetNumberOfElements(prhs[17]) != n_elements)
292
mexErrMsgTxt("mex: Input slice_coord_z must be a n_voxels array.");
295
slice_x = (Ipp32f *)mxGetData(prhs[15]);
299
printf("Cannot get slice_x");
303
/* check if slice_x is aligned by 32 bytes */
304
if (is_aligned(slice_x, (int)alignment) == 0)
306
printf("slice_x have to be aligned by 32 bytes\n");
310
slice_y = (Ipp32f *)mxGetData(prhs[16]);
314
printf("Cannot get slice_y");
318
/* check if slice_y is aligned by 32 bytes */
319
if (is_aligned(slice_y, (int)alignment) == 0)
321
printf("slice_y have to be aligned by 32 bytes\n");
325
slice_coord_z = (Ipp32f *)mxGetData(prhs[17]);
327
if (slice_coord_z == NULL) {
328
printf("Cannot get slice_coord_z");
334
/* check input n_threads data type */
335
if(mxGetNumberOfElements(prhs[18])!=1 || !mxIsInt32(prhs[18]))
337
mexErrMsgTxt("mex: Input n_threads is not scalar or int32.");
340
n_threads = (int)mxGetScalar(prhs[18]);
343
/* create the output matrix im_size x im_size*/
345
dims[0] = n_elements;
346
dims[1] = n_elements;
347
dims[2] = n_elements;
348
plhs[0] = mxCreateNumericArray((mwSize)3,dims,mxSINGLE_CLASS,mxREAL);
350
/* get a pointer to the data in the output matrix */
351
out_volume = (Ipp32f *)mxGetData(plhs[0]);
353
if (out_volume == NULL) {
354
printf("Cannot get out_volume");
358
/*//////// INITIALIZE THREADS /////////////*/
360
/* set global variable counter to zero */
363
/* allocate memory for threads */
364
t_info = (struct thread_info*) calloc(n_threads, sizeof(struct thread_info));
368
printf("Structure t_info memory allocation error\n");
372
/* fill tread_info structure and create threads */
373
for (tnum = 0; tnum < n_threads; tnum++)
375
t_info[tnum].thread_num = tnum; /* Application-defined thread # */
376
t_info[tnum].n_elements = n_elements;
377
t_info[tnum].n_proj = n_proj;
378
t_info[tnum].cor = cor;
380
t_info[tnum].detector_size = detector_size;
381
t_info[tnum].pixel_size = pixel_size;
382
t_info[tnum].cor_offset = cor_offset;
383
t_info[tnum].detector_offset_u = detector_offset_u;
384
t_info[tnum].detector_offset_v = detector_offset_v;
385
t_info[tnum].detector_offset_z = detector_offset_z;
386
t_info[tnum].source = source;
387
t_info[tnum].u_detector = u_detector;
388
t_info[tnum].v_detector = v_detector;
389
t_info[tnum].n_detector = n_detector;
390
t_info[tnum].projections = projections;
391
t_info[tnum].slice_x = slice_x;
392
t_info[tnum].slice_y = slice_y;
393
t_info[tnum].slice_coord_z = slice_coord_z;
394
t_info[tnum].out_volume = out_volume;
396
m = pthread_create(&t_info[tnum].thread_id, NULL, &process, &t_info[tnum]);
400
printf("Cannot create thread with error %i\n", m);
406
for (tnum = 0; tnum < n_threads; tnum++)
408
m = pthread_join(t_info[tnum].thread_id, &res);
412
printf("Cannot join threads with error %i\n", m);
b'\\ No newline at end of file'