2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13 #include "alltypes.hxx"
14 #include "types_tools.hxx"
15 #include "overload.hxx"
16 #include "execvisitor.hxx"
19 #include "elem_common.h"
20 #include "os_string.h"
26 void getIndexes(T* val, std::vector<int>& vec)
28 typename T::type* p = val->get();
29 int size = val->getSize();
30 for (int i = 0; i < size; ++i)
32 vec.push_back(static_cast<int>(p[i]));
37 double getIndex(T* val)
39 typename T::type* p = val->get();
40 return static_cast<double>(p[0]);
43 double getIndex(InternalType* val)
45 switch (val->getType())
48 case InternalType::ScilabDouble:
50 return getIndex(val->getAs<Double>());
52 case InternalType::ScilabInt8:
54 return getIndex(val->getAs<Int8>());
56 case InternalType::ScilabInt16:
58 return getIndex(val->getAs<Int16>());
60 case InternalType::ScilabInt32:
62 return getIndex(val->getAs<Int32>());
64 case InternalType::ScilabInt64:
66 return getIndex(val->getAs<Int64>());
68 case InternalType::ScilabUInt8:
70 return getIndex(val->getAs<UInt8>());
72 case InternalType::ScilabUInt16:
74 return getIndex(val->getAs<UInt16>());
76 case InternalType::ScilabUInt32:
78 return getIndex(val->getAs<UInt32>());
80 case InternalType::ScilabUInt64:
82 return getIndex(val->getAs<UInt64>());
89 //get only scalar index
90 bool getScalarIndex(GenericType* _pRef, typed_list* _pArgsIn, int* index)
92 //input size must be equal to ref dims
93 int dimsRef = _pRef->getDims();
94 int dimsIn = static_cast<int>(_pArgsIn->size());
96 //same dims and less than internal limit
97 if (dimsIn != 1 && dimsIn != dimsRef || dimsIn > MAX_DIMS)
102 int* pdims = _pRef->getDimsArray();
104 for (int i = 0; i < dimsIn; ++i)
106 InternalType* in = (*_pArgsIn)[i];
107 //input arg type must be scalar double, int8, int16, ...
108 if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
110 ind[i] = static_cast<int>(getIndex(in)) - 1;
118 //failed, so use entire process
124 if (dimsIn > 1 && idx >= pdims[0])
129 for (int i = 1; i < dimsIn; ++i)
131 if (ind[i] >= pdims[i])
135 idx += ind[i] * pdims[i - 1];
142 static double evalute(InternalType* pIT, int sizeRef)
146 if (pIT->getId() == InternalType::IdScalarPolynom)
148 SinglePoly* pSP = pIT->getAs<Polynom>()->get()[0];
149 pSP->evaluate(sizeRef, 0, &real, &img);
153 real = getIndex(pIT);
158 //get index from implicit or colon index + scalar
159 bool getImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<int>& index)
161 int dimsRef = _pRef->getDims();
162 int dimsIn = static_cast<int>(_pArgsIn->size());
163 bool viewAsVector = dimsIn == 1;
164 //same dims and less than internal limit
165 if (dimsIn != 1 && dimsIn != dimsRef || dimsIn > MAX_DIMS)
170 int* pdims = _pRef->getDimsArray();
171 //input arg type must be computable ( double, $, :, ... )
172 std::list<std::vector<int>> lstIdx;
174 for (int i = 0; i < dimsIn; ++i)
176 InternalType* in = (*_pArgsIn)[i];
177 if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
179 int idx = static_cast<int>(getIndex(in)) - 1;
185 lstIdx.emplace_back(1, idx);
187 else if (in->isColon())
191 idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
192 lstIdx.push_back(idx);
195 else if (in->isImplicitList())
197 ImplicitList* pIL = in->getAs<ImplicitList>();
198 int sizeRef = viewAsVector ? _pRef->getSize() : pdims[i];
199 double start = evalute(pIL->getStart(), sizeRef);
200 double step = evalute(pIL->getStep(), sizeRef);
201 double end = evalute(pIL->getEnd(), sizeRef);
203 //printf("%.2f : %.2f : %.2f\n", start, step, end);
205 int size = (end - start) / step + 1;
206 vector<int> idx(size);
208 int* pi = idx.data();
209 pi[0] = start - 1; //0-indexed
210 for (int j = 1; j < size; ++j)
212 pi[j] = pi[j - 1] + step;
215 lstIdx.push_back(idx);
224 index.resize(finalSize, 0);
225 //printf("finalSize : %d\n", finalSize);
227 int previousSize = 1;
229 int previousDims = 1;
230 while (lstIdx.empty() == false)
232 std::vector<int>& v = lstIdx.front();
233 int currentSize = v.size();
234 const int* pv = v.data();
237 if (pv[0] == -1 && currentSize == 2)
240 int occ = finalSize / (currentSize * previousSize);
241 for (int n = 0; n < occ; ++n)
243 int idx = currentSize * previousSize * n;
244 for (int m = 0; m < currentSize; ++m)
246 if (dimsIn > 1 && m >= pdims[currentDim])
250 int idx2 = idx + previousSize * m;
251 int idx3 = previousDims * m;
252 for (int j = 0; j < previousSize; ++j)
254 index[idx2 + j] += idx3;
255 //printf("\tindex[%d] = %d\n", idx2 + i, previousSize * v[m]);
262 //printf("currentSize : %d\n", currentSize);
263 //printf("previousSize : %d\n", previousSize);
264 //printf("n : %d\n", finalSize / (currentSize * previousSize));
265 int occ = finalSize / (currentSize * previousSize);
266 for (int n = 0; n < occ; ++n)
268 int idx = currentSize * previousSize * n;
269 for (int m = 0; m < currentSize; ++m)
271 if (dimsIn > 1 && pv[m] >= pdims[currentDim])
275 int idx2 = idx + previousSize * m;
276 int idx3 = previousDims * pv[m];
277 for (int j = 0; j < previousSize; ++j)
279 index[idx2 + j] += idx3;
280 //printf("\tindex[%d] = %d\n", idx2 + i, previousSize * v[m]);
286 previousSize *= currentSize;
287 previousDims *= pdims[currentDim];
296 //check argument types and compute, dimensions, count of combinations, max indexes
297 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
299 int iDims = static_cast<int>(_pArgsIn->size());
301 bool bUndefine = false;
303 for (int i = 0; i < iDims; i++)
305 bool bDeleteNeeded = false;
306 InternalType* pIT = (*_pArgsIn)[i];
307 Double *pCurrentArg = NULL;
311 pCurrentArg = pIT->getAs<Double>();
312 if (pCurrentArg->isEmpty())
317 if (pCurrentArg->isIdentity())
319 //extract with eye() <=> :
321 bDeleteNeeded = true;
323 else if (pIT->isDeletable())
325 // Clone pIT when this ref is equal to zero
326 // will prevent double delete.
327 pCurrentArg = pIT->clone()->getAs<Double>();
330 //check valid values neg or complex
331 if (pCurrentArg->isComplex())
333 if (pCurrentArg->isDeletable())
335 pCurrentArg->killMe();
342 int size = pCurrentArg->getSize();
343 double* dbl = pCurrentArg->get();
344 for (int j = 0; j < size; ++j)
348 if (pCurrentArg->isDeletable())
350 pCurrentArg->killMe();
359 //previous if can update pIT to Colon
360 if (pIT->isColon() || pIT->isImplicitList())
363 ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
364 if (pIL->isComputable() == false)
369 //not enough information to compute indexes.
370 _pArgsOut->push_back(NULL);
375 //evalute polynom with "MaxDim"
376 int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
377 #if defined(_SCILAB_DEBUGREF_)
378 Double* pdbl = new Double(iMaxDim);
382 if (pIL->getStart()->isPoly())
384 Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
385 #if defined(_SCILAB_DEBUGREF_)
386 pIL->setStart(poPoly->evaluate(pdbl));
388 pIL->setStart(poPoly->evaluate(&dbl));
391 if (pIL->getStep()->isPoly())
393 Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
394 #if defined(_SCILAB_DEBUGREF_)
395 pIL->setStep(poPoly->evaluate(pdbl));
397 pIL->setStep(poPoly->evaluate(&dbl));
400 if (pIL->getEnd()->isPoly())
402 Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
403 #if defined(_SCILAB_DEBUGREF_)
404 pIL->setEnd(poPoly->evaluate(pdbl));
406 pIL->setEnd(poPoly->evaluate(&dbl));
410 #if defined(_SCILAB_DEBUGREF_)
416 pCurrentArg = pIL->extractFullMatrix()->getAs<Double>();
419 else if (pIT->isString())
421 String* pStr = pIT->getAs<String>();
422 if (_pRef->isStruct())
424 Struct* pStruct = _pRef->getAs<Struct>();
426 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
432 wchar_t* pFieldName = pStr->get(0);
434 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
435 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
442 pCurrentArg = new Double((double)iIndex);
444 else if (_pRef->isTList())
446 // List can't be extract by field and MList must call overload
447 TList* pTL = _pRef->getAs<TList>();
448 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
449 double* pdbl = pCurrentArg->get();
450 for (int i = 0; i < pStr->getSize(); i++)
452 wchar_t* pFieldName = pStr->get(i);
453 int iIndex = pTL->getIndexFromString(pFieldName);
459 pdbl[i] = (double)(iIndex + 1);
462 else if (_pRef->isList())
467 else if (_pRef->isCell())
471 else if (pIT->isPoly())
474 Polynom* pMP = pIT->getAs<types::Polynom>();
476 //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
479 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
482 #ifdef _SCILAB_DEBUGREF_
483 Double* pdbl = new Double(iMaxDim); // $
484 pCurrentArg = pMP->evaluate(pdbl);
487 Double dbl(iMaxDim); // $
488 pCurrentArg = pMP->evaluate(&dbl);
491 else if (pIT->isBool())
494 Bool *pB = pIT->getAs<types::Bool>();
495 int *piB = pB->get();
496 const int size = pB->getSize();
498 //find true item count
500 for (int j = 0; j < size; j++)
508 //allow new Double variable
509 Double* pDbl = new Double(1, iItemCount);
510 double* pdbl = pDbl->getReal();
513 for (int l = 0; l < size; l++)
530 const int iCountDim = pCurrentArg->getSize();
532 for (int j = 0; j < iCountDim; j++)
534 //checks if size < size(int)
535 if (pCurrentArg->get(j) >= INT_MAX)
537 wchar_t szError[bsiz];
538 os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
539 throw ast::ScilabError(szError);
542 int d = static_cast<int>(pCurrentArg->get(j));
543 if (d > _piMaxDim[i])
549 iSeqCount *= iCountDim;
552 _piCountDim[i] = iCountDim;
557 wchar_t szError[bsiz];
558 os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
561 delete[] _piCountDim;
562 cleanIndexesArguments(_pArgsIn, _pArgsOut);
564 throw ast::ScilabError(szError);
566 _pArgsOut->push_back(pCurrentArg);
571 //return 0 to force extract to create an empty matrix
572 if (_pRef && _pRef->isDouble() && _pRef->getAs<Double>()->isEmpty())
577 //returns a negative value if at least one parameter is undefined
578 //case with : or $ for creation by insertion
579 return (!bUndefine ? iSeqCount : -iSeqCount);
582 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
587 for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
589 if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
591 if ((*_pArgsNew)[iArg])
593 (*_pArgsNew)[iArg]->killMe();
602 void getIndexesWithDims(int _iIndex, int* _piIndexes, int* _piDims, int _iDims)
605 for (int i = 0; i < _iDims; i++)
607 _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
612 //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
627 // (22 / 12) % 3 -> 1
636 // (35 / 12) % 3 -> 2
640 int getIndexWithDims(int* _piIndexes, int* _piDims, int _iDims)
644 for (int i = 0; i < _iDims; i++)
646 idx += _piIndexes[i] * iMult;
652 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
654 if (pIT->hasToString() == false)
656 types::Function::ReturnValue ret = types::Function::Error;
657 //call overload %type_p
658 types::typed_list in;
659 types::typed_list out;
660 ast::ExecVisitor exec;
667 ret = Overload::generateNameAndCall(L"p", in, 1, out, &exec);
671 catch (ast::ScilabError &e)
679 std::wostringstream ostr;
680 if (pIT->isFunction())
682 pIT->getAs<types::Function>()->toString(ostr);
684 else if (pIT->isList() || pIT->isCallable())
689 //to manage lines information
690 int iLines = ConfigVariable::getConsoleLines();
692 bool bFinish = false;
696 bFinish = pIT->toString(ostr);
697 if (ConfigVariable::isError())
699 ConfigVariable::resetError();
701 return types::Function::Error;
704 if (bFinish == false && iLines != 0)
706 //show message on prompt
707 bFinish = linesmore() == 1;
710 scilabForcedWriteW(ostr.str().c_str());
713 while (bFinish == false);
715 pIT->clearPrintState();
716 return types::Function::OK;