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])
130 int previousDims = 1;
131 for (int i = 0; i < dimsIn; ++i)
133 if (dimsIn != 1 && ind[i] >= pdims[i])
138 idx += ind[i] * previousDims;
139 previousDims *= pdims[i];
146 static double evalute(InternalType* pIT, int sizeRef)
150 if (pIT->getId() == InternalType::IdScalarPolynom)
152 SinglePoly* pSP = pIT->getAs<Polynom>()->get()[0];
153 pSP->evaluate(sizeRef, 0, &real, &img);
157 real = getIndex(pIT);
162 //get index from implicit or colon index + scalar
163 bool getImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<int>& index)
165 int dimsRef = _pRef->getDims();
166 int dimsIn = static_cast<int>(_pArgsIn->size());
167 bool viewAsVector = dimsIn == 1;
168 //same dims and less than internal limit
169 if (dimsIn != 1 && dimsIn != dimsRef || dimsIn > MAX_DIMS)
174 int* pdims = _pRef->getDimsArray();
175 //input arg type must be computable ( double, $, :, ... )
176 std::list<std::vector<int>> lstIdx;
178 for (int i = 0; i < dimsIn; ++i)
180 InternalType* in = (*_pArgsIn)[i];
181 if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
183 int idx = static_cast<int>(getIndex(in)) - 1;
189 lstIdx.emplace_back(1, idx);
191 else if (in->isColon())
195 idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
196 lstIdx.push_back(idx);
199 else if (in->isImplicitList())
201 ImplicitList* pIL = in->getAs<ImplicitList>();
202 InternalType* piStart = pIL->getStart();
203 InternalType* piStep = pIL->getStep();
204 InternalType* piEnd = pIL->getEnd();
206 if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
208 if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
210 SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
211 if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
215 idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
216 lstIdx.push_back(idx);
223 int sizeRef = viewAsVector ? _pRef->getSize() : pdims[i];
224 double start = evalute(pIL->getStart(), sizeRef);
225 double step = evalute(pIL->getStep(), sizeRef);
226 double end = evalute(pIL->getEnd(), sizeRef);
228 //printf("%.2f : %.2f : %.2f\n", start, step, end);
230 int size = (end - start) / step + 1;
231 vector<int> idx(size);
235 //manage implicit that return []
240 int* pi = idx.data();
241 pi[0] = start - 1; //0-indexed
242 for (int j = 1; j < size; ++j)
244 pi[j] = pi[j - 1] + step;
247 lstIdx.push_back(idx);
257 index.resize(finalSize, 0);
258 //printf("finalSize : %d\n", finalSize);
260 int previousSize = 1;
262 int previousDims = 1;
263 while (lstIdx.empty() == false)
265 std::vector<int>& v = lstIdx.front();
266 int currentSize = v.size();
267 const int* pv = v.data();
270 if (pv[0] == -1 && currentSize == 2)
273 int occ = finalSize / (currentSize * previousSize);
274 for (int n = 0; n < occ; ++n)
276 int idx = currentSize * previousSize * n;
277 for (int m = 0; m < currentSize; ++m)
279 if (dimsIn > 1 && m >= pdims[currentDim])
283 int idx2 = idx + previousSize * m;
284 int idx3 = previousDims * m;
285 for (int j = 0; j < previousSize; ++j)
287 index[idx2 + j] += idx3;
288 //printf("\tindex[%d] = %d\n", idx2 + i, previousSize * v[m]);
295 //printf("currentSize : %d\n", currentSize);
296 //printf("previousSize : %d\n", previousSize);
297 //printf("n : %d\n", finalSize / (currentSize * previousSize));
298 int occ = finalSize / (currentSize * previousSize);
299 for (int n = 0; n < occ; ++n)
301 int idx = currentSize * previousSize * n;
302 for (int m = 0; m < currentSize; ++m)
304 if (dimsIn > 1 && pv[m] >= pdims[currentDim])
308 int idx2 = idx + previousSize * m;
309 int idx3 = previousDims * pv[m];
310 for (int j = 0; j < previousSize; ++j)
312 index[idx2 + j] += idx3;
313 //printf("\tindex[%d] = %d\n", idx2 + i, previousSize * v[m]);
319 previousSize *= currentSize;
320 previousDims *= pdims[currentDim];
329 //check argument types and compute, dimensions, count of combinations, max indexes
330 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
332 int iDims = static_cast<int>(_pArgsIn->size());
334 bool bUndefine = false;
336 for (int i = 0; i < iDims; i++)
338 bool bDeleteNeeded = false;
339 InternalType* pIT = (*_pArgsIn)[i];
340 Double *pCurrentArg = NULL;
344 pCurrentArg = pIT->getAs<Double>();
345 if (pCurrentArg->isEmpty())
350 if (pCurrentArg->isIdentity())
352 //extract with eye() <=> :
354 bDeleteNeeded = true;
356 else if (pIT->isDeletable())
358 // Clone pIT when this ref is equal to zero
359 // will prevent double delete.
360 pCurrentArg = pIT->clone()->getAs<Double>();
363 //check valid values neg or complex
364 if (pCurrentArg->isComplex())
366 if (pCurrentArg->isDeletable())
368 pCurrentArg->killMe();
375 int size = pCurrentArg->getSize();
376 double* dbl = pCurrentArg->get();
377 for (int j = 0; j < size; ++j)
381 if (pCurrentArg->isDeletable())
383 pCurrentArg->killMe();
392 //previous if can update pIT to Colon
393 if (pIT->isColon() || pIT->isImplicitList())
396 ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
397 if (pIL->isComputable() == false)
402 //not enough information to compute indexes.
403 _pArgsOut->push_back(NULL);
408 //evalute polynom with "MaxDim"
409 int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
410 #if defined(_SCILAB_DEBUGREF_)
411 Double* pdbl = new Double(iMaxDim);
415 if (pIL->getStart()->isPoly())
417 Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
418 #if defined(_SCILAB_DEBUGREF_)
419 pIL->setStart(poPoly->evaluate(pdbl));
421 pIL->setStart(poPoly->evaluate(&dbl));
424 if (pIL->getStep()->isPoly())
426 Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
427 #if defined(_SCILAB_DEBUGREF_)
428 pIL->setStep(poPoly->evaluate(pdbl));
430 pIL->setStep(poPoly->evaluate(&dbl));
433 if (pIL->getEnd()->isPoly())
435 Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
436 #if defined(_SCILAB_DEBUGREF_)
437 pIL->setEnd(poPoly->evaluate(pdbl));
439 pIL->setEnd(poPoly->evaluate(&dbl));
443 #if defined(_SCILAB_DEBUGREF_)
449 pCurrentArg = pIL->extractFullMatrix()->getAs<Double>();
452 else if (pIT->isString())
454 String* pStr = pIT->getAs<String>();
455 if (_pRef->isStruct())
457 Struct* pStruct = _pRef->getAs<Struct>();
459 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
465 wchar_t* pFieldName = pStr->get(0);
467 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
468 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
475 pCurrentArg = new Double((double)iIndex);
477 else if (_pRef->isTList())
479 // List can't be extract by field and MList must call overload
480 TList* pTL = _pRef->getAs<TList>();
481 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
482 double* pdbl = pCurrentArg->get();
483 for (int i = 0; i < pStr->getSize(); i++)
485 wchar_t* pFieldName = pStr->get(i);
486 int iIndex = pTL->getIndexFromString(pFieldName);
492 pdbl[i] = (double)(iIndex + 1);
495 else if (_pRef->isList())
500 else if (_pRef->isCell())
504 else if (pIT->isPoly())
507 Polynom* pMP = pIT->getAs<types::Polynom>();
509 //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
512 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
515 #ifdef _SCILAB_DEBUGREF_
516 Double* pdbl = new Double(iMaxDim); // $
517 pCurrentArg = pMP->evaluate(pdbl);
520 Double dbl(iMaxDim); // $
521 pCurrentArg = pMP->evaluate(&dbl);
524 else if (pIT->isBool())
527 Bool *pB = pIT->getAs<types::Bool>();
528 int *piB = pB->get();
529 const int size = pB->getSize();
531 //find true item count
533 for (int j = 0; j < size; j++)
541 //allow new Double variable
542 Double* pDbl = new Double(1, iItemCount);
543 double* pdbl = pDbl->getReal();
546 for (int l = 0; l < size; l++)
563 const int iCountDim = pCurrentArg->getSize();
565 for (int j = 0; j < iCountDim; j++)
567 //checks if size < size(int)
568 if (pCurrentArg->get(j) >= INT_MAX)
570 wchar_t szError[bsiz];
571 os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
572 throw ast::ScilabError(szError);
575 int d = static_cast<int>(pCurrentArg->get(j));
576 if (d > _piMaxDim[i])
582 iSeqCount *= iCountDim;
585 _piCountDim[i] = iCountDim;
590 wchar_t szError[bsiz];
591 os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
594 delete[] _piCountDim;
595 cleanIndexesArguments(_pArgsIn, _pArgsOut);
597 throw ast::ScilabError(szError);
599 _pArgsOut->push_back(pCurrentArg);
604 //return 0 to force extract to create an empty matrix
605 if (_pRef && _pRef->isDouble() && _pRef->getAs<Double>()->isEmpty())
610 //returns a negative value if at least one parameter is undefined
611 //case with : or $ for creation by insertion
612 return (!bUndefine ? iSeqCount : -iSeqCount);
615 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
620 for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
622 if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
624 if ((*_pArgsNew)[iArg])
626 (*_pArgsNew)[iArg]->killMe();
635 void getIndexesWithDims(int _iIndex, int* _piIndexes, int* _piDims, int _iDims)
638 for (int i = 0; i < _iDims; i++)
640 _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
645 //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
660 // (22 / 12) % 3 -> 1
669 // (35 / 12) % 3 -> 2
673 int getIndexWithDims(int* _piIndexes, int* _piDims, int _iDims)
677 for (int i = 0; i < _iDims; i++)
679 idx += _piIndexes[i] * iMult;
685 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
687 if (pIT->hasToString() == false)
689 types::Function::ReturnValue ret = types::Function::Error;
690 //call overload %type_p
691 types::typed_list in;
692 types::typed_list out;
693 ast::ExecVisitor exec;
700 ret = Overload::generateNameAndCall(L"p", in, 1, out, &exec);
704 catch (ast::ScilabError &e)
712 std::wostringstream ostr;
713 if (pIT->isFunction())
715 pIT->getAs<types::Function>()->toString(ostr);
717 else if (pIT->isList() || pIT->isCallable())
722 //to manage lines information
723 int iLines = ConfigVariable::getConsoleLines();
725 bool bFinish = false;
729 bFinish = pIT->toString(ostr);
730 if (ConfigVariable::isError())
732 ConfigVariable::resetError();
734 return types::Function::Error;
737 if (bFinish == false && iLines != 0)
739 //show message on prompt
740 bFinish = linesmore() == 1;
743 scilabForcedWriteW(ostr.str().c_str());
746 while (bFinish == false);
748 pIT->clearPrintState();
749 return types::Function::OK;