4b945801b68d791aedc84caa3310aaada81152eb
[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->isInt())
698         {
699             switch (pIT->getType())
700             {
701                 case InternalType::ScilabInt8:
702                 {
703                     pCurrentArg = convertIndex(pIT->getAs<Int8>());
704                     break;
705                 }
706                 case InternalType::ScilabInt16:
707                 {
708                     pCurrentArg = convertIndex(pIT->getAs<Int16>());
709                     break;
710                 }
711                 case InternalType::ScilabInt32:
712                 {
713                     pCurrentArg = convertIndex(pIT->getAs<Int32>());
714                     break;
715                 }
716                 case InternalType::ScilabInt64:
717                 {
718                     pCurrentArg = convertIndex(pIT->getAs<Int64>());
719                     break;
720                 }
721                 case InternalType::ScilabUInt8:
722                 {
723                     pCurrentArg = convertIndex(pIT->getAs<UInt8>());
724                     break;
725                 }
726                 case InternalType::ScilabUInt16:
727                 {
728                     pCurrentArg = convertIndex(pIT->getAs<UInt16>());
729                     break;
730                 }
731                 case InternalType::ScilabUInt32:
732                 {
733                     pCurrentArg = convertIndex(pIT->getAs<UInt32>());
734                     break;
735                 }
736                 case InternalType::ScilabUInt64:
737                 {
738                     pCurrentArg = convertIndex(pIT->getAs<UInt64>());
739                     break;
740                 }
741             }
742         }
743
744         if (bDeleteNeeded)
745         {
746             pIT->killMe();
747         }
748
749         if (pCurrentArg)
750         {
751             const int iCountDim = pCurrentArg->getSize();
752             _piMaxDim[i] = 0;
753             for (int j = 0; j < iCountDim; j++)
754             {
755                 //checks if size < size(int)
756                 if (pCurrentArg->get(j) >= INT_MAX)
757                 {
758                     wchar_t szError[bsiz];
759                     os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
760                     throw ast::InternalError(szError);
761                 }
762
763                 int d = static_cast<int>(pCurrentArg->get(j));
764                 if (d > _piMaxDim[i])
765                 {
766                     _piMaxDim[i] = d;
767                 }
768             }
769
770             iSeqCount *= iCountDim;
771             if (_piCountDim)
772             {
773                 _piCountDim[i] = iCountDim;
774             }
775         }
776         else
777         {
778             wchar_t szError[bsiz];
779             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
780
781             delete[] _piMaxDim;
782             delete[] _piCountDim;
783             cleanIndexesArguments(_pArgsIn, _pArgsOut);
784
785             throw ast::InternalError(szError);
786         }
787         _pArgsOut->push_back(pCurrentArg);
788
789     }
790
791
792     //return 0 to force extract to create an empty matrix
793     if (_pRef &&
794             (_pRef->isDouble() && _pRef->getAs<Double>()->isEmpty()))
795     {
796         return 0;
797     }
798
799     //returns a negative value if at least one parameter is undefined
800     //case with : or $ for creation by insertion
801     return (!bUndefine ? iSeqCount : -iSeqCount);
802 }
803
804 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
805 {
806     if (_pArgsNew)
807     {
808         //free pArg content
809         for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
810         {
811             if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
812             {
813                 if ((*_pArgsNew)[iArg])
814                 {
815                     (*_pArgsNew)[iArg]->killMe();
816                 }
817             }
818         }
819
820         _pArgsNew->clear();
821     }
822 }
823
824 void getIndexesWithDims(int _iIndex, int* _piIndexes, const int* _piDims, int _iDims)
825 {
826     int iMul = 1;
827     for (int i = 0; i < _iDims; i++)
828     {
829         _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
830         iMul *= _piDims[i];
831     }
832
833     //matrix [2,4,3]
834     //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
835     //loop 1
836     // (12 / 1) % 2 -> 0
837     //loop 2
838     // (12 / 2) % 4 -> 2
839     //loop 3
840     // (12 / 8) % 3 -> 1
841
842     //matrix [3,4,3]
843     //index = 22
844     //loop 1
845     // (22 / 1) % 3 -> 1
846     //loop 2
847     // (22 / 3) % 4 -> 3
848     //loop 3
849     // (22 / 12) % 3 -> 1
850
851     //matrix [3,4,3]
852     //index = 35
853     //loop 1
854     // (35 / 1) % 3 -> 2
855     //loop 2
856     // (35 / 3) % 4 -> 3
857     //loop 3
858     // (35 / 12) % 3 -> 2
859 }
860
861
862 int getIndexWithDims(int* _piIndexes, const int* _piDims, int _iDims)
863 {
864     int idx = 0;
865     int iMult = 1;
866     for (int i = 0; i < _iDims; i++)
867     {
868         idx += _piIndexes[i] * iMult;
869         iMult *= _piDims[i];
870     }
871     return idx;
872 }
873
874 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
875 {
876     if (pIT->hasToString() == false)
877     {
878         types::Function::ReturnValue ret = types::Function::Error;
879         //call overload %type_p
880         types::typed_list in;
881         types::typed_list out;
882
883         pIT->IncreaseRef();
884         in.push_back(pIT);
885
886         try
887         {
888             ret = Overload::generateNameAndCall(L"p", in, 1, out);
889             pIT->DecreaseRef();
890             return ret;
891         }
892         catch (const ast::InternalError &ie)
893         {
894             pIT->DecreaseRef();
895             throw ie;
896         }
897     }
898     else
899     {
900         std::wostringstream ostr;
901         if (pIT->isFunction())
902         {
903             pIT->getAs<types::Function>()->toString(ostr);
904         }
905         else if (pIT->isList() || pIT->isCallable())
906         {
907             ostr << wcsVarName;
908         }
909
910         //to manage lines information
911         int iLines = ConfigVariable::getConsoleLines();
912
913         bool bFinish = false;
914         do
915         {
916             //block by block
917             bFinish = pIT->toString(ostr);
918             if (ConfigVariable::isError())
919             {
920                 ConfigVariable::resetError();
921                 ostr.str(L"");
922                 ConfigVariable::resetExecutionBreak();
923                 return types::Function::Error;
924             }
925
926             if (bFinish == false && iLines != 0)
927             {
928                 //show message on prompt
929                 bFinish = linesmore() == 1;
930             }
931
932             if (ConfigVariable::isPrintCompact() == false && ConfigVariable::isPrintInput() == false)
933             {
934                 ostr << std::endl;
935             }
936
937             scilabForcedWriteW(ostr.str().c_str());
938             ostr.str(L"");
939         }
940         while (bFinish == false && ConfigVariable::isExecutionBreak() == false);
941
942         if (bFinish == false)
943         {
944             ConfigVariable::resetExecutionBreak();
945         }
946         pIT->clearPrintState();
947         return types::Function::OK;
948     }
949 }
950
951 //n-uplet in french
952 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
953 {
954     //if bRet == 1, previous dims has reach max value.
955     int iRet = 0;
956
957     if (_iCurrentDim == 0)
958     {
959         //last dims
960         if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
961         {
962             _piIndex[_iCurrentDim] = 0;
963             return 1;
964         }
965     }
966     else
967     {
968         iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
969         if (iRet)
970         {
971             _piIndex[_iCurrentDim]++;
972             if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
973             {
974                 _piIndex[_iCurrentDim] = 0;
975                 return 1;
976             }
977         }
978     }
979     return 0;
980 }
981
982 Double* createEmptyDouble()
983 {
984     return Double::Empty();
985 }
986
987 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
988 {
989     return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
990 }
991
992 double* getDoubleArrayFromDouble(InternalType* _pIT)
993 {
994     return _pIT->getAs<Double>()->get();
995 }
996
997 Double* createDoubleVector(int _iSize)
998 {
999     int piDims[] = {1, _iSize};
1000     Double* pOut = new Double(2, piDims);
1001     for (int i = 0; i < _iSize; i++)
1002     {
1003         pOut->set(i, i + 1);
1004     }
1005     return pOut;
1006 }
1007
1008 bool checkArgValidity(typed_list& _Arg)
1009 {
1010     for (int i = 0; i < (int)_Arg.size(); i++)
1011     {
1012         if (_Arg[i]->isDouble() == false)
1013         {
1014             return false;
1015         }
1016
1017         Double* pDbl = _Arg[i]->getAs<Double>();
1018         double* pdbl = pDbl->get();
1019         for (int j = 0; j < pDbl->getSize(); j++)
1020         {
1021             if (pdbl[j] <= 0)
1022             {
1023                 return false;
1024             }
1025         }
1026     }
1027
1028     return true;
1029 }
1030
1031 }