2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
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.
19 #include "context.hxx"
20 #include "gatewaystruct.hxx"
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"
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);
38 //internal sparse functions
39 SciErr getSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
41 return getCommonSparseMatrix(_pvCtx, _piAddress, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
44 SciErr getComplexSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
46 return getCommonSparseMatrix(_pvCtx, _piAddress, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
49 SciErr getCommonSparseMatrix(void* _pvCtx, int* _piAddress, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
51 SciErr sciErr = sciErrInit();
55 if (_piAddress == NULL)
57 addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix");
61 sciErr = getVarType(_pvCtx, _piAddress, &iType);
64 addErrorMessage(&sciErr, API_ERROR_GET_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
68 if (iType != sci_sparse)
70 addErrorMessage(&sciErr, API_ERROR_INVALID_TYPE, _("%s: Invalid argument type, %s expected"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", _("sparse matrix"));
74 if (isVarComplex(_pvCtx, _piAddress) != _iComplex)
76 addErrorMessage(&sciErr, API_ERROR_INVALID_COMPLEXITY, _("%s: Bad call to get a non complex matrix"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix");
81 sciErr = getVarDimension(_pvCtx, _piAddress, _piRows, _piCols);
84 addErrorMessage(&sciErr, API_ERROR_GET_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getComplexSparseMatrix" : "getSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
88 types::Sparse* pS = ((types::InternalType*)_piAddress)->getAs<types::Sparse>();
90 *_piNbItem = (int)pS->nonZeros();
92 if (_piNbItemRow == NULL)
97 //WARNING: leak memory, caller must free pointer
98 int* piNbItemRows = (int*)MALLOC(sizeof(int) **_piRows);
99 *_piNbItemRow = pS->getNbItemByRow(piNbItemRows);
101 if (_piColPos == NULL)
106 //WARNING: leak memory, caller must free pointer
107 int* piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
108 *_piColPos = pS->getColPos(piColPos);
110 if (_pdblReal == NULL)
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);
122 if (_iComplex == 1 && _pdblImg != NULL)
134 SciErr allocSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
136 return allocCommonSparseMatrix(_pvCtx, _iVar, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
139 SciErr allocComplexSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
141 return allocCommonSparseMatrix(_pvCtx, _iVar, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
144 SciErr allocCommonSparseMatrix(void* _pvCtx, int _iVar, int _iComplex, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
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.
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)
156 SciErr sciErr = sciErrInit();
158 if (_piAddress == NULL)
160 addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), "fillCommonSparseMatrix");
164 //convert to ij, val, dims format to call sparse constructor
167 types::Double* dims = new types::Double(1, 2, false);
168 dims->get()[0] = (double)_iRows;
169 dims->get()[1] = (double)_iCols;
172 types::Double* ij = new types::Double(_iNbItem, 2);
173 double* pI = ij->get();
174 double* pJ = ij->get() + _iNbItem;
177 for (int i = 0; i < _iRows; i++)
179 for (int j = 0; j < _piNbItemRow[i]; j++)
182 pJ[idx] = *_piColPos++;
187 types::Double* val = new types::Double(_iNbItem, 1, _iComplex == 1);
188 double* pR = val->get();
191 double* pI = val->getImg();
192 for (int i = 0; i < _iNbItem; ++i)
194 pR[i] = _pdblReal[i];
200 for (int i = 0; i < _iNbItem; ++i)
202 pR[i] = _pdblReal[i];
206 types::Sparse* pSparse = new types::Sparse(*val, *ij, *dims);
211 *_piAddress = (int*)pSparse;
212 *_piTotalSize = (int)pSparse->nonZeros();
217 SciErr createSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal)
219 return createCommonSparseMatrix(_pvCtx, _iVar, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
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)
224 return createCommonSparseMatrix(_pvCtx, _iVar, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
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)
229 SciErr sciErr = sciErrInit();
231 if (_iRows == 0 && _iCols == 0)
234 sciErr = createMatrixOfDouble(_pvCtx, _iVar, 0, 0, &dblReal);
237 addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createEmptyMatrix");
242 types::GatewayStruct* pStr = (types::GatewayStruct*)_pvCtx;
243 types::InternalType** out = pStr->m_pOut;
246 types::Sparse* pSparse = NULL;
247 sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
250 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create variable in Scilab memory"), _iComplex ? "createComplexSparseMatrix" : "createSparseMatrix");
254 int rhs = _iVar - *getNbInputArgument(_pvCtx);
255 out[rhs - 1] = pSparse;
260 SciErr createNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal)
262 return createCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
265 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)
267 return createCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
270 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)
272 SciErr sciErr = sciErrInit();
274 // check variable name
275 if (checkNamedVarFormat(_pvCtx, _pstName) == 0)
277 addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Invalid variable name: %s."), "createCommonNamedMatrixOfPoly", _pstName);
281 //return named empty matrix
282 if (_iRows == 0 && _iCols == 0)
285 sciErr = createNamedMatrixOfDouble(_pvCtx, _pstName, 0, 0, &dblReal);
288 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createNamedEmptyMatrix");
293 if (!checkNamedVarFormat(_pvCtx, _pstName))
295 addErrorMessage(&sciErr, API_ERROR_INVALID_NAME, _("%s: Invalid variable name: %s."), "createCommonNamedSparseMatrix", _pstName);
300 types::Sparse* pSparse = NULL;
301 sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
304 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create %s named \"%s\""), _iComplex ? "createNamedComplexSparseMatrix" : "createNamedSparseMatrix", _("sparse matrix"), _pstName);
309 wchar_t* pwstName = to_wide_string(_pstName);
310 symbol::Context* ctx = symbol::Context::getInstance();
311 symbol::Symbol sym = symbol::Symbol(pwstName);
313 if (ctx->isprotected(sym) == false)
315 ctx->put(sym, pSparse);
320 addErrorMessage(&sciErr, API_ERROR_REDEFINE_PERMANENT_VAR, _("Redefining permanent variable.\n"));
325 SciErr readNamedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal)
327 return readCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
330 SciErr readNamedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
332 return readCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
335 SciErr readCommonNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
338 int* piNbItemRow = 0;
342 double* pdblReal = NULL;
343 double* pdblImg = NULL;
345 SciErr sciErr = getVarAddressFromName(_pvCtx, _pstName, &piAddr);
348 addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
354 sciErr = getComplexSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
358 sciErr = getSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal);
363 addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
367 if (_piNbItemRow == NULL)
372 memcpy(_piNbItemRow, piNbItemRow, *_piRows * sizeof(int));
374 if (_piColPos == NULL)
379 memcpy(_piColPos, piColPos, *_piNbItem * sizeof(int));
382 if (_pdblReal == NULL)
387 C2F(dcopy)(_piNbItem, pdblReal, &iOne, _pdblReal, &iOne);
389 if (_iComplex && _pdblImg)
391 C2F(dcopy)(_piNbItem, pdblImg, &iOne, _pdblImg, &iOne);
397 /* shortcut functions */
399 /*--------------------------------------------------------------------------*/
400 int isSparseType(void* _pvCtx, int* _piAddress)
402 return checkVarType(_pvCtx, _piAddress, sci_sparse);
404 /*--------------------------------------------------------------------------*/
405 int isNamedSparseType(void* _pvCtx, const char* _pstName)
407 return checkNamedVarType(_pvCtx, _pstName, sci_sparse);
409 /*--------------------------------------------------------------------------*/
410 int getAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
412 return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
414 /*--------------------------------------------------------------------------*/
415 int getAllocatedComplexSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
417 return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
419 /*--------------------------------------------------------------------------*/
420 static int getCommonAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
422 int* piNbItemRow = NULL;
423 int* piColPos = NULL;
425 double* pdblReal = NULL;
426 double* pdblImg = NULL;
428 SciErr sciErr = getCommonSparseMatrix(_pvCtx, _piAddress, _iComplex, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
431 addErrorMessage(&sciErr, API_ERROR_GET_ALLOC_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getAllocatedComplexSparseMatrix" : "getAllocatedSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
432 printError(&sciErr, 0);
436 *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
437 memcpy(*_piNbItemRow, piNbItemRow, sizeof(int) **_piRows);
439 *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
440 memcpy(*_piColPos, piColPos, sizeof(int) **_piNbItem);
442 *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
443 C2F(dcopy)(_piNbItem, pdblReal, &iOne, *_pdblReal, &iOne);
451 *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
452 C2F(dcopy)(_piNbItem, pdblImg, &iOne, *_pdblImg, &iOne);
459 /*--------------------------------------------------------------------------*/
460 int getNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
462 return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
464 /*--------------------------------------------------------------------------*/
465 int getNamedAllocatedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
467 return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
469 /*--------------------------------------------------------------------------*/
470 static int getCommonNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
472 SciErr sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, NULL, NULL, NULL, NULL);
475 addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
476 printError(&sciErr, 0);
480 *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
481 *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
483 *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
486 *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
489 sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, *_piNbItemRow, *_piColPos, *_pdblReal, *_pdblImg);
492 addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
493 printError(&sciErr, 0);
499 /*--------------------------------------------------------------------------*/
500 void freeAllocatedSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal)
506 /*--------------------------------------------------------------------------*/
507 void freeAllocatedComplexSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal, double* _pdblImg)
509 freeAllocatedSparseMatrix(_piNbItemRows, _piColPos, _pdblReal);
512 /*--------------------------------------------------------------------------*/