/ani/mrses

To get this branch, use:
bzr branch http://darksoft.org/webbzr/ani/mrses
1 by Suren A. Chilingaryan
Initial import
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <sys/time.h>
5
6
7
#include <mex.h>
8
9
#include "mrses.h"
10
#include "msg.h"
11
12
#define MAX_FILE_NAME 2048
13
/*#define USE_UNDOCUMENTED*/
14
15
#ifndef EXTERN_C
16
# ifdef __cplusplus
17
   #define EXTERN_C extern "C"
18
# else
19
   #define EXTERN_C extern
20
# endif
21
#endif
22
23
#ifdef USE_UNDOCUMENTED
24
EXTERN_C mxArray *mxCreateSharedDataCopy(const mxArray *pr);
25
#endif /* USE_UNDOCUMENTED */
26
27
28
typedef enum {
29
    ACTION_SETUP = 1,
30
    ACTION_COMPUTE = 10,
31
    ACTION_ITERATE = 15,
32
    ACTION_GET_HIST = 16
33
} TAction;
34
35
36
struct MEXContextT {
37
    MRSESContext mrses;
38
    mxArray *res; 
39
    mxArray *hist;
40
    unsigned int initialized;
41
    unsigned int width, max_block;
42
};
43
typedef struct MEXContextT MEXContextS;
44
typedef struct MEXContextT *MEXContext;
45
46
static MEXContext pstate = NULL;
47
48
MEXContext mexCreateContext() {
49
    pstate = (MEXContext)malloc(sizeof(MEXContextS));
50
    if (pstate) {
51
	MRSESContext ctx = mrses_create_context();
52
	if (!ctx) {
53
	    free(pstate);
54
	    return NULL;
55
	}
56
	
57
	memset(pstate, 0, sizeof(MEXContextS));
58
	pstate->mrses = ctx;
59
    }
60
    return pstate;
61
}
62
63
void mexDestroyContext(MEXContext pstate) {
64
    if (pstate) {
65
	if (pstate->res) {
66
	    mxDestroyArray(pstate->res);
67
	}
68
	if (pstate->hist) {
69
	    mxDestroyArray(pstate->hist);
70
	}
71
	if (pstate->mrses) {
72
	    mrses_destroy_context(pstate->mrses);
73
	}
74
	free(pstate);
75
    }
76
}
77
78
static void selfClean() {
79
    if (pstate) {
80
	reportMessage("Cleaning hw instance");
81
82
	mexDestroyContext(pstate);
83
	pstate = NULL;
84
    }
85
86
}
87
88
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
89
    int err;
90
91
    mxArray *idMatrix;
92
    int32_t *idPtr;
93
94
    static int32_t id = 0;
95
    
96
    MRSESDistance dist;
97
    MRSESIntType *ires;
98
    const mxArray *A, *B, *index;
99
    mxArray *res;
100
    unsigned int iterations;
101
    unsigned int properties;
102
    unsigned int block_size;
103
    unsigned int width;
104
105
    MEXContext ps;
106
    TAction action;
107
108
109
    if (!nrhs) {
110
	reportMessage("Initializing hw instance");
111
112
	if (nlhs != 1) {
113
	    reportError("You should accept a single result from initialization call");
114
	    return;
115
	}
116
	
117
	idMatrix = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL);
118
	if (!idMatrix) {
119
	    reportError("Initialization is failed");
120
	    return;
121
	}
122
123
	if (pstate) mexDestroyContext(pstate);
124
	pstate = mexCreateContext();
125
	
126
	if (pstate) {
127
	    mexAtExit(selfClean);
128
	    id = 1;
129
	} else if (id > 0) {
130
	    reportError("Context initialization has failed");
131
	    id = -1;
132
	}
133
134
	idPtr = (int32_t*)mxGetData(idMatrix);
135
	idPtr[0] = id;
136
	
137
	plhs[0] = idMatrix;
138
	return;
