/ani/mrses

To get this branch, use:
bzr branch http://suren.me/webbzr/ani/mrses

« back to all changes in this revision

Viewing changes to cell/mrses_hw.c

  • Committer: Suren A. Chilingaryan
  • Date: 2010-04-28 04:30:08 UTC
  • Revision ID: csa@dside.dyndns.org-20100428043008-vd9z0nso9axezvlp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}