some update on sparse comparisons
[scilab.git] / scilab / modules / hdf5 / sci_gateway / cpp / sci_export_to_hdf5.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
4 * Copyright (C) 2011 - DIGITEO - Cedric DELAMARRE
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13
14 #include <stdio.h>
15
16 #include "string.hxx"
17 #include "int.hxx"
18 #include "bool.hxx"
19 #include "polynom.hxx"
20 #include "tlist.hxx"
21 #include "mlist.hxx"
22 #include "function.hxx"
23 #include "context.hxx"
24 #include "hdf5_gw.hxx"
25
26 extern "C"
27 {
28 #include "MALLOC.h"
29 #include "localization.h"
30 #include "charEncoding.h"
31 #include "Scierror.h"
32 #include "h5_fileManagement.h"
33 #include "deleteafile.h"
34 #include "h5_writeDataToFile.h"
35 #include "sci_types.h"
36 }
37
38 #include "forceJHDF5load.hxx"
39
40 //#define PRINT_DEBUG
41 int iLevel = 0;
42
43 static bool export_data(int _iH5File, types::InternalType* pIT, wchar_t* _pwstName);
44 static bool export_list(int _iH5File, types::InternalType* pIT, wchar_t* _pwstName);
45 static bool export_double(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
46 static bool export_poly(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
47 static bool export_boolean(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
48 static bool export_sparse(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
49 //static bool export_boolean_sparse(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
50 //static bool export_matlab_sparse(void* pvApiCtx, int *_piVar, char* _pstName);
51 static bool export_ints(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
52 //static bool export_handles(void* pvApiCtx, int *_piVar, char* _pstName);
53 static bool export_strings(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
54 //static bool export_u_function(void* pvApiCtx, int *_piVar, char* _pstName);
55 //static bool export_c_function(void* pvApiCtx, int *_piVar, char* _pstName);
56 //static bool export_lib(void* pvApiCtx, int *_piVar, char* _pstName);
57 //static bool export_lufact_pointer(void* pvApiCtx, int *_piVar, char* _pstName);
58
59 static bool export_void(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName);
60
61
62 void print_type(char* _pstType);
63 int extractVarNameList(types::typed_list &in, wchar_t** _pstNameList);
64
65 /*--------------------------------------------------------------------------*/
66 types::Function::ReturnValue sci_export_to_hdf5(types::typed_list &in, int _iRetCount, types::typed_list &out)
67 {
68     int iNbVar              = 0;
69     wchar_t** pwstNameList      = NULL;
70     char* pstFileName       = NULL;
71     bool bExport            = false;
72
73 #ifndef _MSC_VER
74     forceJHDF5load();
75 #endif
76
77     if(in.size() < 2)
78     {
79         ScierrorW(77, _W("%ls: Wrong number of input argument(s): At least %d expected.\n"), L"export_to_hdf5", 2);
80         return types::Function::Error;
81     }
82
83     pwstNameList = (wchar_t**)MALLOC(sizeof(wchar_t*) * in.size());
84     iNbVar = extractVarNameList(in, pwstNameList);
85     if(iNbVar != 0)
86     {
87         //convert UTF16 to UTF8
88         pstFileName = wide_string_to_UTF8(pwstNameList[0]);
89
90         // open hdf5 file
91         int iH5File = createHDF5File(pstFileName);
92         if(iH5File < 0)
93         {
94             if(iH5File == -2)
95             {
96                 ScierrorW(999, _W("%ls: Wrong value for input argument #%d: \"%s\" is a directory"), L"export_to_hdf5", 1, pstFileName);
97             }
98             else
99             {
100                 ScierrorW(999,_W("%ls: Cannot open file %s.\n"), L"export_to_hdf5", pstFileName);
101             }
102
103             FREE(pstFileName);
104             FREE(pwstNameList);
105             return types::Function::Error;
106         }
107
108         for(int i = 0 ; i < in.size() - 1; i++)
109         {
110             types::InternalType* pIT = symbol::Context::getInstance()->get(symbol::Symbol(pwstNameList[i + 1]));
111
112             bExport = export_data(iH5File, pIT, pwstNameList[i + 1]);
113             if(bExport == false)
114             {
115                 break;
116             }
117         }
118
119         //close hdf5 file
120         closeHDF5File(iH5File);
121         if(bExport == false)
122         {//remove file
123             deleteafileW(pwstNameList[0]);
124         }
125     }
126     //create boolean return value
127     types::Bool* pOut = new types::Bool(bExport);
128     out.push_back(pOut);
129
130     //free allocated memory
131     FREE(pstFileName);
132     FREE(pwstNameList);
133
134     return types::Function::OK;
135 }
136
137 static bool export_data(int _iH5File, types::InternalType* pIT, wchar_t* _pwstName)
138 {
139     bool bReturn = false;
140
141     switch(pIT->getType())
142     {
143     case types::InternalType::RealDouble :
144         {
145             bReturn = export_double(_iH5File, pIT, _pwstName);
146             break;
147         }
148    case types::InternalType::RealPoly :
149         {
150             bReturn = export_poly(_iH5File, pIT, _pwstName);
151             break;
152         }
153     case types::InternalType::RealBool :
154         {
155             bReturn = export_boolean(_iH5File, pIT, _pwstName);
156             break;
157         }
158         /*
159     case sci_sparse :
160         {
161             bReturn = export_sparse(_iH5File, pIT, _pwstName);
162             break;
163         }
164     case sci_boolean_sparse :
165         {
166             bReturn = export_boolean_sparse(_iH5File, pIT, _pwstName);
167             break;
168         }
169     case sci_matlab_sparse :
170         {
171             bReturn = export_matlab_sparse(pvApiCtx, _piVar, _pwstName);
172             break;
173         }
174      */
175     case types::InternalType::RealInt8 :
176     case types::InternalType::RealUInt8 :
177     case types::InternalType::RealInt16 :
178     case types::InternalType::RealUInt16 :
179     case types::InternalType::RealInt32 :
180     case types::InternalType::RealUInt32 :
181     case types::InternalType::RealInt64 :
182     case types::InternalType::RealUInt64 :
183         {
184             bReturn = export_ints(_iH5File, pIT, _pwstName);
185             break;
186         }
187         /*
188     case sci_handles :
189         {
190             bReturn = export_handles(pvApiCtx, _piVar, _pwstName);
191             break;
192         }
193         */
194     case types::InternalType::RealString :
195         {
196             bReturn = export_strings(_iH5File, pIT, _pwstName);
197             break;
198         }
199         /*
200     case types::Function :
201         {
202             bReturn = export_u_function(pvApiCtx, _piVar, _pwstName);
203             break;
204         }
205     case sci_c_function :
206         {
207             bReturn = export_c_function(pvApiCtx, _piVar, _pwstName);
208             break;
209         }
210     case sci_lib :
211         {
212             bReturn = export_lib(pvApiCtx, _piVar, _pwstName);
213             break;
214         }
215         */
216     case types::InternalType::RealList :
217     case types::InternalType::RealTList :
218     case types::InternalType::RealMList :
219         {
220             bReturn = export_list(_iH5File, pIT, _pwstName);
221             break;
222         }
223         /*
224     case sci_lufact_pointer :
225         {
226             bReturn = export_lufact_pointer(pvApiCtx, _piVar, _pwstName);
227             break;
228         }
229         */
230     case 0 : //void case to "null" items in list
231         {
232             bReturn = export_void(_iH5File, pIT, _pwstName);
233             break;
234         }
235     }
236     return bReturn;
237 }
238
239
240 static bool export_void(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
241 {
242     int iRet = writeVoid(_iH5File, wide_string_to_UTF8(_pwstName));
243     if(iRet)
244     {
245         return false;
246     }
247
248     char pstMsg[] = "void";
249     print_type(pstMsg);
250     return true;
251 }
252
253 static bool export_undefined(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
254 {
255     int iRet = writeUndefined(_iH5File, wide_string_to_UTF8(_pwstName));
256     if(iRet)
257     {
258         return false;
259     }
260
261     char pstMsg[] = "void";
262     print_type(pstMsg);
263     return true;
264 }
265
266 static bool export_list(int _iH5File, types::InternalType* pIT, wchar_t* _pwstName)
267 {
268     int iRet        = 0;
269     char* pstName   = wide_string_to_UTF8(_pwstName);
270     bool bReturn    = false;
271
272     types::List* pList = pIT->getAs<types::List>();
273     int iItemNumber = pList->getSize();
274     //create groupe name
275     char* pstGroupName  = createGroupName(pstName);
276
277     iLevel++;
278     //open list
279     void *pvList = openList(_iH5File, pstGroupName, iItemNumber);
280     for(int i = 0 ; i < iItemNumber ; i++)
281     {
282         int *piNewVar = NULL;
283        // getListItemAddress(_piVar, i + 1, &piNewVar);//1 indexed
284         types::InternalType* pNewIT =  pList->get(i);
285         char* pstPathName   = createPathName(pstGroupName, i);
286         wchar_t* pwstPathName = to_wide_string(pstPathName);
287         if(pNewIT->isListUndefined())
288         {//undefined item
289             bReturn = export_undefined(_iH5File, pNewIT, pwstPathName);
290         }
291         else
292         {
293             bReturn = export_data(_iH5File, pNewIT, pwstPathName);
294         }
295
296         iRet = addItemInList(_iH5File, pvList, i, pstPathName);
297         FREE(pstPathName);
298         FREE(pwstPathName);
299
300         if(bReturn == false || iRet)
301             return false;
302     }
303     iLevel--;
304
305     int type = 0;
306     switch(pIT->getType())
307     {
308     case types::InternalType::RealList :
309         type = sci_list;
310         break;
311     case types::InternalType::RealTList :
312         type = sci_tlist;
313         break;
314     case types::InternalType::RealMList :
315         type = sci_mlist;
316         break;
317     default : return false;
318     }
319
320     closeList(_iH5File, pvList, pstName, iItemNumber, type);
321     FREE(pstGroupName);
322     //close list
323     return true;
324 }
325
326 static bool export_double(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
327 {
328     int iRet            = 0;
329     types::Double* pDbl = pIT->getAs<types::Double>();
330     char* pstName       = wide_string_to_UTF8(_pwstName);
331
332     if(pDbl->isComplex())
333         iRet = writeDoubleComplexMatrix(_iH5File, pstName, pDbl->getRows(), pDbl->getCols(), pDbl->getReal(), pDbl->getImg());
334     else
335         iRet = writeDoubleMatrix(_iH5File, pstName, pDbl->getRows(), pDbl->getCols(), pDbl->getReal());
336
337     FREE(pstName);
338
339     if(iRet)
340     {
341         return false;
342     }
343
344     char pstMsg[512];
345     sprintf(pstMsg, "double (%d x %d)", pDbl->getRows(), pDbl->getCols());
346     print_type(pstMsg);
347     return true;
348 }
349
350 static bool export_poly(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
351 {
352     int iRet                = 0;
353     types::Polynom* pPoly   = pIT->getAs<types::Polynom>();
354     char* pstName           = wide_string_to_UTF8(_pwstName);
355     char* varName           = wide_string_to_UTF8(pPoly->getVariableName().c_str());
356     double** real           = NULL;
357     double** img            = NULL;
358     int* nbrCoef            = NULL;
359     int size                = pPoly->getRows()*pPoly->getCols();
360
361     real = (double**)MALLOC(size*sizeof(double*));
362     nbrCoef = (int*)MALLOC(size*sizeof(int));
363
364     for(int i=0; i < size; i++)
365     {
366         nbrCoef[i] = pPoly->get(i)->getRank();
367         real[i] = pPoly->get(i)->getCoefReal();
368     }
369
370     if(pPoly->isComplex())
371     {
372         img = (double**)MALLOC(size*sizeof(double*));
373         for(int i=0; i <size; i++)
374         {
375             img[i] = pPoly->get(i)->getCoefImg();
376         }
377
378         iRet = writePolyComplexMatrix(_iH5File, pstName, varName , pPoly->getRows(), pPoly->getCols(), nbrCoef, real, img);
379         FREE(img);
380     }
381     else
382     {
383         iRet = writePolyMatrix(_iH5File, pstName, varName, pPoly->getRows(), pPoly->getCols(), nbrCoef, real);
384     }
385
386     FREE(nbrCoef);
387     FREE(real);
388     FREE(pstName);
389     FREE(varName);
390
391     if(iRet)
392     {
393         return false;
394     }
395 /*
396     char pstMsg[512];
397     sprintf(pstMsg, "poly (%d x %d)", iRows, iCols);
398     print_type(pstMsg);
399 */
400     return true;
401 }
402
403 static bool export_boolean(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
404 {
405     int iRet            = 0;
406     types::Bool* pBool  = pIT->getAs<types::Bool>();
407     char* pstName       = wide_string_to_UTF8(_pwstName);
408
409     iRet = writeBooleanMatrix(_iH5File, pstName, pBool->getRows(), pBool->getCols(), pBool->get());
410
411     FREE(pstName);
412
413     if(iRet)
414     {
415         //Msg ??
416         return false;
417     }
418
419     char pstMsg[512];
420     sprintf(pstMsg, "bool (%d x %d)", pBool->getRows(), pBool->getCols());
421     print_type(pstMsg);
422     return true;
423 }
424 /*
425 static bool export_boolean_sparse(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
426 {
427     int iRet                                            = 0;
428     int iRows                                           = 0;InternalType::Real
429     int iCols                                           = 0;
430     int iNbItem                                 = 0;
431     int* piNbItemRow            = NULL;
432     int* piColPos                               = NULL;
433
434     SciErr sciErr = getBooleanSparseMatrix(pvApiCtx, _piVar, &iRows, &iCols, &iNbItem, &piNbItemRow, &piColPos);
435     if(sciErr.iErr)
436     {
437         printError(&sciErr, 0);
438         return false;
439     }
440
441     iRet = writeBooleanSparseMatrix(_iH5File, _pstName, iRows, iCols, iNbItem, piNbItemRow, piColPos);
442     if(iRet)
443     {
444         //Msg ??
445         return false;
446     }
447
448     char pstMsg[512];
449     sprintf(pstMsg, "boolean sparse (%d x %d)", iRows, iCols);
450     print_type(pstMsg);
451     return true;
452 }
453 /*
454 static bool export_sparse(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
455 {
456     int iRet                                            = 0;
457     int iRows                                           = 0;
458     int iCols                                           = 0;
459     int iNbItem                                 = 0;
460     int* piNbItemRow            = NULL;
461     int* piColPos                               = NULL;
462     double* pdblReal            = NULL;
463     double* pdblImg             = NULL;
464     SciErr sciErr;
465
466     if(isVarComplex(pvApiCtx, _piVar))
467     {
468         sciErr = getComplexSparseMatrix(pvApiCtx, _piVar, &iRows, &iCols, &iNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
469         if(sciErr.iErr)
470         {
471             printError(&sciErr, 0);
472             return false;
473         }
474
475         iRet = writeSparseComplexMatrix(_iH5File, _pstName, iRows, iCols, iNbItem, piNbItemRow, piColPos, pdblReal, pdblImg);
476     }
477     else
478     {
479         sciErr = getSparseMatrix(pvApiCtx, _piVar, &iRows, &iCols, &iNbItem, &piNbItemRow, &piColPos, &pdblReal);
480         if(sciErr.iErr)
481         {
482             printError(&sciErr, 0);
483             return false;
484         }
485
486         iRet = writeSparseMatrix(_iH5File, _pstName, iRows, iCols, iNbItem, piNbItemRow, piColPos, pdblReal);
487     }
488
489     if(iRet)
490     {
491         return false;
492     }
493
494     char pstMsg[512];
495     sprintf(pstMsg, "sparse (%d x %d)", iRows, iCols);
496     print_type(pstMsg);
497     return true;
498 }
499 /*
500 static bool export_matlab_sparse(void* pvApiCtx, int *_piVar, char* _pstName)
501 {
502     print_type(_pstName);
503     return false;
504 }
505 */
506 static bool export_ints(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
507 {
508     int iRet            = 0;
509     char* pstName       = wide_string_to_UTF8(_pwstName);
510
511     switch(pIT->getType())
512     {
513         case types::InternalType::RealInt8 :
514         {
515             types::Int8* pInt    = pIT->getAs<types::Int8>();
516             iRet = writeInteger8Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
517             break;
518         }
519         case types::InternalType::RealUInt8 :
520         {
521             types::UInt8* pInt    = pIT->getAs<types::UInt8>();
522             iRet = writeUnsignedInteger8Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
523             break;
524         }
525         case types::InternalType::RealInt16 :
526         {
527             types::Int16* pInt    = pIT->getAs<types::Int16>();
528             iRet = writeInteger16Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
529             break;
530         }
531         case types::InternalType::RealUInt16 :
532         {
533             types::UInt16* pInt    = pIT->getAs<types::UInt16>();
534             iRet = writeUnsignedInteger16Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
535             break;
536         }
537         case types::InternalType::RealInt32 :
538         {
539             types::Int32* pInt    = pIT->getAs<types::Int32>();
540             iRet = writeInteger32Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
541             break;
542         }
543         case types::InternalType::RealUInt32 :
544         {
545             types::UInt32* pInt    = pIT->getAs<types::UInt32>();
546             iRet = writeUnsignedInteger32Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
547             break;
548         }
549         case types::InternalType::RealInt64 :
550         {
551             types::Int64* pInt    = pIT->getAs<types::Int64>();
552             iRet = writeInteger64Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
553             break;
554         }
555         case types::InternalType::RealUInt64 :
556         {
557             types::UInt64* pInt    = pIT->getAs<types::UInt64>();
558             iRet = writeUnsignedInteger64Matrix(_iH5File, pstName, pInt->getRows(), pInt->getCols(), pInt->get());
559             break;
560         }
561         default :
562             iRet = true;
563     }
564
565     if(iRet)
566     {
567         return false;
568     }
569 /*
570     char pstMsg[512];
571     sprintf(pstMsg, "int%d (%d x %d)", 8*iPrec, iRows, iCols);
572     print_type(pstMsg);
573 */
574     return true;
575 }
576 /*
577 static bool export_handles(void* pvApiCtx, int *_piVar, char* _pstName)
578 {
579     print_type(_pstName);
580     return false;
581 }
582 */
583 static bool export_strings(int _iH5File, types::InternalType* pIT,wchar_t* _pwstName)
584 {
585
586     int iRet            = 0;
587     types::String* pStr = pIT->getAs<types::String>();
588     char* pstName       = wide_string_to_UTF8(_pwstName);
589     char** pstData      = NULL;
590
591     pstData = (char**)malloc(pStr->getRows()*pStr->getCols()*sizeof(char*));
592
593     for(int i=0; i < pStr->getRows()*pStr->getCols(); i++)
594         pstData[i] = wide_string_to_UTF8(pStr->get(i));
595
596     iRet = writeStringMatrix(_iH5File, pstName, pStr->getRows(), pStr->getCols(),pstData);
597
598     FREE(pstName);
599     FREE(pstData);
600
601     if(iRet)
602     {
603         return false;
604     }
605
606     char pstMsg[512];
607     sprintf(pstMsg, "string (%d x %d)", pStr->getRows(), pStr->getCols());
608     print_type(pstMsg);
609
610     return true;
611 }
612 /*
613 static bool export_u_function(void* pvApiCtx, int *_piVar, char* _pstName)
614 {
615     print_type(_pstName);
616     return false;
617 }
618 /*
619 static bool export_c_function(void* pvApiCtx, int *_piVar, char* _pstName)
620 {
621     print_type(_pstName);
622     return false;
623 }
624 /*
625 static bool export_lib(void* pvApiCtx, int *_piVar, char* _pstName)
626 {
627     print_type(_pstName);
628     return false;
629 }
630 /*
631 static bool export_lufact_pointer(void* pvApiCtx, int *_piVar, char* _pstName)
632 {
633     print_type(_pstName);
634     return false;
635 }
636 */
637 void print_type(char* _pstType)
638 {
639 #ifdef PRINT_DEBUG
640     for(int i = 0 ; i < iLevel ; i++)
641     {
642         sciprint("\t");
643     }
644     sciprint("%s\n", _pstType);
645 #endif
646 }
647
648
649 int extractVarNameList(types::typed_list &in, wchar_t** _pstNameList)
650 {
651     int iCount = 0;
652
653     for(int i = 0 ; i < in.size() ; i++)
654     {
655         if(in[i]->isString() == false || in[i]->getAs<types::String>()->isScalar() == false)
656         {
657             ScierrorW(999,_W("%ls: Wrong type for input argument #%d: A string expected.\n"), L"export_to_hdf5", i + 1);
658             return 0;
659         }
660
661         _pstNameList[i] = in[i]->getAs<types::String>()->get(0);
662         iCount++;
663     }
664     return iCount;
665 }
666 /*--------------------------------------------------------------------------*/