139
    } else {
140
	if (!pstate) {
141
	    reportError("normxcorr_hw should be initialized first");
142
	    return;
143
	}
144
    }
145
146
	/* Clean request */
147
    if (nrhs == 1) {
148
	selfClean();
149
	return;
150
    }
151
152
    ps = pstate;
153
154
    action = (TAction)(mxGetScalar((mxArray*)prhs[1]));
155
156
    /*reportMessage("Executing normxcorr_hw action: %u", action);*/
157
158
    switch (action) {
159
     case ACTION_SETUP:
160
        if ((nrhs < 6)||(nrhs > 7)) {
161
	    reportError("Initialization call expects following arguments: 'width', 'block_size', matrices 'A' and 'B', distance_type");
162
	    return;
163
	}
164
	
165
	width = (int)mxGetScalar(prhs[2]);
166
	block_size = (int)mxGetScalar(prhs[3]);
167
	if (nrhs == 7) {
168
	    dist = (int)mxGetScalar(prhs[6]) - 1;
169
	    if (dist >= MRSES_DISTANCE_LAST) {
170
		reportError("Invalid distance mode is requested: %i", dist);
171
		return;
172
	    }
173
	} else dist = BHATTACHARYYA;
174
	A = prhs[4];
175
	B = prhs[5];
176
	
177
	properties = mxGetN(A);
178
	if (properties != mxGetN(B)) {
179
	    reportError("Dimenssions of matrices A and B does not match: %i, %i", properties, mxGetN(B));
180
	    return;
181
	}
182
	
183
	if ((mxGetClassID(A) == mxSINGLE_CLASS)&&(mxGetClassID(B) == mxSINGLE_CLASS)) {
184
	    err = mrses_init_context(ps->mrses, properties, mxGetM(A), mxGetData(A), mxGetM(B), mxGetData(B));
185
	} else if ((mxGetClassID(A) == mxDOUBLE_CLASS)&&(mxGetClassID(B) == mxDOUBLE_CLASS)) {
186
	    err = mrses_init_context_from_double(ps->mrses, properties, mxGetM(A), mxGetData(A), mxGetM(B), mxGetData(B));
187
	} else {
188
	    reportError("Only single-precision floating point numbers are supported");
189
	    return;
190
	}
191
	
192
	if (err) {
193
	    reportError("Initialization is failed with error, %i", err);
194
	    return;
195
	}
196
	
197
	err = mrses_set_distance_mode(ps->mrses, dist);
198
	if (err) {
199
	    reportError("Failed to set distance mode, error %i", err);
200
	    return;
201
	}
202
	
203
	err = mrses_prepare(ps->mrses, width, block_size);
204
	if (err) {
205
	    reportError("Failed to prepare for execution, error %i", err);
206
	    return;
207
	}
208
209
	if (ps->res) mxDestroyArray(ps->res);
210
	ps->res = mxCreateNumericMatrix(block_size, 1, mxSINGLE_CLASS, mxREAL);
211
	if (ps->res) mexMakeArrayPersistent(ps->res);
212
	else {
213
	    reportError("Allocation of result matrix of size %u*float bytes is failed", block_size);
214
	    return;
215
	}
216
	
217
	if (ps->hist) mxDestroyArray(ps->hist);
218
	ps->hist = mxCreateNumericMatrix(1, properties, mxUINT32_CLASS, mxREAL);
219
	if (ps->hist) mexMakeArrayPersistent(ps->hist);
220
	else {
221
	    reportError("Allocation of result matrix of size %u*uint32_t bytes is failed", properties);
222
	    return;
223
	}
224
225
	ps->width = width;
226
	ps->max_block = block_size;
227
	ps->initialized = 1;
228
     break;
229
     case ACTION_COMPUTE:
230
	if (!pstate->initialized) {
231
	    reportError("We are not initialized yet, issue intialize call first");
232
	    return;
233
	}
234
235
        if ((nlhs != 1)||((nrhs < 3)||(nrhs > 4))) {
236
	    reportError("Compute call expects following arguments: 'block_size', 'index'. It should accept a single result matrix as well.");
237
	    return;
238
	}
239
	
240
	if (nrhs > 3) {
241
	    block_size = (int)mxGetScalar(prhs[2]);
242
	    index = prhs[3];
243
244
	    if (mxGetN(index) < block_size) {
245
		reportError("Index matrix does not contain specified number of blocks");
246
		return;
247
	    }
248
	} else {
249
	    index = prhs[2];
250
	    block_size = mxGetN(index);
251
	}
252
253
	if (block_size > pstate->max_block) {
254
	    reportError("The block is too big: maximum configured size is %i, but %i supplied", pstate->max_block, block_size);
255
	    return;
256
	}
257
	
258
	width = mxGetM(index);
259
	if (pstate->width != width) {
260
	    reportError("The index matrix dimension does not fit requirement: width = %i, but index side is %i", pstate->width, width);
261
	    return;
262
	}
263
	
264
	if (mxGetClassID(index) != mxINT16_CLASS) {
265
	    reportError("Only 16 bit integers are supported for index");
266
	    return;
267
	}
268
	
269
	res = ps->res;
270
	mxSetN(res, block_size);
271
	mxSetM(res, 1);
272
273
	err = mrses_compute(ps->mrses, block_size, mxGetData(index), mxGetData(res));
274
	if (err) {
275
	    reportError("Error executing compute, failed with code: %i", err);
276
	    return;
277
	}
278
279
#ifdef USE_UNDOCUMENTED
280
	plhs[0] = mxCreateSharedDataCopy(res);
281
#else /* USE_UNDOCUMENTED */
282
	plhs[0] = mxDuplicateArray(res);
283
#endif /* USE_UNDOCUMENTED */
284
	
285
     break;
286
     case ACTION_ITERATE:
287
	if (!pstate->initialized) {
288
	    reportError("We are not initialized yet, issue intialize call first");
289
	    return;
290
	}
291
292
        if (nrhs != 4) {
293
	    reportError("Iterate call expects following arguments: 'iterations', 'block_size'.");
294
	    return;
295
	}
296
	
297
	iterations = (int)mxGetScalar(prhs[2]);
298
	block_size = (int)mxGetScalar(prhs[3]);
299
300
	if (block_size > pstate->max_block) {
301
	    reportError("The block is too big: maximum configured size is %i, but %i supplied", pstate->max_block, block_size);
302
	    return;
303
	}
304
305
	if (nlhs == 1) {
306
	    idMatrix = mxCreateNumericMatrix(pstate->width, pstate->max_block, mxUINT16_CLASS, mxREAL);
307
	    mxSetN(idMatrix, block_size);
308
	    ires = mxGetData(idMatrix);
309
	    plhs[0] = idMatrix;
310
	} else {
311
	    ires = NULL;
312
	}
313
	err = mrses_iterate(ps->mrses, iterations, block_size, ires);
314
	if (err) {
315
	    reportError("Error executing iterate, failed with code: %i", err);
316
	    return;
317
	}
318
     break;
319
     case ACTION_GET_HIST:
320
	if (!pstate->initialized) {
321
	    reportError("We are not initialized yet, issue intialize call first");
322
	    return;
323
	}
324
325
        if ((nlhs != 1)&&(nrhs != 2)) {
326
	    reportError("GetHist call returns histogram vector and expects no arguments.");
327
	    return;
328
	}
329
330
	res = ps->hist;
331
	err = mrses_get_results(ps->mrses, mxGetData(res));
332
	if (err) {
333
	    reportError("Error executing iterate, failed with code: %i", err);
334
	    return;
335
	}
336
337
	plhs[0] = mxDuplicateArray(res);
338
     break;
339
     default:
340
        reportError("Unknown request %i", action);
341
    }
342
}