2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - 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.
19 #include "alltypes.hxx"
20 #include "types_tools.hxx"
21 #include "overload.hxx"
22 #include "scilabWrite.hxx"
26 #include "elem_common.h"
27 #include "os_string.h"
34 void getIndexes(T* val, std::vector<int>& vec)
36 typename T::type* p = val->get();
37 int size = val->getSize();
38 for (int i = 0; i < size; ++i)
40 vec.push_back(static_cast<int>(p[i]));
45 double getIndex(T* val)
47 typename T::type* p = val->get();
48 return static_cast<double>(p[0]);
52 Double* convertIndex(T* pI)
54 int size = pI->getSize();
55 Double* pCurrentArg = new Double(1, size);
56 double* pdbl = pCurrentArg->get();
57 for (int l = 0; l < size; l++)
59 pdbl[l] = static_cast<double>(pI->get(l));
64 double getIndex(InternalType* val)
66 switch (val->getType())
69 case InternalType::ScilabDouble:
71 return getIndex(val->getAs<Double>());
73 case InternalType::ScilabInt8:
75 return getIndex(val->getAs<Int8>());
77 case InternalType::ScilabInt16:
79 return getIndex(val->getAs<Int16>());
81 case InternalType::ScilabInt32:
83 return getIndex(val->getAs<Int32>());
85 case InternalType::ScilabInt64:
87 return getIndex(val->getAs<Int64>());
89 case InternalType::ScilabUInt8:
91 return getIndex(val->getAs<UInt8>());
93 case InternalType::ScilabUInt16:
95 return getIndex(val->getAs<UInt16>());
97 case InternalType::ScilabUInt32:
99 return getIndex(val->getAs<UInt32>());
101 case InternalType::ScilabUInt64:
103 return getIndex(val->getAs<UInt64>());
110 //get only scalar index
111 bool getScalarIndex(GenericType* _pRef, typed_list* _pArgsIn, int* index)
113 //input size must be equal to ref dims
114 int dimsRef = _pRef->getDims();
115 int dimsIn = static_cast<int>(_pArgsIn->size());
117 //same dims and less than internal limit
118 if (dimsIn != 1 && (dimsIn != dimsRef || dimsIn > MAX_DIMS))
123 int* pdims = _pRef->getDimsArray();
125 for (int i = 0; i < dimsIn; ++i)
127 InternalType* in = (*_pArgsIn)[i];
128 //input arg type must be scalar double, int8, int16, ...
129 if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
131 ind[i] = static_cast<int>(getIndex(in)) - 1;
139 //failed, so use entire process
145 int previousDims = 1;
146 for (int i = 0; i < dimsIn; ++i)
148 if (dimsIn != 1 && ind[i] >= pdims[i])
153 idx += ind[i] * previousDims;
154 previousDims *= pdims[i];
161 static double evalute(InternalType* pIT, int sizeRef)
165 if (pIT->getId() == InternalType::IdScalarPolynom)
167 SinglePoly* pSP = pIT->getAs<Polynom>()->get()[0];
168 pSP->evaluate(sizeRef, 0, &real, &img);
172 real = getIndex(pIT);
178 bool getScalarImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<double>& index)
180 int dimsIn = static_cast<int>(_pArgsIn->size());
186 InternalType* pIT = (*_pArgsIn)[0];
188 if (pIT->isImplicitList() == false)
198 index.push_back(_pRef->getSize());
199 //use to know we have a real ":" to shape return matrix in col vector
204 ImplicitList* pIL = pIT->getAs<ImplicitList>();
205 int sizeRef = _pRef->getSize();
206 index.push_back(evalute(pIL->getStart(), sizeRef));
207 index.push_back(evalute(pIL->getStep(), sizeRef));
208 index.push_back(evalute(pIL->getEnd(), sizeRef));
214 //get index from implicit or colon index + scalar
215 bool getImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<int>& index, std::vector<int>& dims)
217 int dimsRef = _pRef->getDims();
218 int dimsIn = static_cast<int>(_pArgsIn->size());
219 bool viewAsVector = dimsIn == 1;
220 dims.reserve(dimsIn);
221 //same dims and less than internal limit
222 if (dimsIn != 1 && (dimsIn != dimsRef || dimsIn > MAX_DIMS))
227 int* pdims = _pRef->getDimsArray();
228 //input arg type must be computable ( double, $, :, ... )
229 std::list<std::vector<int>> lstIdx;
231 for (int i = 0; i < dimsIn; ++i)
233 InternalType* in = (*_pArgsIn)[i];
234 if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
236 int idx = static_cast<int>(getIndex(in)) - 1;
242 lstIdx.emplace_back(1, idx);
245 else if (in->isColon())
247 std::vector<int> idx(2);
249 idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
250 lstIdx.push_back(idx);
252 dims.push_back(idx[1]);
254 else if (in->isImplicitList())
256 ImplicitList* pIL = in->getAs<ImplicitList>();
257 InternalType* piStart = pIL->getStart();
258 InternalType* piStep = pIL->getStep();
259 InternalType* piEnd = pIL->getEnd();
261 bool isColon = false;
262 if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
264 if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
266 SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
267 if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
269 std::vector<int> idx(2);
271 idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
272 lstIdx.push_back(idx);
275 dims.push_back(idx[1]);
280 if (isColon == false)
282 int sizeRef = viewAsVector ? _pRef->getSize() : pdims[i];
283 double start = evalute(pIL->getStart(), sizeRef);
284 double step = evalute(pIL->getStep(), sizeRef);
285 double end = evalute(pIL->getEnd(), sizeRef);
287 //printf("%.2f : %.2f : %.2f\n", start, step, end);
289 int size = (end - start) / step + 1;
292 //manage implicit that return []
297 std::vector<int> idx(size);
298 int* pi = idx.data();
299 pi[0] = start - 1; //0-indexed
300 for (int j = 1; j < size; ++j)
302 pi[j] = pi[j - 1] + step;
305 lstIdx.push_back(idx);
307 dims.push_back(size);
316 index.resize(finalSize, 0);
324 int previousSize = 1;
326 int previousDims = 1;
327 while (lstIdx.empty() == false)
329 std::vector<int>& v = lstIdx.front();
330 int currentSize = static_cast<int>(v.size());
331 const int* pv = v.data();
333 if (pv[0] == -1 && currentSize == 2)
336 int occ = finalSize / (currentSize * previousSize);
337 for (int n = 0; n < occ; ++n)
339 int idx = currentSize * previousSize * n;
340 for (int m = 0; m < currentSize; ++m)
342 if (dimsIn > 1 && m >= pdims[currentDim])
346 int idx2 = idx + previousSize * m;
347 int idx3 = previousDims * m;
348 for (int j = 0; j < previousSize; ++j)
350 index[idx2 + j] += idx3;
357 int occ = finalSize / (currentSize * previousSize);
358 for (int n = 0; n < occ; ++n)
360 int idx = currentSize * previousSize * n;
361 for (int m = 0; m < currentSize; ++m)
363 if (dimsIn > 1 && pv[m] >= pdims[currentDim])
367 int idx2 = idx + previousSize * m;
368 int idx3 = previousDims * pv[m];
369 for (int j = 0; j < previousSize; ++j)
371 index[idx2 + j] += idx3;
377 previousSize *= currentSize;
378 previousDims *= pdims[currentDim];
387 //check argument types and compute, dimensions, count of combinations, max indexes
388 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
390 int iDims = static_cast<int>(_pArgsIn->size());
392 bool bUndefine = false;
394 for (int i = 0; i < iDims; i++)
396 bool bDeleteNeeded = false;
397 InternalType* pIT = (*_pArgsIn)[i];
398 Double *pCurrentArg = NULL;
402 pCurrentArg = pIT->getAs<Double>();
403 if (pCurrentArg->isEmpty())
408 if (pCurrentArg->isIdentity())
410 //extract with eye() <=> :
412 bDeleteNeeded = true;
414 else if (pIT->isDeletable())
416 // Clone pIT when this ref is equal to zero
417 // will prevent double delete.
418 pCurrentArg = pIT->clone()->getAs<Double>();
421 //check valid values neg or complex
422 if (pCurrentArg->isComplex())
424 if (pCurrentArg->isDeletable())
426 pCurrentArg->killMe();
433 int size = pCurrentArg->getSize();
434 double* dbl = pCurrentArg->get();
435 for (int j = 0; j < size; ++j)
439 if (pCurrentArg->isDeletable())
441 pCurrentArg->killMe();
450 //previous if can update pIT to Colon
451 if (pIT->isColon() || pIT->isImplicitList())
454 ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
455 if (pIL->isComputable() == false)
460 //not enough information to compute indexes.
461 _pArgsOut->push_back(NULL);
466 //evalute polynom with "MaxDim"
467 int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
468 #if defined(_SCILAB_DEBUGREF_)
469 Double* pdbl = new Double(iMaxDim);
473 if (pIL->getStart()->isPoly())
475 Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
476 #if defined(_SCILAB_DEBUGREF_)
477 pIL->setStart(poPoly->evaluate(pdbl));
479 pIL->setStart(poPoly->evaluate(&dbl));
482 if (pIL->getStep()->isPoly())
484 Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
485 #if defined(_SCILAB_DEBUGREF_)
486 pIL->setStep(poPoly->evaluate(pdbl));
488 pIL->setStep(poPoly->evaluate(&dbl));
491 if (pIL->getEnd()->isPoly())
493 Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
494 #if defined(_SCILAB_DEBUGREF_)
495 pIL->setEnd(poPoly->evaluate(pdbl));
497 pIL->setEnd(poPoly->evaluate(&dbl));
501 #if defined(_SCILAB_DEBUGREF_)
507 pCurrentArg = pIL->extractFullMatrix()->getAs<Double>();
510 else if (pIT->isString())
512 String* pStr = pIT->getAs<String>();
518 if (_pRef->isStruct())
520 Struct* pStruct = _pRef->getAs<Struct>();
522 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
528 wchar_t* pFieldName = pStr->get(0);
530 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
531 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
538 pCurrentArg = new Double((double)iIndex);
540 else if (_pRef->isTList())
542 // List can't be extract by field and MList must call overload
543 TList* pTL = _pRef->getAs<TList>();
544 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
545 double* pdbl = pCurrentArg->get();
546 for (int i = 0; i < pStr->getSize(); i++)
548 wchar_t* pFieldName = pStr->get(i);
549 int iIndex = pTL->getIndexFromString(pFieldName);
555 pdbl[i] = (double)(iIndex + 1);
558 else if (_pRef->isList())
563 else if (_pRef->isCell())
567 else if (pIT->isPoly())
570 Polynom* pMP = pIT->getAs<types::Polynom>();
572 //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
575 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
578 #ifdef _SCILAB_DEBUGREF_
579 Double* pdbl = new Double(iMaxDim); // $
580 pCurrentArg = pMP->evaluate(pdbl);
583 Double dbl(iMaxDim); // $
584 pCurrentArg = pMP->evaluate(&dbl);
587 else if (pIT->isBool())
590 Bool *pB = pIT->getAs<types::Bool>();
591 int *piB = pB->get();
592 const int size = pB->getSize();
594 //find true item count
596 for (int j = 0; j < size; j++)
604 //allow new Double variable
605 Double* pDbl = new Double(1, iItemCount);
606 double* pdbl = pDbl->getReal();
609 for (int l = 0; l < size; l++)
618 else if (pIT->isInt())
620 switch (pIT->getType())
622 case InternalType::ScilabInt8:
624 pCurrentArg = convertIndex(pIT->getAs<Int8>());
627 case InternalType::ScilabInt16:
629 pCurrentArg = convertIndex(pIT->getAs<Int16>());
632 case InternalType::ScilabInt32:
634 pCurrentArg = convertIndex(pIT->getAs<Int32>());
637 case InternalType::ScilabInt64:
639 pCurrentArg = convertIndex(pIT->getAs<Int64>());
642 case InternalType::ScilabUInt8:
644 pCurrentArg = convertIndex(pIT->getAs<UInt8>());
647 case InternalType::ScilabUInt16:
649 pCurrentArg = convertIndex(pIT->getAs<UInt16>());
652 case InternalType::ScilabUInt32:
654 pCurrentArg = convertIndex(pIT->getAs<UInt32>());
657 case InternalType::ScilabUInt64:
659 pCurrentArg = convertIndex(pIT->getAs<UInt64>());
672 const int iCountDim = pCurrentArg->getSize();
674 for (int j = 0; j < iCountDim; j++)
676 //checks if size < size(int)
677 if (pCurrentArg->get(j) >= INT_MAX)
679 wchar_t szError[bsiz];
680 os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
681 throw ast::InternalError(szError);
684 int d = static_cast<int>(pCurrentArg->get(j));
685 if (d > _piMaxDim[i])
691 iSeqCount *= iCountDim;
694 _piCountDim[i] = iCountDim;
699 wchar_t szError[bsiz];
700 os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
703 delete[] _piCountDim;
704 cleanIndexesArguments(_pArgsIn, _pArgsOut);
706 throw ast::InternalError(szError);
708 _pArgsOut->push_back(pCurrentArg);
713 //return 0 to force extract to create an empty matrix
715 (_pRef->isDouble() && _pRef->getAs<Double>()->isEmpty()))
720 //returns a negative value if at least one parameter is undefined
721 //case with : or $ for creation by insertion
722 return (!bUndefine ? iSeqCount : -iSeqCount);
725 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
730 for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
732 if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
734 if ((*_pArgsNew)[iArg])
736 (*_pArgsNew)[iArg]->killMe();
745 void getIndexesWithDims(int _iIndex, int* _piIndexes, const int* _piDims, int _iDims)
748 for (int i = 0; i < _iDims; i++)
750 _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
755 //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
770 // (22 / 12) % 3 -> 1
779 // (35 / 12) % 3 -> 2
783 int getIndexWithDims(int* _piIndexes, const int* _piDims, int _iDims)
787 for (int i = 0; i < _iDims; i++)
789 idx += _piIndexes[i] * iMult;
795 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
797 if (pIT->hasToString() == false)
799 types::Function::ReturnValue ret = types::Function::Error;
800 //call overload %type_p
801 types::typed_list in;
802 types::typed_list out;
809 ret = Overload::generateNameAndCall(L"p", in, 1, out);
813 catch (const ast::InternalError &ie)
821 std::wostringstream ostr;
822 if (pIT->isFunction())
824 pIT->getAs<types::Function>()->toString(ostr);
826 else if (pIT->isList() || pIT->isCallable())
831 //to manage lines information
832 int iLines = ConfigVariable::getConsoleLines();
834 bool bFinish = false;
838 bFinish = pIT->toString(ostr);
839 if (ConfigVariable::isError())
841 ConfigVariable::resetError();
843 ConfigVariable::resetExecutionBreak();
844 return types::Function::Error;
847 if (bFinish == false && iLines != 0)
849 //show message on prompt
850 bFinish = linesmore() == 1;
853 if (ConfigVariable::isPrintCompact() == false && ConfigVariable::isPrintInput() == false)
858 scilabForcedWriteW(ostr.str().c_str());
861 while (bFinish == false && ConfigVariable::isExecutionBreak() == false);
863 if (bFinish == false)
865 ConfigVariable::resetExecutionBreak();
867 pIT->clearPrintState();
868 return types::Function::OK;
873 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
875 //if bRet == 1, previous dims has reach max value.
878 if (_iCurrentDim == 0)
881 if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
883 _piIndex[_iCurrentDim] = 0;
889 iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
892 _piIndex[_iCurrentDim]++;
893 if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
895 _piIndex[_iCurrentDim] = 0;
903 Double* createEmptyDouble()
905 return Double::Empty();
908 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
910 return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
913 double* getDoubleArrayFromDouble(InternalType* _pIT)
915 return _pIT->getAs<Double>()->get();
918 Double* createDoubleVector(int _iSize)
920 int piDims[] = {1, _iSize};
921 Double* pOut = new Double(2, piDims);
922 for (int i = 0; i < _iSize; i++)
929 bool checkArgValidity(typed_list& _Arg)
931 for (int i = 0; i < (int)_Arg.size(); i++)
933 if (_Arg[i]->isDouble() == false)
938 Double* pDbl = _Arg[i]->getAs<Double>();
939 double* pdbl = pDbl->get();
940 for (int j = 0; j < pDbl->getSize(); j++)