1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
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.
13 *
14 */
15 
16 #include <list>
17 #include <vector>
18 
19 #include "alltypes.hxx"
20 #include "types_tools.hxx"
21 #include "overload.hxx"
22 #include "scilabWrite.hxx"
23 
24 extern "C"
25 {
26 #include "elem_common.h"
27 #include "os_string.h"
28 #include "more.h"
29 #include "sciprint.h"
30 }
31 
32 namespace types
33 {
34 template<typename T>
getIndexes(T * val,std::vector<int> & vec)35 void getIndexes(T* val, std::vector<int>& vec)
36 {
37     typename T::type* p = val->get();
38     int size = val->getSize();
39     for (int i = 0; i < size; ++i)
40     {
41         vec.push_back(static_cast<int>(p[i]));
42     }
43 }
44 
45 template<typename T>
getIndex(T * val)46 double getIndex(T* val)
47 {
48     typename T::type* p = val->get();
49     return static_cast<double>(p[0]);
50 }
51 
52 template<typename T>
convertIndex(T * pI)53 Double* convertIndex(T* pI)
54 {
55     int size = pI->getSize();
56     Double* pCurrentArg = new Double(pI->getDims(), pI->getDimsArray());
57     double* pdbl = pCurrentArg->get();
58     for (int l = 0; l < size; l++)
59     {
60         pdbl[l] = static_cast<double>(pI->get(l));
61     }
62     return pCurrentArg;
63 }
64 
getIndex(InternalType * val)65 double getIndex(InternalType* val)
66 {
67     switch (val->getType())
68     {
69         //scalar
70         case InternalType::ScilabDouble:
71         {
72             return getIndex(val->getAs<Double>());
73         }
74         case InternalType::ScilabInt8:
75         {
76             return getIndex(val->getAs<Int8>());
77         }
78         case InternalType::ScilabInt16:
79         {
80             return getIndex(val->getAs<Int16>());
81         }
82         case InternalType::ScilabInt32:
83         {
84             return getIndex(val->getAs<Int32>());
85         }
86         case InternalType::ScilabInt64:
87         {
88             return getIndex(val->getAs<Int64>());
89         }
90         case InternalType::ScilabUInt8:
91         {
92             return getIndex(val->getAs<UInt8>());
93         }
94         case InternalType::ScilabUInt16:
95         {
96             return getIndex(val->getAs<UInt16>());
97         }
98         case InternalType::ScilabUInt32:
99         {
100             return getIndex(val->getAs<UInt32>());
101         }
102         case InternalType::ScilabUInt64:
103         {
104             return getIndex(val->getAs<UInt64>());
105         }
106     }
107 
108     return 0;
109 }
110 
111 //get only scalar index
getArgsDims(typed_list * _pArgsIn,std::vector<int> & dims)112 bool getArgsDims(typed_list* _pArgsIn, std::vector<int>& dims)
113 {
114     //input size must be equal to ref dims
115     int dimsIn = static_cast<int>(_pArgsIn->size());
116 
117     //same dims and less than internal limit
118     if (dimsIn > MAX_DIMS)
119     {
120         return false;
121     }
122 
123     dims.reserve(dimsIn);
124 
125     for (int i = 0; i < dimsIn; ++i)
126     {
127         InternalType* in = (*_pArgsIn)[i];
128         //input arg type must be scalar double, int8, int16, ...
129         if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
130         {
131             int ind = static_cast<int>(getIndex(in));
132             if (ind == 0)
133             {
134                 return false;
135             }
136 
137             dims.push_back(ind);
138         }
139         else if (in->isImplicitList())
140         {
141             ImplicitList* pIL = in->getAs<ImplicitList>();
142             if (pIL->isComputable() == false)
143             {
144                 return false;
145             }
146 
147             int size = (int)pIL->getSize();
148             if (size <= 0)
149             {
150                 return false;
151             }
152 
153 
154             double start = getIndex(pIL->getStart());
155             double step = getIndex(pIL->getStep());
156             if (step > 0)
157             {
158                 double real_end = start + step * (size - 1);
159                 dims.push_back((int)real_end);
160             }
161             else if (step < 0)
162             {
163                 dims.push_back((int)start);
164             }
165             else
166             {
167                 return false;
168             }
169         }
170         else
171         {
172             //failed, so use entire process
173             return false;
174         }
175     }
176 
177 
178     //remove last dims == 1
179     while (dims.size() > 2)
180     {
181         if (dims.back() != 1)
182         {
183             break;
184         }
185 
186         dims.pop_back();
187     }
188 
189     return true;
190 }
191 
192 
193 //get only scalar index
getScalarIndex(GenericType * _pRef,typed_list * _pArgsIn,int * index)194 bool getScalarIndex(GenericType* _pRef, typed_list* _pArgsIn, int* index)
195 {
196     //input size must be equal to ref dims
197     int dimsRef = _pRef->getDims();
198     int dimsIn = static_cast<int>(_pArgsIn->size());
199 
200     //same dims and less than internal limit
201     if (dimsIn != 1 && (dimsIn != dimsRef || dimsIn > MAX_DIMS))
202     {
203         return false;
204     }
205 
206     int* pdims = _pRef->getDimsArray();
207     int ind[MAX_DIMS];
208     for (int i = 0; i < dimsIn; ++i)
209     {
210         InternalType* in = (*_pArgsIn)[i];
211         //input arg type must be scalar double, int8, int16, ...
212         if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
213         {
214             ind[i] = static_cast<int>(getIndex(in)) - 1;
215             if (ind[i] < 0)
216             {
217                 return false;
218             }
219         }
220         else
221         {
222             //failed, so use entire process
223             return false;
224         }
225     }
226 
227     int idx = 0;
228     int previousDims = 1;
229     for (int i = 0; i < dimsIn; ++i)
230     {
231         if (dimsIn != 1 && ind[i] >= pdims[i])
232         {
233             return false;
234         }
235 
236         idx += ind[i] * previousDims;
237         previousDims *= pdims[i];
238     }
239 
240     *index = idx;
241     return true;
242 }
243 
evalute(InternalType * pIT,int sizeRef)244 static double evalute(InternalType* pIT, int sizeRef)
245 {
246     double real;
247     double img;
248     if (pIT->getId() == InternalType::IdScalarPolynom)
249     {
250         SinglePoly* pSP = pIT->getAs<Polynom>()->get()[0];
251         pSP->evaluate(sizeRef, 0, &real, &img);
252     }
253     else
254     {
255         real = getIndex(pIT);
256     }
257 
258     return real;
259 }
260 
getScalarImplicitIndex(GenericType * _pRef,typed_list * _pArgsIn,std::vector<double> & index)261 bool getScalarImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<double>& index)
262 {
263     int dimsIn = static_cast<int>(_pArgsIn->size());
264     if (dimsIn != 1)
265     {
266         return false;
267     }
268 
269     InternalType* pIT = (*_pArgsIn)[0];
270 
271     if (pIT->isImplicitList() == false)
272     {
273         return false;
274     }
275 
276     index.reserve(4);
277     if (pIT->isColon())
278     {
279         index.push_back(1);
280         index.push_back(1);
281         index.push_back(_pRef->getSize());
282         //use to know we have a real ":" to shape return matrix in col vector
283         index.push_back(0);
284     }
285     else
286     {
287         ImplicitList* pIL = pIT->getAs<ImplicitList>();
288         int sizeRef = _pRef->getSize();
289         double start = evalute(pIL->getStart(), sizeRef);
290         double step = evalute(pIL->getStep(), sizeRef);
291         double end = evalute(pIL->getEnd(), sizeRef);
292 
293         if (start < 1 && step > 0 || end < 1 && step < 0)
294         {
295             wchar_t szError[bsiz];
296             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
297             throw ast::InternalError(szError);
298         }
299 
300         index.push_back(start);
301         index.push_back(step);
302         index.push_back(end);
303     }
304 
305     return true;
306 }
307 
308 //get index from implicit or colon index + scalar
getImplicitIndex(GenericType * _pRef,typed_list * _pArgsIn,std::vector<int> & index,std::vector<int> & dims)309 bool getImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<int>& index, std::vector<int>& dims)
310 {
311     int dimsRef = _pRef->getDims();
312     int dimsIn = static_cast<int>(_pArgsIn->size());
313     bool viewAsVector = dimsIn == 1;
314     dims.reserve(dimsIn);
315     //same dims and less than internal limit
316     if (dimsIn != 1 && (dimsIn != dimsRef || dimsIn > MAX_DIMS))
317     {
318         return false;
319     }
320 
321     int* pdims = _pRef->getDimsArray();
322     //input arg type must be computable ( double, $, :, ... )
323     std::list<std::vector<int>> lstIdx;
324     int finalSize = 1;
325     for (int i = 0; i < dimsIn; ++i)
326     {
327         InternalType* in = (*_pArgsIn)[i];
328         if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
329         {
330             int idx = static_cast<int>(getIndex(in)) - 1;
331             if (idx < 0)
332             {
333                 return false;
334             }
335 
336             lstIdx.emplace_back(1, idx);
337             dims.push_back(1);
338         }
339         else if (in->isColon())
340         {
341             std::vector<int> idx(2);
342             idx[0] = -1;
343             idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
344             lstIdx.push_back(idx);
345             finalSize *= idx[1];
346             dims.push_back(idx[1]);
347         }
348         else if (in->isImplicitList())
349         {
350             ImplicitList* pIL = in->getAs<ImplicitList>();
351             InternalType* piStart = pIL->getStart();
352             InternalType* piStep = pIL->getStep();
353             InternalType* piEnd = pIL->getEnd();
354 
355             bool isColon = false;
356             if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
357             {
358                 if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
359                 {
360                     SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
361                     if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
362                     {
363                         std::vector<int> idx(2);
364                         idx[0] = -1;
365                         idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
366                         lstIdx.push_back(idx);
367                         finalSize *= idx[1];
368                         isColon = true;
369                         dims.push_back(idx[1]);
370                     }
371                 }
372             }
373 
374             if (isColon == false)
375             {
376                 int sizeRef = viewAsVector ? _pRef->getSize() : pdims[i];
377                 double start = evalute(pIL->getStart(), sizeRef);
378                 double step = evalute(pIL->getStep(), sizeRef);
379                 double end = evalute(pIL->getEnd(), sizeRef);
380 
381                 int size = (int)((end - start) / step + 1);
382                 if (size <= 0)
383                 {
384                     //manage implicit that return []
385                     index.clear();
386                     return true;
387                 }
388 
389                 std::vector<int> idx(size);
390 
391                 if (start < 1 && step > 0 || end < 1 && step < 0)
392                 {
393                     wchar_t szError[bsiz];
394                     os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
395                     throw ast::InternalError(szError);
396                 }
397 
398                 double val = start - 1;
399                 std::generate(idx.begin(), idx.end(), [&val, step] { double s = val; val += step; return (int)s; });
400 
401                 lstIdx.push_back(idx);
402                 finalSize *= size;
403                 dims.push_back(size);
404             }
405         }
406         else
407         {
408             return false;
409         }
410     }
411 
412     index.resize(finalSize, 0);
413 
414     if (finalSize == 0)
415     {
416         return true;
417     }
418 
419     //compute tuples
420     int previousSize = 1;
421     int currentDim = 0;
422     int previousDims = 1;
423     int* p = index.data();
424     while (lstIdx.empty() == false)
425     {
426         std::vector<int>& v = lstIdx.front();
427         int currentSize = static_cast<int>(v.size());
428         const int* pv = v.data();
429 
430         if (pv[0] == -1 && currentSize == 2)
431         {
432             currentSize = pv[1];
433             int occ = finalSize / (currentSize * previousSize);
434             for (int n = 0; n < occ; ++n)
435             {
436                 int idx = currentSize * previousSize * n;
437                 for (int m = 0; m < currentSize; ++m)
438                 {
439                     if (dimsIn > 1 && m >= pdims[currentDim])
440                     {
441                         return false;
442                     }
443                     int idx2 = idx + previousSize * m;
444                     int idx3 = previousDims * m;
445                     for (int j = 0; j < previousSize; ++j)
446                     {
447                         p[idx2 + j] += idx3;
448                     }
449                 }
450             }
451         }
452         else
453         {
454             int* p = index.data();
455             int occ = finalSize / (currentSize * previousSize);
456             for (int n = 0; n < occ; ++n)
457             {
458                 int idx = currentSize * previousSize * n;
459                 for (int m = 0; m < currentSize; ++m)
460                 {
461                     if (dimsIn > 1 && pv[m] >= pdims[currentDim])
462                     {
463                         return false;
464                     }
465                     int idx2 = idx + previousSize * m;
466                     int idx3 = previousDims * pv[m];
467                     for (int j = 0; j < previousSize; ++j)
468                     {
469                         p[idx2 + j] += idx3;
470                     }
471                 }
472             }
473         }
474 
475         previousSize *= currentSize;
476         previousDims *= pdims[currentDim];
477         ++currentDim;
478         //remove used vector
479         lstIdx.pop_front();
480     }
481 
482     return true;
483 }
484 
485 //check argument types and compute, dimensions, count of combinations, max indexes
checkIndexesArguments(InternalType * _pRef,typed_list * _pArgsIn,typed_list * _pArgsOut,int * _piMaxDim,int * _piCountDim)486 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
487 {
488     int iDims = static_cast<int>(_pArgsIn->size());
489     int iSeqCount = 1;
490     bool bUndefine = false;
491 
492     for (int i = 0; i < iDims; i++)
493     {
494         bool bDeleteNeeded = false;
495         InternalType* pIT = (*_pArgsIn)[i];
496         Double *pCurrentArg = NULL;
497 
498         if (pIT->isDouble())
499         {
500             pCurrentArg = pIT->getAs<Double>();
501             if (pCurrentArg->isEmpty())
502             {
503                 return 0;
504             }
505 
506             if (pCurrentArg->isIdentity())
507             {
508                 //extract with eye() <=> :
509                 pIT = new Colon();
510                 bDeleteNeeded = true;
511             }
512             else if (pIT->isDeletable())
513             {
514                 // Clone pIT when this ref is equal to zero
515                 // will prevent double delete.
516                 pCurrentArg = pIT->clone()->getAs<Double>();
517             }
518 
519             //check valid values neg or complex
520             if (pCurrentArg->isComplex())
521             {
522                 if (pCurrentArg->isDeletable())
523                 {
524                     pCurrentArg->killMe();
525                 }
526                 pCurrentArg = NULL;
527             }
528 
529             if (pCurrentArg)
530             {
531                 int size = pCurrentArg->getSize();
532                 double* dbl = pCurrentArg->get();
533                 double minIndex = _pRef == NULL || _pRef->isList() == false ? 1 : 0;
534                 for (int j = 0; j < size; ++j)
535                 {
536                     if (dbl[j] < minIndex || std::isnan(dbl[j]))
537                     {
538                         if (pCurrentArg->isDeletable())
539                         {
540                             pCurrentArg->killMe();
541                         }
542                         pCurrentArg = NULL;
543                         break;
544                     }
545                 }
546             }
547         }
548 
549         //previous  if can update pIT to Colon
550         if (pIT->isColon() || pIT->isImplicitList())
551         {
552             //: or a:b:c
553             ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
554             if (pIL->isComputable() == false)
555             {
556                 //: or $
557                 if (_pRef == NULL)
558                 {
559                     if (pIL->getStep()->isDouble() &&
560                             ((getIndex(pIL->getStep()) > 0 && pIL->getStart()->isDouble() && getIndex(pIL->getStart()) < 1) ||
561                              (getIndex(pIL->getStep()) < 0 && pIL->getEnd()->isDouble() && getIndex(pIL->getEnd()) < 1)))
562                     {
563                         pCurrentArg = NULL;
564                     }
565                     else
566                     {
567                         //not enough information to compute indexes.
568                         _pArgsOut->push_back(NULL);
569                         bUndefine = true;
570                         pIL->killMe();
571                         continue;
572                     }
573                 }
574                 else
575                 {
576                     //evalute polynom with "MaxDim"
577                     int iMaxDim = 0;
578                     if(_pRef->isImplicitList())
579                     {
580                         ImplicitList* pIL = _pRef->getAs<ImplicitList>();
581                         iMaxDim = pIL->compute() ? pIL->getSize() : 3;
582                     }
583                     else
584                     {
585                         iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
586                     }
587 
588 #if defined(_SCILAB_DEBUGREF_)
589                     Double* pdbl = new Double(iMaxDim);
590 #else
591                     Double dbl(iMaxDim);
592 #endif
593                     if (pIL->getStart()->isPoly())
594                     {
595                         Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
596 #if defined(_SCILAB_DEBUGREF_)
597                         pIL->setStart(poPoly->evaluate(pdbl));
598 #else
599                         pIL->setStart(poPoly->evaluate(&dbl));
600 #endif
601                     }
602                     if (pIL->getStep()->isPoly())
603                     {
604                         Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
605 #if defined(_SCILAB_DEBUGREF_)
606                         pIL->setStep(poPoly->evaluate(pdbl));
607 #else
608                         pIL->setStep(poPoly->evaluate(&dbl));
609 #endif
610                     }
611                     if (pIL->getEnd()->isPoly())
612                     {
613                         Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
614 #if defined(_SCILAB_DEBUGREF_)
615                         pIL->setEnd(poPoly->evaluate(pdbl));
616 #else
617                         pIL->setEnd(poPoly->evaluate(&dbl));
618 #endif
619                     }
620 
621 #if defined(_SCILAB_DEBUGREF_)
622                     pdbl->killMe();
623 #endif
624                 }
625             }
626             if (_pRef != NULL || pIL->isComputable() == true)
627             {
628                 double start = getIndex(pIL->getStart());
629                 double step = getIndex(pIL->getStep());
630                 double end = getIndex(pIL->getEnd());
631 
632                 pCurrentArg = (start < 1 && step > 0 || end < 1 && step < 0) ? NULL : pIL->extractFullMatrix()->getAs<Double>();
633             }
634 
635             pIL->killMe();
636         }
637         else if (pIT->isString())
638         {
639             String* pStr = pIT->getAs<String>();
640             if (!_pRef)
641             {
642                 bUndefine = true;
643                 continue;
644             }
645             if (_pRef->isStruct())
646             {
647                 Struct* pStruct = _pRef->getAs<Struct>();
648 
649                 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
650                 {
651                     bUndefine = true;
652                     continue;
653                 }
654 
655                 wchar_t* pFieldName = pStr->get(0);
656 
657                 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
658                 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
659                 if (iIndex == -1)
660                 {
661                     bUndefine = true;
662                     continue;
663                 }
664 
665                 pCurrentArg = new Double((double)iIndex);
666             }
667             else if (_pRef->isTList())
668             {
669                 // List can't be extract by field and MList must call overload
670                 TList* pTL = _pRef->getAs<TList>();
671                 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
672                 double* pdbl = pCurrentArg->get();
673                 for (int i = 0; i < pStr->getSize(); i++)
674                 {
675                     wchar_t* pFieldName = pStr->get(i);
676                     int iIndex = pTL->getIndexFromString(pFieldName);
677                     if (iIndex == -1)
678                     {
679                         bUndefine = true;
680                         continue;
681                     }
682                     pdbl[i] = (double)(iIndex + 1);
683                 }
684             }
685             else if (_pRef->isList())
686             {
687                 bUndefine = true;
688                 break;
689             }
690             else if (_pRef->isCell())
691             {
692             }
693         }
694         else if (pIT->isPoly() && pIT->getAs<types::Polynom>()->getVariableName() == L"$")
695         {
696             //$
697             Polynom* pMP = pIT->getAs<types::Polynom>();
698             int iMaxDim = 0;
699             //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
700             if (_pRef && _pRef->isGenericType())
701             {
702                 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
703             }
704             else if(_pRef && _pRef->isImplicitList())
705             {
706                 ImplicitList* pIL = _pRef->getAs<ImplicitList>();
707                 // pIL is not computable, iMaxDim = 3 is the implicit list end.
708                 iMaxDim = pIL->compute() ? pIL->getSize() : 3;
709             }
710 
711 #ifdef _SCILAB_DEBUGREF_
712             Double* pdbl = new Double(iMaxDim); // $
713             pCurrentArg = pMP->evaluate(pdbl);
714             pdbl->killMe();
715 #else
716             Double dbl(iMaxDim); // $
717             pCurrentArg = pMP->evaluate(&dbl);
718 #endif
719         }
720         else if (pIT->isBool())
721         {
722             //[T F F T F]
723             Bool *pB = pIT->getAs<types::Bool>();
724             int *piB = pB->get();
725             const int size = pB->getSize();
726 
727             //find true item count
728             int iItemCount = 0;
729             for (int j = 0; j < size; j++)
730             {
731                 if (piB[j])
732                 {
733                     iItemCount++;
734                 }
735             }
736 
737             //allow new Double variable
738             Double* pDbl = new Double(1, iItemCount);
739             double* pdbl = pDbl->getReal();
740 
741             int j = 0;
742             for (int l = 0; l < size; l++)
743             {
744                 if (piB[l])
745                 {
746                     pdbl[j++] = l + 1;
747                 }
748             }
749             pCurrentArg = pDbl;
750         }
751         else if (pIT->isSparseBool())
752         {
753             types::SparseBool* pSb = pIT->getAs<types::SparseBool>();
754             int iItemCount = static_cast<int>(pSb->nbTrue());
755             int iRows = pSb->getRows();
756             int *pCoord = new int[iItemCount * 2];
757 
758             //get (r,c) positions of True Elements
759             pSb->outputRowCol(pCoord);
760             int* pY = pCoord + iItemCount;
761             //allow new Double index variable
762             Double* pDbl = new Double(1, iItemCount);
763             double* pdbl = pDbl->getReal();
764             for (int i = 0; i < iItemCount; ++i)
765             {
766                 pdbl[i] = pCoord[i] + (pY[i] - 1) * iRows;
767             }
768 
769             delete[] pCoord;
770             pCurrentArg = pDbl;
771         }
772         else if (pIT->isInt())
773         {
774             switch (pIT->getType())
775             {
776                 case InternalType::ScilabInt8:
777                 {
778                     pCurrentArg = convertIndex(pIT->getAs<Int8>());
779                     break;
780                 }
781                 case InternalType::ScilabInt16:
782                 {
783                     pCurrentArg = convertIndex(pIT->getAs<Int16>());
784                     break;
785                 }
786                 case InternalType::ScilabInt32:
787                 {
788                     pCurrentArg = convertIndex(pIT->getAs<Int32>());
789                     break;
790                 }
791                 case InternalType::ScilabInt64:
792                 {
793                     pCurrentArg = convertIndex(pIT->getAs<Int64>());
794                     break;
795                 }
796                 case InternalType::ScilabUInt8:
797                 {
798                     pCurrentArg = convertIndex(pIT->getAs<UInt8>());
799                     break;
800                 }
801                 case InternalType::ScilabUInt16:
802                 {
803                     pCurrentArg = convertIndex(pIT->getAs<UInt16>());
804                     break;
805                 }
806                 case InternalType::ScilabUInt32:
807                 {
808                     pCurrentArg = convertIndex(pIT->getAs<UInt32>());
809                     break;
810                 }
811                 case InternalType::ScilabUInt64:
812                 {
813                     pCurrentArg = convertIndex(pIT->getAs<UInt64>());
814                     break;
815                 }
816             }
817         }
818 
819         if (bDeleteNeeded)
820         {
821             pIT->killMe();
822         }
823 
824         if (pCurrentArg)
825         {
826             const int iCountDim = pCurrentArg->getSize();
827             _piMaxDim[i] = 0;
828             for (int j = 0; j < iCountDim; j++)
829             {
830                 //checks if size < size(int)
831                 if (pCurrentArg->get(j) >= INT_MAX)
832                 {
833                     wchar_t szError[bsiz];
834                     os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
835 
836                     throw ast::InternalError(szError);
837                 }
838 
839                 int d = static_cast<int>(pCurrentArg->get(j));
840                 if (d > _piMaxDim[i])
841                 {
842                     _piMaxDim[i] = d;
843                 }
844             }
845 
846             iSeqCount *= iCountDim;
847             if (_piCountDim)
848             {
849                 _piCountDim[i] = iCountDim;
850             }
851         }
852         else
853         {
854             wchar_t szError[bsiz];
855             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
856 
857             delete[] _piMaxDim;
858             if (_piCountDim)
859             {
860                 delete[] _piCountDim;
861             }
862             cleanIndexesArguments(_pArgsIn, _pArgsOut);
863 
864             // Location(-1,-1,-1,-1): it means the locations are unknown at the throw time,
865             // this can be use to set the locations in the first catch which know them.
866             throw ast::InternalError(szError, 999, Location(-1,-1,-1,-1));
867         }
868 
869         _pArgsOut->push_back(pCurrentArg);
870     }
871 
872     //return 0 to force extract to create an empty matrix
873     if (_pRef && (_pRef->isDouble() && _pRef->getAs<Double>()->isEmpty()))
874     {
875         return 0;
876     }
877 
878     //returns a negative value if at least one parameter is undefined
879     //case with : or $ for creation by insertion
880     return (!bUndefine ? iSeqCount : -iSeqCount);
881 }
882 
cleanIndexesArguments(typed_list * _pArgsOrig,typed_list * _pArgsNew)883 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
884 {
885     if (_pArgsNew)
886     {
887         //free pArg content
888         for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
889         {
890             if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
891             {
892                 if ((*_pArgsNew)[iArg])
893                 {
894                     (*_pArgsNew)[iArg]->killMe();
895                 }
896             }
897         }
898 
899         _pArgsNew->clear();
900     }
901 }
902 
getIndexesWithDims(int _iIndex,int * _piIndexes,const int * _piDims,int _iDims)903 void getIndexesWithDims(int _iIndex, int* _piIndexes, const int* _piDims, int _iDims)
904 {
905     int iMul = 1;
906     for (int i = 0; i < _iDims; i++)
907     {
908         _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
909         iMul *= _piDims[i];
910     }
911 
912     //matrix [2,4,3]
913     //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
914     //loop 1
915     // (12 / 1) % 2 -> 0
916     //loop 2
917     // (12 / 2) % 4 -> 2
918     //loop 3
919     // (12 / 8) % 3 -> 1
920 
921     //matrix [3,4,3]
922     //index = 22
923     //loop 1
924     // (22 / 1) % 3 -> 1
925     //loop 2
926     // (22 / 3) % 4 -> 3
927     //loop 3
928     // (22 / 12) % 3 -> 1
929 
930     //matrix [3,4,3]
931     //index = 35
932     //loop 1
933     // (35 / 1) % 3 -> 2
934     //loop 2
935     // (35 / 3) % 4 -> 3
936     //loop 3
937     // (35 / 12) % 3 -> 2
938 }
939 
940 
getIndexWithDims(int * _piIndexes,const int * _piDims,int _iDims)941 int getIndexWithDims(int* _piIndexes, const int* _piDims, int _iDims)
942 {
943     int idx = 0;
944     int iMult = 1;
945     for (int i = 0; i < _iDims; i++)
946     {
947         idx += _piIndexes[i] * iMult;
948         iMult *= _piDims[i];
949     }
950     return idx;
951 }
952 
VariableToString(types::InternalType * pIT,const wchar_t * wcsVarName)953 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
954 {
955     if (pIT->hasToString() == false)
956     {
957         types::Function::ReturnValue ret = types::Function::Error;
958         //call overload %type_p
959         types::typed_list in;
960         types::typed_list out;
961 
962         pIT->IncreaseRef();
963         in.push_back(pIT);
964 
965         try
966         {
967             ret = Overload::generateNameAndCall(L"p", in, 1, out);
968             pIT->DecreaseRef();
969             return ret;
970         }
971         catch (const ast::InternalError &ie)
972         {
973             pIT->DecreaseRef();
974             throw ie;
975         }
976     }
977     else
978     {
979         std::wostringstream ostr;
980         if (pIT->isFunction())
981         {
982             pIT->getAs<types::Function>()->toString(ostr);
983         }
984         else if (pIT->isList() || pIT->isCallable())
985         {
986             ostr << wcsVarName;
987         }
988 
989         //to manage lines information
990         int iLines = ConfigVariable::getConsoleLines();
991 
992         bool bFinish = false;
993         do
994         {
995             //block by block
996             bFinish = pIT->toString(ostr);
997             if (ConfigVariable::isError())
998             {
999                 ConfigVariable::resetError();
1000                 ostr.str(L"");
1001                 ConfigVariable::resetExecutionBreak();
1002                 return types::Function::Error;
1003             }
1004 
1005             if (bFinish == false && iLines != 0)
1006             {
1007                 //show message on prompt
1008                 bFinish = linesmore() == 1;
1009             }
1010 
1011             scilabForcedWriteW(ostr.str().c_str());
1012             ostr.str(L"");
1013         }
1014         while (bFinish == false && ConfigVariable::isExecutionBreak() == false);
1015 
1016         if (bFinish == false)
1017         {
1018             ConfigVariable::resetExecutionBreak();
1019         }
1020         pIT->clearPrintState();
1021         return types::Function::OK;
1022     }
1023 }
1024 
1025 //n-uplet in french
computeTuples(int * _piCountDim,int _iDims,int _iCurrentDim,int * _piIndex)1026 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
1027 {
1028     //if bRet == 1, previous dims has reach max value.
1029     int iRet = 0;
1030 
1031     if (_iCurrentDim == 0)
1032     {
1033         //last dims
1034         if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1035         {
1036             _piIndex[_iCurrentDim] = 0;
1037             return 1;
1038         }
1039     }
1040     else
1041     {
1042         iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
1043         if (iRet)
1044         {
1045             _piIndex[_iCurrentDim]++;
1046             if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1047             {
1048                 _piIndex[_iCurrentDim] = 0;
1049                 return 1;
1050             }
1051         }
1052     }
1053     return 0;
1054 }
1055 
createEmptyDouble()1056 Double* createEmptyDouble()
1057 {
1058     return Double::Empty();
1059 }
1060 
getIntValueFromDouble(InternalType * _pIT,int _iPos)1061 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
1062 {
1063     return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
1064 }
1065 
getDoubleArrayFromDouble(InternalType * _pIT)1066 double* getDoubleArrayFromDouble(InternalType* _pIT)
1067 {
1068     return _pIT->getAs<Double>()->get();
1069 }
1070 
createDoubleVector(int _iSize)1071 Double* createDoubleVector(int _iSize)
1072 {
1073     int piDims[] = {1, _iSize};
1074     Double* pOut = new Double(2, piDims);
1075     for (int i = 0; i < _iSize; i++)
1076     {
1077         pOut->set(i, i + 1);
1078     }
1079     return pOut;
1080 }
1081 
checkArgValidity(typed_list & _Arg)1082 bool checkArgValidity(typed_list& _Arg)
1083 {
1084     for (int i = 0; i < (int)_Arg.size(); i++)
1085     {
1086         if (_Arg[i]->isDouble() == false)
1087         {
1088             return false;
1089         }
1090 
1091         Double* pDbl = _Arg[i]->getAs<Double>();
1092         double* pdbl = pDbl->get();
1093         for (int j = 0; j < pDbl->getSize(); j++)
1094         {
1095             if (pdbl[j] <= 0)
1096             {
1097                 return false;
1098             }
1099         }
1100     }
1101 
1102     return true;
1103 }
1104 
1105 }
1106