* Bug 16601 fixed: libmatio >= 1.5.18 was not supported
[scilab.git] / scilab / modules / matio / src / cpp / GetSparseVariable.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2008 - INRIA - Vincent COUVERT
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include "GetMatlabVariable.hxx"
17
18 extern "C"
19 {
20 #include "api_scilab.h"
21 #include "scisparse.h"
22 }
23
24 matvar_t *GetSparseVariable(void *pvApiCtx, int iVar, const char *name, int * parent, int item_position)
25 {
26
27     types::GatewayStruct* pGS = (types::GatewayStruct*)pvApiCtx;
28     types::typed_list in = *pGS->m_pIn;
29
30     if (in[iVar - 1]->isSparse() == false)
31     {
32         Scierror(999, _("%s: Wrong type for first input argument: Sparse matrix expected.\n"), "GetSparseVariable");
33         return NULL;
34     }
35
36     types::Sparse* pSparse = in[iVar - 1]->getAs<types::Sparse>();
37
38     return GetSparseMatVar(pSparse, name);
39 }
40
41 matvar_t* GetSparseMatVar(types::Sparse* pSparse, const char *name)
42 {
43     int Dims = pSparse->getDims();
44     int* pDims = pSparse->getDimsArray();
45     int isize = pSparse->getSize();
46     size_t* psize_t = NULL;
47     matvar_t * pMatVarOut = NULL;
48
49     if (pSparse->getDims() > 2)
50     {
51         Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
52         return NULL;
53     }
54
55     mat_sparse_t *sparseData = NULL;
56     sparseData = (mat_sparse_t*)MALLOC(sizeof(mat_sparse_t));
57     if (sparseData == NULL)
58     {
59         Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
60         return NULL;
61     }
62
63     int nonZeros = pSparse->nonZeros();
64     int* colPos = new int[nonZeros];
65     int* itemsRow = new int[pSparse->getRows()];
66     pSparse->getNbItemByRow(itemsRow);
67
68 #if MATIO_RELEASE_LEVEL < 18
69     mat_int32_t* colIndexes = (mat_int32_t*)MALLOC(sizeof(mat_int32_t) *  (pSparse->getRows() + 1));
70 #else
71     mat_uint32_t* colIndexes = (mat_uint32_t*)MALLOC(sizeof(mat_uint32_t) *  (pSparse->getRows() + 1));
72 #endif
73     if (colIndexes == NULL)
74     {
75         FREE(sparseData);
76         Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
77         delete[] colPos;
78         delete[] itemsRow;
79         return NULL;
80     }
81
82     colIndexes[0] = 0;
83
84     for (int K = 0; K < pSparse->getRows(); ++K)
85     {
86         colIndexes[K + 1] = colIndexes[K] + itemsRow[K];
87     }
88
89 #if MATIO_RELEASE_LEVEL < 18
90     mat_int32_t* rowIndexes = (mat_int32_t*)MALLOC(sizeof(mat_int32_t) *  nonZeros);
91 #else
92     mat_uint32_t* rowIndexes = (mat_uint32_t*)MALLOC(sizeof(mat_uint32_t) *  nonZeros);
93 #endif
94     if (rowIndexes == NULL)
95     {
96         FREE(sparseData);
97         FREE(colIndexes);
98         delete[] colPos;
99         delete[] itemsRow;
100         Scierror(999, _("%s: No more memory.\n"), "GetSparseVariable");
101         return NULL;
102     }
103
104     pSparse->getColPos(colPos);
105     for (int K = 0; K < nonZeros; ++K)
106     {
107         rowIndexes[K] = colPos[K] - 1;
108     }
109
110
111     /* Create Matlab Sparse matrix data */
112     sparseData->nzmax = nonZeros;
113     sparseData->nir = nonZeros;
114     sparseData->ir = rowIndexes;
115     /* sparseData->njc   = scilabSparse.nel + 1; */
116     sparseData->njc = pSparse->getRows() + 1;
117     sparseData->jc = colIndexes;
118     sparseData->ndata = nonZeros;
119     /* get position data*/
120     int* iPositVal = new int[nonZeros];
121
122     int idx = 0;
123     for (int i = 0; i < pSparse->getRows(); i++)
124     {
125         for (int j = 0; j < itemsRow[i]; j++)
126         {
127             iPositVal[idx] = (colPos[idx] - 1) * pSparse->getRows() + i;
128             ++idx;
129         }
130     }
131
132     psize_t = (size_t*)MALLOC(Dims * sizeof(size_t));
133     if (psize_t == NULL)
134     {
135         FREE(sparseData);
136         FREE(rowIndexes);
137         FREE(colIndexes);
138         delete[] itemsRow;
139         delete[] colPos;
140         delete[] iPositVal;
141         Scierror(999, _("%s: No more memory.\n"), "GetSparseVariable");
142         return NULL;
143     }
144     psize_t[0] = (int)pDims[1];
145     psize_t[1] = (int)pDims[0];
146
147     if (pSparse->isComplex())
148     {
149         struct mat_complex_split_t* data;
150         double* dataReal = NULL;
151         double* dataImg = NULL;
152         if ((dataReal = (double*)MALLOC(sizeof(double) * nonZeros)) == NULL)
153         {
154             FREE(psize_t);
155             FREE(sparseData);
156             FREE(colIndexes);
157             FREE(rowIndexes);
158             delete[] itemsRow;
159             delete[] colPos;
160             delete[] iPositVal;
161             Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
162             return NULL;
163         }
164
165         if ((dataImg = (double*)MALLOC(sizeof(double) * nonZeros)) == NULL)
166         {
167             FREE(dataReal);
168             FREE(psize_t);
169             FREE(sparseData);
170             FREE(colIndexes);
171             FREE(rowIndexes);
172             delete[] itemsRow;
173             delete[] colPos;
174             delete[] iPositVal;
175             Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
176             return NULL;
177         }
178
179         if ((data = (mat_complex_split_t*)MALLOC(sizeof(mat_complex_split_t))) == NULL)
180         {
181             FREE(dataImg);
182             FREE(dataReal);
183             FREE(psize_t);
184             FREE(sparseData);
185             FREE(colIndexes);
186             FREE(rowIndexes);
187             delete[] itemsRow;
188             delete[] colPos;
189             delete[] iPositVal;
190             Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
191             return NULL;
192         }
193
194         std::complex<double> complexData;
195         for (int K = 0; K < nonZeros; ++K)
196         {
197             complexData = pSparse->getImg(iPositVal[K]);
198             dataReal[K] = complexData.real();
199             dataImg[K] = (-1 * complexData.imag());
200
201         }
202         data->Re = dataReal;
203         data->Im = dataImg;
204
205         sparseData->data = (void*)data;
206
207         pMatVarOut = Mat_VarCreate(name, MAT_C_SPARSE, MAT_T_DOUBLE, Dims, psize_t, sparseData, MAT_F_COMPLEX | MAT_F_DONT_COPY_DATA);
208     }
209     else
210     {
211         double* data = NULL;
212
213         if ((data = (double*)MALLOC(sizeof(double) * nonZeros)) == NULL)
214         {
215             FREE(psize_t);
216             FREE(sparseData);
217             FREE(colIndexes);
218             FREE(rowIndexes);
219             delete[] itemsRow;
220             delete[] colPos;
221             delete[] iPositVal;
222             Scierror(999, _("%s: No more memory.\n"), "GetSparseMatVar");
223             return NULL;
224         }
225
226         for (int K = 0; K < nonZeros; ++K)
227         {
228             data[K] = pSparse->getReal(iPositVal[K]);
229         }
230
231
232         sparseData->data = (void*)data;
233
234         pMatVarOut = Mat_VarCreate(name, MAT_C_SPARSE, MAT_T_DOUBLE, Dims, psize_t, sparseData, 0 | MAT_F_DONT_COPY_DATA);
235     }
236
237     FREE(psize_t);
238     delete[] iPositVal;
239     delete[] colPos;
240     delete[] itemsRow;
241     return pMatVarOut;
242 }