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