[sparse] now sparse([]) is sparse
[scilab.git] / scilab / modules / api_scilab / src / cpp / api_stack_sparse.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
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 * Please note that piece of code will be rewrited for the Scilab 6 family
15 * However, the API (profile of the functions in the header files) will be
16 * still available and supported in Scilab 6.
17 */
18 #include "sparse.hxx"
19 #include "context.hxx"
20 #include "gatewaystruct.hxx"
21
22 extern "C"
23 {
24 #include <string.h>
25 #include "elem_common.h"
26 #include "api_scilab.h"
27 #include "api_internal_common.h"
28 #include "api_internal_sparse.h"
29 #include "localization.h"
30 #include "sci_malloc.h"
31 #include "call_scilab.h"
32 }
33
34 static int getCommonAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg);
35 static int getCommonNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg);
36
37
38 //internal sparse functions
39 SciErr getSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
40 {
41     return getCommonSparseMatrix(_pvCtx, _piAddress, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
42 }
43
44 SciErr getComplexSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
45 {
46     return getCommonSparseMatrix(_pvCtx, _piAddress, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
47 }
48
49 SciErr getCommonSparseMatrix(void* _pvCtx, int* _piAddress, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
50 {
51     SciErr sciErr = sciErrInit();
52     int iPos = 0;
53     int iType = 0;
54
55     if (_piAddress == NULL)
56     {
57         addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix");
58         return sciErr;
59     }
60
61     sciErr = getVarType(_pvCtx, _piAddress, &iType);
62     if (sciErr.iErr)
63     {
64         addErrorMessage(&sciErr, API_ERROR_GET_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
65         return sciErr;
66     }
67
68     if (iType != sci_sparse)
69     {
70         addErrorMessage(&sciErr, API_ERROR_INVALID_TYPE, _("%s: Invalid argument type, %s expected"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", _("sparse matrix"));
71         return sciErr;
72     }
73
74     if (isVarComplex(_pvCtx, _piAddress) != _iComplex)
75     {
76         addErrorMessage(&sciErr, API_ERROR_INVALID_COMPLEXITY, _("%s: Bad call to get a non complex matrix"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix");
77         return sciErr;
78     }
79
80
81     sciErr = getVarDimension(_pvCtx, _piAddress, _piRows, _piCols);
82     if (sciErr.iErr)
83     {
84         addErrorMessage(&sciErr, API_ERROR_GET_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
85         return sciErr;
86     }
87
88     types::Sparse* pS = ((types::InternalType*)_piAddress)->getAs<types::Sparse>();
89
90     *_piNbItem = (int)pS->nonZeros();
91
92     if (_piNbItemRow == NULL)
93     {
94         return sciErr;
95     }
96
97     //WARNING: leak memory, caller must free pointer
98     int* piNbItemRows = (int*)MALLOC(sizeof(int) **_piRows);
99     *_piNbItemRow = pS->getNbItemByRow(piNbItemRows);
100
101     if (_piColPos == NULL)
102     {
103         return sciErr;
104     }
105
106     //WARNING: leak memory, caller must free pointer
107     int* piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
108     *_piColPos = pS->getColPos(piColPos);
109
110     if (_pdblReal == NULL)
111     {
112         return sciErr;
113     }
114
115     //WARNING: leak memory, caller must free pointers
116     double* pR = (double*)MALLOC(sizeof(double) **_piNbItem);
117     double* pI = (double*)MALLOC(sizeof(double) **_piNbItem);
118     pS->outputValues(pR, pI);
119
120     *_pdblReal = pR;
121
122     if (_iComplex == 1 && _pdblImg != NULL)
123     {
124         *_pdblImg = pI;
125     }
126     else
127     {
128         FREE(pI);
129     }
130
131     return sciErr;
132 }
133
134 SciErr allocSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
135 {
136     return allocCommonSparseMatrix(_pvCtx, _iVar, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
137 }
138
139 SciErr allocComplexSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
140 {
141     return allocCommonSparseMatrix(_pvCtx, _iVar, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
142 }
143
144 SciErr allocCommonSparseMatrix(void* _pvCtx, int _iVar, int _iComplex, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
145 {
146     SciErr sciErr = sciErrInit();
147     // We cant rewrite this function in Scilab 6
148     // because sparses are not stored like scilab 5.
149     // We cant return pointer to _piNbItemRow and
150     // _piColPos and let user fill it.
151     return sciErr;
152 }
153
154 SciErr fillCommonSparseMatrix(void* _pvCtx, int **_piAddress, int _iComplex, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal, const double* _pdblImg, int* _piTotalSize)
155 {
156     SciErr sciErr = sciErrInit();
157
158     if (_piAddress == NULL)
159     {
160         addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), "fillCommonSparseMatrix");
161         return sciErr;
162     }
163
164     //convert to ij, val, dims format to call sparse constructor
165
166     //dims
167     types::Double* dims = new types::Double(1, 2, false);
168     dims->get()[0] = (double)_iRows;
169     dims->get()[1] = (double)_iCols;
170
171     //ij
172     types::Double* ij = new types::Double(_iNbItem, 2);
173     double* pI = ij->get();
174     double* pJ = ij->get() + _iNbItem;
175
176     int idx = 0;
177     for (int i = 0; i < _iRows; i++)
178     {
179         for (int j = 0; j < _piNbItemRow[i]; j++)
180         {
181             pI[idx] = i + 1;
182             pJ[idx] = *_piColPos++;
183             ++idx;
184         }
185     }
186
187     types::Double* val = new types::Double(_iNbItem, 1, _iComplex == 1);
188     double* pR = val->get();
189     if (_iComplex)
190     {
191         double* pI = val->getImg();
192         for (int i = 0; i < _iNbItem; ++i)
193         {
194             pR[i] = _pdblReal[i];
195             pI[i] = _pdblImg[i];
196         }
197     }
198     else
199     {
200         for (int i = 0; i < _iNbItem; ++i)
201         {
202             pR[i] = _pdblReal[i];
203         }
204     }
205
206     types::Sparse* pSparse = new types::Sparse(*val, *ij, *dims);
207     delete dims;
208     delete val;
209     delete ij;
210
211     *_piAddress = (int*)pSparse;
212     *_piTotalSize = (int)pSparse->nonZeros();
213
214     return sciErr;
215 }
216
217 SciErr createSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal)
218 {
219     return createCommonSparseMatrix(_pvCtx, _iVar, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
220 }
221
222 SciErr createComplexSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal, const double* _pdblImg)
223 {
224     return createCommonSparseMatrix(_pvCtx, _iVar, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
225 }
226
227 SciErr createCommonSparseMatrix(void* _pvCtx, int _iVar, int _iComplex, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal, const double* _pdblImg)
228 {
229     SciErr sciErr = sciErrInit();
230
231     types::GatewayStruct* pStr = (types::GatewayStruct*)_pvCtx;
232     types::InternalType** out = pStr->m_pOut;
233     types::Sparse* pSparse = NULL;
234
235     if (_iRows == 0 && _iCols == 0)
236     {
237         pSparse = new types::Sparse(0,0,false);
238     }
239     else
240     {
241         int iTotalSize = 0;
242         sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
243         if (pSparse == NULL)
244         {
245             addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create variable in Scilab memory"), _iComplex ? "createComplexSparseMatrix" : "createSparseMatrix");
246             return sciErr;
247         }
248     }
249     
250     int rhs = _iVar - *getNbInputArgument(_pvCtx);
251     out[rhs - 1] = pSparse;
252
253     return sciErr;
254 }
255
256 SciErr createNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal)
257 {
258     return createCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
259 }
260
261 SciErr createNamedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal, const double* _pdblImg)
262 {
263     return createCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
264 }
265
266 SciErr createCommonNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal, const double* _pdblImg)
267 {
268     SciErr sciErr = sciErrInit();
269
270     // check variable name
271     if (checkNamedVarFormat(_pvCtx, _pstName) == 0)
272     {
273         addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Invalid variable name: %s."), "createCommonNamedMatrixOfPoly", _pstName);
274         return sciErr;
275     }
276
277     //return named empty matrix
278     if (_iRows == 0 && _iCols == 0)
279     {
280         double dblReal = 0;
281         sciErr = createNamedMatrixOfDouble(_pvCtx, _pstName, 0, 0, &dblReal);
282         if (sciErr.iErr)
283         {
284             addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createNamedEmptyMatrix");
285         }
286         return sciErr;
287     }
288
289     if (!checkNamedVarFormat(_pvCtx, _pstName))
290     {
291         addErrorMessage(&sciErr, API_ERROR_INVALID_NAME, _("%s: Invalid variable name: %s."), "createCommonNamedSparseMatrix", _pstName);
292         return sciErr;
293     }
294
295     int iTotalSize = 0;
296     types::Sparse* pSparse = NULL;
297     sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
298     if (pSparse == NULL)
299     {
300         addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create %s named \"%s\""), _iComplex ? "createNamedComplexSparseMatrix" : "createNamedSparseMatrix", _("sparse matrix"), _pstName);
301         return sciErr;
302     }
303
304
305     wchar_t* pwstName = to_wide_string(_pstName);
306     symbol::Context* ctx = symbol::Context::getInstance();
307     symbol::Symbol sym = symbol::Symbol(pwstName);
308     FREE(pwstName);
309     if (ctx->isprotected(sym) == false)
310     {
311         ctx->put(sym, pSparse);
312     }
313     else
314     {
315         delete pSparse;
316         addErrorMessage(&sciErr, API_ERROR_REDEFINE_PERMANENT_VAR, _("Redefining permanent variable.\n"));
317     }
318     return sciErr;
319 }
320
321 SciErr readNamedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal)
322 {
323     return readCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
324 }
325
326 SciErr readNamedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
327 {
328     return readCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
329 }
330
331 SciErr readCommonNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
332 {
333     int* piAddr = NULL;
334     int* piNbItemRow = 0;
335     int* piColPos = 0;
336     int iOne = 1;
337
338     double* pdblReal = NULL;
339     double* pdblImg = NULL;
340
341     SciErr sciErr = getVarAddressFromName(_pvCtx, _pstName, &piAddr);
342     if (sciErr.iErr)
343     {
344         addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
345         return sciErr;
346     }
347
348     if (_iComplex == 1)
349     {
350         sciErr = getComplexSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
351     }
352     else
353     {
354         sciErr = getSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal);
355     }
356
357     if (sciErr.iErr)
358     {
359         addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
360         return sciErr;
361     }
362
363     if (_piNbItemRow == NULL)
364     {
365         return sciErr;
366     }
367
368     memcpy(_piNbItemRow, piNbItemRow, *_piRows * sizeof(int));
369
370     if (_piColPos == NULL)
371     {
372         return sciErr;
373     }
374
375     memcpy(_piColPos, piColPos, *_piNbItem * sizeof(int));
376
377
378     if (_pdblReal == NULL)
379     {
380         return sciErr;
381     }
382
383     C2F(dcopy)(_piNbItem, pdblReal, &iOne, _pdblReal, &iOne);
384
385     if (_iComplex && _pdblImg)
386     {
387         C2F(dcopy)(_piNbItem, pdblImg, &iOne, _pdblImg, &iOne);
388     }
389
390     return sciErr;
391 }
392
393 /* shortcut functions */
394
395 /*--------------------------------------------------------------------------*/
396 int isSparseType(void* _pvCtx, int* _piAddress)
397 {
398     return checkVarType(_pvCtx, _piAddress, sci_sparse);
399 }
400 /*--------------------------------------------------------------------------*/
401 int isNamedSparseType(void* _pvCtx, const char* _pstName)
402 {
403     return checkNamedVarType(_pvCtx, _pstName, sci_sparse);
404 }
405 /*--------------------------------------------------------------------------*/
406 int getAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
407 {
408     return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
409 }
410 /*--------------------------------------------------------------------------*/
411 int getAllocatedComplexSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
412 {
413     return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
414 }
415 /*--------------------------------------------------------------------------*/
416 static int getCommonAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
417 {
418     int* piNbItemRow = NULL;
419     int* piColPos = NULL;
420     int iOne = 1;
421     double* pdblReal = NULL;
422     double* pdblImg = NULL;
423
424     SciErr sciErr = getCommonSparseMatrix(_pvCtx, _piAddress, _iComplex, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
425     if (sciErr.iErr)
426     {
427         addErrorMessage(&sciErr, API_ERROR_GET_ALLOC_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getAllocatedComplexSparseMatrix" : "getAllocatedSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
428         printError(&sciErr, 0);
429         return sciErr.iErr;
430     }
431
432     *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
433     memcpy(*_piNbItemRow, piNbItemRow, sizeof(int) **_piRows);
434
435     *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
436     memcpy(*_piColPos, piColPos, sizeof(int) **_piNbItem);
437
438     *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
439     C2F(dcopy)(_piNbItem, pdblReal, &iOne, *_pdblReal, &iOne);
440
441     FREE(piNbItemRow);
442     FREE(piColPos);
443     FREE(pdblReal);
444
445     if (_iComplex)
446     {
447         *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
448         C2F(dcopy)(_piNbItem, pdblImg, &iOne, *_pdblImg, &iOne);
449         FREE(pdblImg);
450     }
451
452
453     return 0;
454 }
455 /*--------------------------------------------------------------------------*/
456 int getNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
457 {
458     return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
459 }
460 /*--------------------------------------------------------------------------*/
461 int getNamedAllocatedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
462 {
463     return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
464 }
465 /*--------------------------------------------------------------------------*/
466 static int getCommonNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
467 {
468     SciErr sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, NULL, NULL, NULL, NULL);
469     if (sciErr.iErr)
470     {
471         addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
472         printError(&sciErr, 0);
473         return sciErr.iErr;
474     }
475
476     *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
477     *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
478
479     *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
480     if (_iComplex)
481     {
482         *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
483     }
484
485     sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, *_piNbItemRow, *_piColPos, *_pdblReal, *_pdblImg);
486     if (sciErr.iErr)
487     {
488         addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
489         printError(&sciErr, 0);
490         return sciErr.iErr;
491     }
492
493     return 0;
494 }
495 /*--------------------------------------------------------------------------*/
496 void freeAllocatedSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal)
497 {
498     FREE(_piNbItemRows);
499     FREE(_piColPos);
500     FREE(_pdblReal);
501 }
502 /*--------------------------------------------------------------------------*/
503 void freeAllocatedComplexSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal, double* _pdblImg)
504 {
505     freeAllocatedSparseMatrix(_piNbItemRows, _piColPos, _pdblReal);
506     FREE(_pdblImg);
507 }
508 /*--------------------------------------------------------------------------*/