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 types::GatewayStruct* pStr = (types::GatewayStruct*)_pvCtx;
232 types::InternalType** out = pStr->m_pOut;
233 types::Sparse* pSparse = NULL;
235 if (_iRows == 0 && _iCols == 0)
237 pSparse = new types::Sparse(0,0,false);
242 sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
245 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create variable in Scilab memory"), _iComplex ? "createComplexSparseMatrix" : "createSparseMatrix");
250 int rhs = _iVar - *getNbInputArgument(_pvCtx);
251 out[rhs - 1] = pSparse;
256 SciErr createNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos, const double* _pdblReal)
258 return createCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
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)
263 return createCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
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)
268 SciErr sciErr = sciErrInit();
270 // check variable name
271 if (checkNamedVarFormat(_pvCtx, _pstName) == 0)
273 addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Invalid variable name: %s."), "createCommonNamedMatrixOfPoly", _pstName);
277 //return named empty matrix
278 if (_iRows == 0 && _iCols == 0)
281 sciErr = createNamedMatrixOfDouble(_pvCtx, _pstName, 0, 0, &dblReal);
284 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createNamedEmptyMatrix");
289 if (!checkNamedVarFormat(_pvCtx, _pstName))
291 addErrorMessage(&sciErr, API_ERROR_INVALID_NAME, _("%s: Invalid variable name: %s."), "createCommonNamedSparseMatrix", _pstName);
296 types::Sparse* pSparse = NULL;
297 sciErr = fillCommonSparseMatrix(_pvCtx, (int**)&pSparse, _iComplex, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg, &iTotalSize);
300 addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_SPARSE, _("%s: Unable to create %s named \"%s\""), _iComplex ? "createNamedComplexSparseMatrix" : "createNamedSparseMatrix", _("sparse matrix"), _pstName);
305 wchar_t* pwstName = to_wide_string(_pstName);
306 symbol::Context* ctx = symbol::Context::getInstance();
307 symbol::Symbol sym = symbol::Symbol(pwstName);
309 if (ctx->isprotected(sym) == false)
311 ctx->put(sym, pSparse);
316 addErrorMessage(&sciErr, API_ERROR_REDEFINE_PERMANENT_VAR, _("Redefining permanent variable.\n"));
321 SciErr readNamedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal)
323 return readCommonNamedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
326 SciErr readNamedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
328 return readCommonNamedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
331 SciErr readCommonNamedSparseMatrix(void* _pvCtx, const char* _pstName, int _iComplex, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos, double* _pdblReal, double* _pdblImg)
334 int* piNbItemRow = 0;
338 double* pdblReal = NULL;
339 double* pdblImg = NULL;
341 SciErr sciErr = getVarAddressFromName(_pvCtx, _pstName, &piAddr);
344 addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
350 sciErr = getComplexSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
354 sciErr = getSparseMatrix(_pvCtx, piAddr, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal);
359 addErrorMessage(&sciErr, API_ERROR_READ_NAMED_SPARSE, _("%s: Unable to get variable \"%s\""), _iComplex ? "readNamedComplexSparseMatrix" : "readNamedSparseMatrix", _pstName);
363 if (_piNbItemRow == NULL)
368 memcpy(_piNbItemRow, piNbItemRow, *_piRows * sizeof(int));
370 if (_piColPos == NULL)
375 memcpy(_piColPos, piColPos, *_piNbItem * sizeof(int));
378 if (_pdblReal == NULL)
383 C2F(dcopy)(_piNbItem, pdblReal, &iOne, _pdblReal, &iOne);
385 if (_iComplex && _pdblImg)
387 C2F(dcopy)(_piNbItem, pdblImg, &iOne, _pdblImg, &iOne);
393 /* shortcut functions */
395 /*--------------------------------------------------------------------------*/
396 int isSparseType(void* _pvCtx, int* _piAddress)
398 return checkVarType(_pvCtx, _piAddress, sci_sparse);
400 /*--------------------------------------------------------------------------*/
401 int isNamedSparseType(void* _pvCtx, const char* _pstName)
403 return checkNamedVarType(_pvCtx, _pstName, sci_sparse);
405 /*--------------------------------------------------------------------------*/
406 int getAllocatedSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
408 return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
410 /*--------------------------------------------------------------------------*/
411 int getAllocatedComplexSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
413 return getCommonAllocatedSparseMatrix(_pvCtx, _piAddress, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
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)
418 int* piNbItemRow = NULL;
419 int* piColPos = NULL;
421 double* pdblReal = NULL;
422 double* pdblImg = NULL;
424 SciErr sciErr = getCommonSparseMatrix(_pvCtx, _piAddress, _iComplex, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos, &pdblReal, &pdblImg);
427 addErrorMessage(&sciErr, API_ERROR_GET_ALLOC_SPARSE, _("%s: Unable to get argument #%d"), _iComplex ? "getAllocatedComplexSparseMatrix" : "getAllocatedSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
428 printError(&sciErr, 0);
432 *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
433 memcpy(*_piNbItemRow, piNbItemRow, sizeof(int) **_piRows);
435 *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
436 memcpy(*_piColPos, piColPos, sizeof(int) **_piNbItem);
438 *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
439 C2F(dcopy)(_piNbItem, pdblReal, &iOne, *_pdblReal, &iOne);
447 *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
448 C2F(dcopy)(_piNbItem, pdblImg, &iOne, *_pdblImg, &iOne);
455 /*--------------------------------------------------------------------------*/
456 int getNamedAllocatedSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal)
458 return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 0, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, NULL);
460 /*--------------------------------------------------------------------------*/
461 int getNamedAllocatedComplexSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos, double** _pdblReal, double** _pdblImg)
463 return getCommonNamedAllocatedSparseMatrix(_pvCtx, _pstName, 1, _piRows, _piCols, _piNbItem, _piNbItemRow, _piColPos, _pdblReal, _pdblImg);
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)
468 SciErr sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, NULL, NULL, NULL, NULL);
471 addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
472 printError(&sciErr, 0);
476 *_piNbItemRow = (int*)MALLOC(sizeof(int) **_piRows);
477 *_piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
479 *_pdblReal = (double*)MALLOC(sizeof(double) **_piNbItem);
482 *_pdblImg = (double*)MALLOC(sizeof(double) **_piNbItem);
485 sciErr = readCommonNamedSparseMatrix(_pvCtx, _pstName, _iComplex, _piRows, _piCols, _piNbItem, *_piNbItemRow, *_piColPos, *_pdblReal, *_pdblImg);
488 addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_SPARSE, _("%s: Unable to get argument \"%s\""), _iComplex ? "getNamedAllocatedComplexSparseMatrix" : "getNamedAllocatedSparseMatrix", _pstName);
489 printError(&sciErr, 0);
495 /*--------------------------------------------------------------------------*/
496 void freeAllocatedSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal)
502 /*--------------------------------------------------------------------------*/
503 void freeAllocatedComplexSparseMatrix(int* _piNbItemRows, int* _piColPos, double* _pdblReal, double* _pdblImg)
505 freeAllocatedSparseMatrix(_piNbItemRows, _piColPos, _pdblReal);
508 /*--------------------------------------------------------------------------*/