portage to windows of MPI module, add some errors messages
[scilab.git] / scilab / modules / mpi / src / c / serialization.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011-2011 - DIGITEO - Antoine ELIAS
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12 #include <string.h>
13 #include <stdio.h>
14 #include "api_scilab.h"
15 #include "BOOL.h"
16 #include "MALLOC.h"
17 #include "serialization.h"
18
19 static int serialize_double(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
20 {
21     SciErr sciErr;
22     int iRows = 0;
23     int iCols = 0;
24     int iOne = 1;
25     int iSize = 0;
26     double *pdblR = NULL;
27     double *pdblI = NULL;
28
29     int *piOut = NULL;
30     int iOutLen = 0;
31
32     if (isVarComplex(_pvCtx, _piAddr))
33     {
34         double *p = NULL;
35
36         sciErr = getComplexMatrixOfDouble(_pvCtx, _piAddr, &iRows, &iCols, &pdblR, &pdblI);
37         if (sciErr.iErr)
38         {
39             printError(&sciErr, 0);
40             return 1;
41         }
42
43         iOutLen = 4 + (2 * iRows * iCols * sizeof(double) / sizeof(int));
44         piOut = (int *)MALLOC(iOutLen * sizeof(int));
45         if (piOut == NULL)
46         {
47             return 1;
48         }
49
50         piOut[0] = sci_matrix;
51         piOut[1] = iRows;
52         piOut[2] = iCols;
53         piOut[3] = 1;           //complex
54
55         //move 'p' to first real value
56         p = (double *)(piOut + 4);
57         iSize = iRows * iCols;
58         C2F(dcopy) (&iSize, pdblR, &iOne, p, &iOne);
59         //move 'p' to first complex value
60         p = p + iRows * iCols;
61         C2F(dcopy) (&iSize, pdblI, &iOne, p, &iOne);
62     }
63     else
64     {
65         double *p = NULL;
66
67         sciErr = getMatrixOfDouble(_pvCtx, _piAddr, &iRows, &iCols, &pdblR);
68         if (sciErr.iErr)
69         {
70             printError(&sciErr, 0);
71             return 1;
72         }
73
74         iOutLen = 4 + (iRows * iCols * sizeof(double) / sizeof(int));
75         piOut = (int *)MALLOC(iOutLen * sizeof(int));
76         if (piOut == NULL)
77         {
78             return 1;
79         }
80
81         piOut[0] = sci_matrix;
82         piOut[1] = iRows;
83         piOut[2] = iCols;
84         piOut[3] = 0;           //not complex
85
86         //move 'p' to first value
87         p = (double *)(piOut + 4);
88         iSize = iRows * iCols;
89         C2F(dcopy) (&iSize, pdblR, &iOne, p, &iOne);
90     }
91
92     *_piBuffer = piOut;
93     *_piBufferSize = iOutLen;
94     return 0;
95 }
96
97 static int serialize_string(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
98 {
99     int iErr = 0;
100     int i = 0;
101     int iRows = 0;
102     int iCols = 0;
103     char **pstData = NULL;
104     char *p = NULL;
105
106     int *piOut = NULL;
107     int *piOutLen = NULL;
108     int iOutLen = 0;
109
110     iErr = getAllocatedMatrixOfString(_pvCtx, _piAddr, &iRows, &iCols, &pstData);
111     if (iErr)
112     {
113         return 1;
114     }
115
116     for (i = 0; i < iRows * iCols; i++)
117     {
118         iOutLen += (int)strlen(pstData[i]);
119     }
120
121     if (iOutLen % 4)
122     {
123         iOutLen = iOutLen / (sizeof(int) / sizeof(char)) + 1;
124     }
125     else
126     {
127         iOutLen = iOutLen / (sizeof(int) / sizeof(char));
128     }
129
130     //4 for header and size of each string
131     iOutLen += 4 + iRows * iCols;
132
133     piOut = (int *)MALLOC(iOutLen * sizeof(int));
134     if (piOut == NULL)
135     {
136         return 1;
137     }
138
139     piOut[0] = sci_strings;
140     piOut[1] = iRows;
141     piOut[2] = iCols;
142     piOut[3] = 0;               //not complex
143
144     piOutLen = piOut + 4;
145
146     for (i = 0; i < iRows * iCols; i++)
147     {
148         piOutLen[i] = (int)strlen(pstData[i]);
149     }
150
151     p = (char *)(piOut + 4 + iRows * iCols);
152     for (i = 0; i < iRows * iCols; i++)
153     {
154         memcpy(p, pstData[i], piOutLen[i]);
155         p += piOutLen[i];
156     }
157
158     *_piBuffer = piOut;
159     *_piBufferSize = iOutLen;
160     return 0;
161 }
162
163 static int serialize_boolean(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
164 {
165     SciErr sciErr;
166     int iRows = 0;
167     int iCols = 0;
168     int *piBool = NULL;
169     int *p = NULL;
170
171     int *piOut = NULL;
172     int iOutLen = 0;
173
174     sciErr = getMatrixOfBoolean(_pvCtx, _piAddr, &iRows, &iCols, &piBool);
175     if (sciErr.iErr)
176     {
177         printError(&sciErr, 0);
178         return 1;
179     }
180
181     //4 for header and 1 for each boolean
182     iOutLen = 4 + iRows * iCols;
183
184     piOut = (int *)MALLOC(iOutLen * sizeof(int *));
185     if (piOut == NULL)
186     {
187         return 1;
188     }
189
190     piOut[0] = sci_boolean;
191     piOut[1] = iRows;
192     piOut[2] = iCols;
193     piOut[3] = 0;               //not complex
194
195     p = (int *)(piOut + 4);
196     memcpy(p, piBool, iRows * iCols * sizeof(int));
197
198     *_piBuffer = piOut;
199     *_piBufferSize = iOutLen;
200     return 0;
201 }
202
203 static int serialize_int(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
204 {
205     SciErr sciErr;
206     int iPrecision = 0;
207     int iRows = 0;
208     int iCols = 0;
209     int iItemSize = 0;
210     void *p = NULL;
211     void *pvData = NULL;
212
213     int *piOut = NULL;
214     int iOutLen = 0;
215
216     sciErr = getVarDimension(_pvCtx, _piAddr, &iRows, &iCols);
217     if (sciErr.iErr)
218     {
219         printError(&sciErr, 0);
220         return 1;
221     }
222
223     sciErr = getMatrixOfIntegerPrecision(_pvCtx, _piAddr, &iPrecision);
224     if (sciErr.iErr)
225     {
226         printError(&sciErr, 0);
227         return 1;
228     }
229
230     if (iPrecision == SCI_INT8 || iPrecision == SCI_UINT8)
231     {
232         iItemSize = sizeof(char);
233     }
234     else if (iPrecision == SCI_INT16 || iPrecision == SCI_UINT16)
235     {
236         iItemSize = sizeof(short);
237     }
238     else if (iPrecision == SCI_INT32 || iPrecision == SCI_UINT32)
239     {
240         iItemSize = sizeof(int);
241     }
242     /*
243         else if(iPrecision == SCI_INT64 || iPrecision == SCI_UINT64)
244         {
245             iItemSize = sizeof(long long);
246         }
247     */
248     //check and adjust alignement on integer
249     iOutLen = iRows * iCols;
250     if ((iOutLen * iItemSize) % sizeof(int))
251     {
252         iOutLen = (iOutLen * iItemSize) / sizeof(int) + 1;
253     }
254     else
255     {
256         iOutLen = (iOutLen * iItemSize) / (sizeof(int));
257     }
258
259     iOutLen += 4;
260     piOut = (int *)MALLOC(iOutLen * sizeof(int *));
261     if (piOut == NULL)
262     {
263         return 1;
264     }
265
266     piOut[0] = sci_ints;
267     piOut[1] = iRows;
268     piOut[2] = iCols;
269     piOut[3] = iPrecision;      //precision
270
271     switch (iPrecision)
272     {
273         case SCI_INT8:
274         {
275             sciErr = getMatrixOfInteger8(_pvCtx, _piAddr, &iRows, &iCols, (char **)&pvData);
276             break;
277         }
278         case SCI_UINT8:
279         {
280             sciErr = getMatrixOfUnsignedInteger8(_pvCtx, _piAddr, &iRows, &iCols, (unsigned char **)&pvData);
281             break;
282         }
283         case SCI_INT16:
284         {
285             sciErr = getMatrixOfInteger16(_pvCtx, _piAddr, &iRows, &iCols, (short **)&pvData);
286             break;
287         }
288         case SCI_UINT16:
289         {
290             sciErr = getMatrixOfUnsignedInteger16(_pvCtx, _piAddr, &iRows, &iCols, (unsigned short **)&pvData);
291             break;
292         }
293         case SCI_INT32:
294         {
295             sciErr = getMatrixOfInteger32(_pvCtx, _piAddr, &iRows, &iCols, (int **)&pvData);
296             break;
297         }
298         case SCI_UINT32:
299         {
300             sciErr = getMatrixOfUnsignedInteger32(_pvCtx, _piAddr, &iRows, &iCols, (unsigned int **)&pvData);
301             break;
302         }
303         /*
304             case SCI_INT64 :
305             {
306                 sciErr = getMatrixOfInteger64(_pvCtx, _piAddr, &iRows, &iCols, (long long**)&pvData);
307                 break;
308             }
309             case SCI_UINT64 :
310             {
311                 sciErr = getMatrixOfUnsignedInteger64(_pvCtx, _piAddr, &iRows, &iCols, (unsigned long long**)&pvData);
312                 break;
313                 }
314         */ default:
315             return 1;
316     }
317
318     if (sciErr.iErr)
319     {
320         printError(&sciErr, 0);
321         return 1;
322     }
323
324     p = piOut + 4;
325     memcpy(p, pvData, iRows * iCols * iItemSize);
326     *_piBuffer = piOut;
327     *_piBufferSize = iOutLen;
328     return 0;
329 }
330
331 static int serialize_sparse(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize, BOOL _bData)
332 {
333     int iRet = 0;
334     int iRows = 0;
335     int iCols = 0;
336     int iItemCount = 0;
337     int *piRowCount = 0;
338     int *piColPos = 0;
339     int iComplex = 0;
340
341     double *pdblR = NULL;
342     double *pdblI = NULL;
343
344     int *piOut = NULL;
345     int iOutLen = 0;
346
347     if (_bData)
348     {
349         //sparse
350
351         iComplex = isVarComplex(_pvCtx, _piAddr);
352         if (iComplex)
353         {
354             iRet = getAllocatedComplexSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos, &pdblR, &pdblI);
355         }
356         else
357         {
358             iRet = getAllocatedSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos, &pdblR);
359         }
360     }
361     else
362     {
363         //boolean sparse
364         iRet = getAllocatedBooleanSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos);
365     }
366
367     if (iRet)
368     {
369         return 1;
370     }
371
372     //5 -> 4 for header + 1 for item count
373     iOutLen = 5 + iRows + iItemCount;
374
375     if (_bData)
376     {
377         iOutLen += iItemCount * (iComplex + 1) * sizeof(double) / sizeof(int);
378     }
379
380     piOut = (int *)MALLOC(iOutLen * sizeof(int));
381
382     piOut[0] = _bData ? sci_sparse : sci_boolean_sparse;
383     piOut[1] = iRows;
384     piOut[2] = iCols;
385     piOut[3] = iComplex;
386     piOut[4] = iItemCount;
387
388     memcpy(piOut + 5, piRowCount, iRows * sizeof(int));
389     memcpy(piOut + 5 + iRows, piColPos, iItemCount * sizeof(int));
390
391     if (_bData)
392     {
393         int iOne = 1;
394         double *pRealData = (double *)(piOut + 5 + iRows + iItemCount);
395
396         C2F(dcopy) (&iItemCount, pdblR, &iOne, pRealData, &iOne);
397         if (iComplex)
398         {
399             double *pImgData = pRealData + iItemCount;
400
401             C2F(dcopy) (&iItemCount, pdblI, &iOne, pImgData, &iOne);
402         }
403     }
404
405     *_piBuffer = piOut;
406     *_piBufferSize = iOutLen;
407     return 0;
408 }
409
410 int serialize_to_mpi(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
411 {
412     switch (*_piAddr)
413     {
414         case sci_matrix:
415             return serialize_double(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
416             break;
417         case sci_strings:
418             return serialize_string(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
419             break;
420         case sci_boolean:
421             return serialize_boolean(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
422             break;
423         case sci_sparse:
424             return serialize_sparse(pvApiCtx, _piAddr, _piBuffer, _piBufferSize, TRUE);
425             break;
426         case sci_boolean_sparse:
427             return serialize_sparse(pvApiCtx, _piAddr, _piBuffer, _piBufferSize, FALSE);
428             break;
429         case sci_ints:
430             return serialize_int(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
431             break;
432         default:
433             return -1;
434             break;
435     }
436 }