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