* Bug 15630 fixed: now x(0:2)=1 and x=1;x(0:1,1) raise an error
[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         double start = evalute(pIL->getStart(), sizeRef);
289         double step = evalute(pIL->getStep(), sizeRef);
290         double end = evalute(pIL->getEnd(), sizeRef);
291
292         if ((start < 1 && step > 0) || (end < 1 & step < 0))
293         {
294             wchar_t szError[bsiz];
295             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
296             throw ast::InternalError(szError);
297         }
298
299         index.push_back(start);
300         index.push_back(step);
301         index.push_back(end);
302     }
303
304     return true;
305 }
306
307 //get index from implicit or colon index + scalar
308 bool getImplicitIndex(GenericType* _pRef, typed_list* _pArgsIn, std::vector<int>& index, std::vector<int>& dims)
309 {
310     int dimsRef = _pRef->getDims();
311     int dimsIn = static_cast<int>(_pArgsIn->size());
312     bool viewAsVector = dimsIn == 1;
313     dims.reserve(dimsIn);
314     //same dims and less than internal limit
315     if (dimsIn != 1 && (dimsIn != dimsRef || dimsIn > MAX_DIMS))
316     {
317         return false;
318     }
319
320     int* pdims = _pRef->getDimsArray();
321     //input arg type must be computable ( double, $, :, ... )
322     std::list<std::vector<int>> lstIdx;
323     int finalSize = 1;
324     for (int i = 0; i < dimsIn; ++i)
325     {
326         InternalType* in = (*_pArgsIn)[i];
327         if (in->isGenericType() && in->getAs<GenericType>()->isScalar())
328         {
329             int idx = static_cast<int>(getIndex(in)) - 1;
330             if (idx < 0)
331             {
332                 return false;
333             }
334
335             lstIdx.emplace_back(1, idx);
336             dims.push_back(1);
337         }
338         else if (in->isColon())
339         {
340             std::vector<int> idx(2);
341             idx[0] = -1;
342             idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
343             lstIdx.push_back(idx);
344             finalSize *= idx[1];
345             dims.push_back(idx[1]);
346         }
347         else if (in->isImplicitList())
348         {
349             ImplicitList* pIL = in->getAs<ImplicitList>();
350             InternalType* piStart = pIL->getStart();
351             InternalType* piStep = pIL->getStep();
352             InternalType* piEnd = pIL->getEnd();
353
354             bool isColon = false;
355             if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
356             {
357                 if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
358                 {
359                     SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
360                     if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
361                     {
362                         std::vector<int> idx(2);
363                         idx[0] = -1;
364                         idx[1] = viewAsVector ? _pRef->getSize() : pdims[i];
365                         lstIdx.push_back(idx);
366                         finalSize *= idx[1];
367                         isColon = true;
368                         dims.push_back(idx[1]);
369                     }
370                 }
371             }
372
373             if (isColon == false)
374             {
375                 int sizeRef = viewAsVector ? _pRef->getSize() : pdims[i];
376                 double start = evalute(pIL->getStart(), sizeRef);
377                 double step = evalute(pIL->getStep(), sizeRef);
378                 double end = evalute(pIL->getEnd(), sizeRef);
379
380                 int size = (end - start) / step + 1;
381                 if (size <= 0)
382                 {
383                     //manage implicit that return []
384                     index.clear();
385                     return true;
386                 }
387
388                 std::vector<int> idx(size);
389
390                 if ((start < 1 && step > 0) || (end < 1 & step < 0))
391                 {
392                     wchar_t szError[bsiz];
393                     os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
394                     throw ast::InternalError(szError);
395                 }
396
397                 double val = start - 1;
398                 std::generate(idx.begin(), idx.end(), [&val, step]{ double s = val; val += step; return (int)s; });
399
400                 lstIdx.push_back(idx);
401                 finalSize *= size;
402                 dims.push_back(size);
403             }
404         }
405         else
406         {
407             return false;
408         }
409     }
410
411     index.resize(finalSize, 0);
412
413     if (finalSize == 0)
414     {
415         return true;
416     }
417
418     //compute tuples
419     int previousSize = 1;
420     int currentDim = 0;
421     int previousDims = 1;
422     int* p = index.data();
423     while (lstIdx.empty() == false)
424     {
425         std::vector<int>& v = lstIdx.front();
426         int currentSize = static_cast<int>(v.size());
427         const int* pv = v.data();
428
429         if (pv[0] == -1 && currentSize == 2)
430         {
431             currentSize = pv[1];
432             int occ = finalSize / (currentSize * previousSize);
433             for (int n = 0; n < occ; ++n)
434             {
435                 int idx = currentSize * previousSize * n;
436                 for (int m = 0; m < currentSize; ++m)
437                 {
438                     if (dimsIn > 1 && m >= pdims[currentDim])
439                     {
440                         return false;
441                     }
442                     int idx2 = idx + previousSize * m;
443                     int idx3 = previousDims * m;
444                     for (int j = 0; j < previousSize; ++j)
445                     {
446                         p[idx2 + j] += idx3;
447                     }
448                 }
449             }
450         }
451         else
452         {
453             int* p = index.data();
454             int occ = finalSize / (currentSize * previousSize);
455             for (int n = 0; n < occ; ++n)
456             {
457                 int idx = currentSize * previousSize * n;
458                 for (int m = 0; m < currentSize; ++m)
459                 {
460                     if (dimsIn > 1 && pv[m] >= pdims[currentDim])
461                     {
462                         return false;
463                     }
464                     int idx2 = idx + previousSize * m;
465                     int idx3 = previousDims * pv[m];
466                     for (int j = 0; j < previousSize; ++j)
467                     {
468                         p[idx2 + j] += idx3;
469                     }
470                 }
471             }
472         }
473
474         previousSize *= currentSize;
475         previousDims *= pdims[currentDim];
476         ++currentDim;
477         //remove used vector
478         lstIdx.pop_front();
479     }
480
481     return true;
482 }
483
484 //check argument types and compute, dimensions, count of combinations, max indexes
485 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
486 {
487     int iDims = static_cast<int>(_pArgsIn->size());
488     int iSeqCount = 1;
489     bool bUndefine = false;
490
491     for (int i = 0; i < iDims; i++)
492     {
493         bool bDeleteNeeded = false;
494         InternalType* pIT = (*_pArgsIn)[i];
495         Double *pCurrentArg = NULL;
496
497         if (pIT->isDouble())
498         {
499             pCurrentArg = pIT->getAs<Double>();
500             if (pCurrentArg->isEmpty())
501             {
502                 return 0;
503             }
504
505             if (pCurrentArg->isIdentity())
506             {
507                 //extract with eye() <=> :
508                 pIT = new Colon();
509                 bDeleteNeeded = true;
510             }
511             else if (pIT->isDeletable())
512             {
513                 // Clone pIT when this ref is equal to zero
514                 // will prevent double delete.
515                 pCurrentArg = pIT->clone()->getAs<Double>();
516             }
517
518             //check valid values neg or complex
519             if (pCurrentArg->isComplex())
520             {
521                 if (pCurrentArg->isDeletable())
522                 {
523                     pCurrentArg->killMe();
524                 }
525                 pCurrentArg = NULL;
526             }
527
528             if (pCurrentArg)
529             {
530                 int size = pCurrentArg->getSize();
531                 double* dbl = pCurrentArg->get();
532                 double minIndex = _pRef==NULL || _pRef->isList()==false ? 1 : 0;
533                 for (int j = 0; j < size; ++j)
534                 {
535                     if (dbl[j] < minIndex)
536                     {
537                         if (pCurrentArg->isDeletable())
538                         {
539                             pCurrentArg->killMe();
540                         }
541                         pCurrentArg = NULL;
542                         break;
543                     }
544                 }
545             }
546         }
547
548         //previous  if can update pIT to Colon
549         if (pIT->isColon() || pIT->isImplicitList())
550         {
551             //: or a:b:c
552             ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
553             if (pIL->isComputable() == false)
554             {
555                 //: or $
556                 if (_pRef == NULL)
557                 {
558                     if (pIL->getStep()->isDouble() &&
559                         ((getIndex(pIL->getStep()) > 0 && pIL->getStart()->isDouble() && getIndex(pIL->getStart()) < 1) ||
560                         (getIndex(pIL->getStep()) < 0 && pIL->getEnd()->isDouble() && getIndex(pIL->getEnd()) < 1)))
561                     {
562                         pCurrentArg = NULL;
563                     }
564                     else
565                     {
566                         //not enough information to compute indexes.
567                         _pArgsOut->push_back(NULL);
568                         bUndefine = true;
569                         pIL->killMe();
570                         continue;
571                     }
572                 }
573                 else
574                 {        //evalute polynom with "MaxDim"
575                     int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
576     #if defined(_SCILAB_DEBUGREF_)
577                     Double* pdbl = new Double(iMaxDim);
578     #else
579                     Double dbl(iMaxDim);
580     #endif
581                     if (pIL->getStart()->isPoly())
582                     {
583                         Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
584     #if defined(_SCILAB_DEBUGREF_)
585                         pIL->setStart(poPoly->evaluate(pdbl));
586     #else
587                         pIL->setStart(poPoly->evaluate(&dbl));
588     #endif
589                     }
590                     if (pIL->getStep()->isPoly())
591                     {
592                         Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
593     #if defined(_SCILAB_DEBUGREF_)
594                         pIL->setStep(poPoly->evaluate(pdbl));
595     #else
596                         pIL->setStep(poPoly->evaluate(&dbl));
597     #endif
598                     }
599                     if (pIL->getEnd()->isPoly())
600                     {
601                         Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
602     #if defined(_SCILAB_DEBUGREF_)
603                         pIL->setEnd(poPoly->evaluate(pdbl));
604     #else
605                         pIL->setEnd(poPoly->evaluate(&dbl));
606     #endif
607                     }
608
609     #if defined(_SCILAB_DEBUGREF_)
610                     pdbl->killMe();
611 #endif
612                 }
613             }
614             if (_pRef != NULL || pIL->isComputable() == true)
615             {
616                 double start = getIndex(pIL->getStart());
617                 double step = getIndex(pIL->getStep());
618                 double end = getIndex(pIL->getEnd());
619
620                 pCurrentArg = ((start < 1 && step > 0) || (end < 1 & step < 0)) ? NULL : pIL->extractFullMatrix()->getAs<Double>();
621             }
622
623             pIL->killMe();
624         }
625         else if (pIT->isString())
626         {
627             String* pStr = pIT->getAs<String>();
628             if(!_pRef)
629             {
630                 bUndefine = true;
631                 continue;
632             }
633             if (_pRef->isStruct())
634             {
635                 Struct* pStruct = _pRef->getAs<Struct>();
636
637                 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
638                 {
639                     bUndefine = true;
640                     continue;
641                 }
642
643                 wchar_t* pFieldName = pStr->get(0);
644
645                 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
646                 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
647                 if (iIndex == -1)
648                 {
649                     bUndefine = true;
650                     continue;
651                 }
652
653                 pCurrentArg = new Double((double)iIndex);
654             }
655             else if (_pRef->isTList())
656             {
657                 // List can't be extract by field and MList must call overload
658                 TList* pTL = _pRef->getAs<TList>();
659                 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
660                 double* pdbl = pCurrentArg->get();
661                 for (int i = 0; i < pStr->getSize(); i++)
662                 {
663                     wchar_t* pFieldName = pStr->get(i);
664                     int iIndex = pTL->getIndexFromString(pFieldName);
665                     if (iIndex == -1)
666                     {
667                         bUndefine = true;
668                         continue;
669                     }
670                     pdbl[i] = (double)(iIndex + 1);
671                 }
672             }
673             else if (_pRef->isList())
674             {
675                 bUndefine = true;
676                 break;
677             }
678             else if (_pRef->isCell())
679             {
680             }
681         }
682         else if (pIT->isPoly())
683         {
684             //$
685             Polynom* pMP = pIT->getAs<types::Polynom>();
686             int iMaxDim = 0;
687             //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
688             if (_pRef)
689             {
690                 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
691             }
692
693 #ifdef _SCILAB_DEBUGREF_
694             Double* pdbl = new Double(iMaxDim); // $
695             pCurrentArg = pMP->evaluate(pdbl);
696             pdbl->killMe();
697 #else
698             Double dbl(iMaxDim); // $
699             pCurrentArg = pMP->evaluate(&dbl);
700 #endif
701         }
702         else if (pIT->isBool())
703         {
704             //[T F F T F]
705             Bool *pB = pIT->getAs<types::Bool>();
706             int *piB = pB->get();
707             const int size = pB->getSize();
708
709             //find true item count
710             int iItemCount = 0;
711             for (int j = 0; j < size; j++)
712             {
713                 if (piB[j])
714                 {
715                     iItemCount++;
716                 }
717             }
718
719             //allow new Double variable
720             Double* pDbl = new Double(1, iItemCount);
721             double* pdbl = pDbl->getReal();
722
723             int j = 0;
724             for (int l = 0; l < size; l++)
725             {
726                 if (piB[l])
727                 {
728                     pdbl[j++] = l + 1;
729                 }
730             }
731             pCurrentArg = pDbl;
732         }
733         else if (pIT->isSparseBool())
734         {
735             types::SparseBool* pSb = pIT->getAs<types::SparseBool>();
736             int iItemCount = static_cast<int>(pSb->nbTrue());
737             int iRows = pSb->getRows();
738             int *pCoord = new int[iItemCount * 2];
739
740             //get (r,c) positions of True Elements
741             pSb->outputRowCol(pCoord);
742             int* pY = pCoord + iItemCount;
743             //allow new Double index variable
744             Double* pDbl = new Double(1, iItemCount);
745             double* pdbl = pDbl->getReal();
746             for (int i = 0; i < iItemCount; ++i)
747             {
748                 pdbl[i] = pCoord[i] + (pY[i] - 1) * iRows;
749             }
750
751             pCurrentArg = pDbl;
752         }
753         else if (pIT->isInt())
754         {
755             switch (pIT->getType())
756             {
757                 case InternalType::ScilabInt8:
758                 {
759                     pCurrentArg = convertIndex(pIT->getAs<Int8>());
760                     break;
761                 }
762                 case InternalType::ScilabInt16:
763                 {
764                     pCurrentArg = convertIndex(pIT->getAs<Int16>());
765                     break;
766                 }
767                 case InternalType::ScilabInt32:
768                 {
769                     pCurrentArg = convertIndex(pIT->getAs<Int32>());
770                     break;
771                 }
772                 case InternalType::ScilabInt64:
773                 {
774                     pCurrentArg = convertIndex(pIT->getAs<Int64>());
775                     break;
776                 }
777                 case InternalType::ScilabUInt8:
778                 {
779                     pCurrentArg = convertIndex(pIT->getAs<UInt8>());
780                     break;
781                 }
782                 case InternalType::ScilabUInt16:
783                 {
784                     pCurrentArg = convertIndex(pIT->getAs<UInt16>());
785                     break;
786                 }
787                 case InternalType::ScilabUInt32:
788                 {
789                     pCurrentArg = convertIndex(pIT->getAs<UInt32>());
790                     break;
791                 }
792                 case InternalType::ScilabUInt64:
793                 {
794                     pCurrentArg = convertIndex(pIT->getAs<UInt64>());
795                     break;
796                 }
797             }
798         }
799
800         if (bDeleteNeeded)
801         {
802             pIT->killMe();
803         }
804
805         if (pCurrentArg)
806         {
807             const int iCountDim = pCurrentArg->getSize();
808             _piMaxDim[i] = 0;
809             for (int j = 0; j < iCountDim; j++)
810             {
811                 //checks if size < size(int)
812                 if (pCurrentArg->get(j) >= INT_MAX)
813                 {
814                     wchar_t szError[bsiz];
815                     os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
816                     throw ast::InternalError(szError);
817                 }
818
819                 int d = static_cast<int>(pCurrentArg->get(j));
820                 if (d > _piMaxDim[i])
821                 {
822                     _piMaxDim[i] = d;
823                 }
824             }
825
826             iSeqCount *= iCountDim;
827             if (_piCountDim)
828             {
829                 _piCountDim[i] = iCountDim;
830             }
831         }
832         else
833         {
834             wchar_t szError[bsiz];
835             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
836
837             delete[] _piMaxDim;
838             delete[] _piCountDim;
839             cleanIndexesArguments(_pArgsIn, _pArgsOut);
840
841             throw ast::InternalError(szError);
842         }
843         _pArgsOut->push_back(pCurrentArg);
844
845     }
846
847
848     //return 0 to force extract to create an empty matrix
849     if (_pRef &&
850             (_pRef->isDouble() && _pRef->getAs<Double>()->isEmpty()))
851     {
852         return 0;
853     }
854
855     //returns a negative value if at least one parameter is undefined
856     //case with : or $ for creation by insertion
857     return (!bUndefine ? iSeqCount : -iSeqCount);
858 }
859
860 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
861 {
862     if (_pArgsNew)
863     {
864         //free pArg content
865         for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
866         {
867             if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
868             {
869                 if ((*_pArgsNew)[iArg])
870                 {
871                     (*_pArgsNew)[iArg]->killMe();
872                 }
873             }
874         }
875
876         _pArgsNew->clear();
877     }
878 }
879
880 void getIndexesWithDims(int _iIndex, int* _piIndexes, const int* _piDims, int _iDims)
881 {
882     int iMul = 1;
883     for (int i = 0; i < _iDims; i++)
884     {
885         _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
886         iMul *= _piDims[i];
887     }
888
889     //matrix [2,4,3]
890     //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
891     //loop 1
892     // (12 / 1) % 2 -> 0
893     //loop 2
894     // (12 / 2) % 4 -> 2
895     //loop 3
896     // (12 / 8) % 3 -> 1
897
898     //matrix [3,4,3]
899     //index = 22
900     //loop 1
901     // (22 / 1) % 3 -> 1
902     //loop 2
903     // (22 / 3) % 4 -> 3
904     //loop 3
905     // (22 / 12) % 3 -> 1
906
907     //matrix [3,4,3]
908     //index = 35
909     //loop 1
910     // (35 / 1) % 3 -> 2
911     //loop 2
912     // (35 / 3) % 4 -> 3
913     //loop 3
914     // (35 / 12) % 3 -> 2
915 }
916
917
918 int getIndexWithDims(int* _piIndexes, const int* _piDims, int _iDims)
919 {
920     int idx = 0;
921     int iMult = 1;
922     for (int i = 0; i < _iDims; i++)
923     {
924         idx += _piIndexes[i] * iMult;
925         iMult *= _piDims[i];
926     }
927     return idx;
928 }
929
930 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
931 {
932     if (pIT->hasToString() == false)
933     {
934         types::Function::ReturnValue ret = types::Function::Error;
935         //call overload %type_p
936         types::typed_list in;
937         types::typed_list out;
938
939         pIT->IncreaseRef();
940         in.push_back(pIT);
941
942         try
943         {
944             ret = Overload::generateNameAndCall(L"p", in, 1, out);
945             pIT->DecreaseRef();
946             return ret;
947         }
948         catch (const ast::InternalError &ie)
949         {
950             pIT->DecreaseRef();
951             throw ie;
952         }
953     }
954     else
955     {
956         std::wostringstream ostr;
957         if (pIT->isFunction())
958         {
959             pIT->getAs<types::Function>()->toString(ostr);
960         }
961         else if (pIT->isList() || pIT->isCallable())
962         {
963             ostr << wcsVarName;
964         }
965
966         //to manage lines information
967         int iLines = ConfigVariable::getConsoleLines();
968
969         bool bFinish = false;
970         do
971         {
972             //block by block
973             bFinish = pIT->toString(ostr);
974             if (ConfigVariable::isError())
975             {
976                 ConfigVariable::resetError();
977                 ostr.str(L"");
978                 ConfigVariable::resetExecutionBreak();
979                 return types::Function::Error;
980             }
981
982             if (bFinish == false && iLines != 0)
983             {
984                 //show message on prompt
985                 bFinish = linesmore() == 1;
986             }
987
988             if (ConfigVariable::isPrintCompact() == false && ConfigVariable::isPrintInput() == false)
989             {
990                 ostr << std::endl;
991             }
992
993             scilabForcedWriteW(ostr.str().c_str());
994             ostr.str(L"");
995         }
996         while (bFinish == false && ConfigVariable::isExecutionBreak() == false);
997
998         if (bFinish == false)
999         {
1000             ConfigVariable::resetExecutionBreak();
1001         }
1002         pIT->clearPrintState();
1003         return types::Function::OK;
1004     }
1005 }
1006
1007 //n-uplet in french
1008 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
1009 {
1010     //if bRet == 1, previous dims has reach max value.
1011     int iRet = 0;
1012
1013     if (_iCurrentDim == 0)
1014     {
1015         //last dims
1016         if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1017         {
1018             _piIndex[_iCurrentDim] = 0;
1019             return 1;
1020         }
1021     }
1022     else
1023     {
1024         iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
1025         if (iRet)
1026         {
1027             _piIndex[_iCurrentDim]++;
1028             if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1029             {
1030                 _piIndex[_iCurrentDim] = 0;
1031                 return 1;
1032             }
1033         }
1034     }
1035     return 0;
1036 }
1037
1038 Double* createEmptyDouble()
1039 {
1040     return Double::Empty();
1041 }
1042
1043 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
1044 {
1045     return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
1046 }
1047
1048 double* getDoubleArrayFromDouble(InternalType* _pIT)
1049 {
1050     return _pIT->getAs<Double>()->get();
1051 }
1052
1053 Double* createDoubleVector(int _iSize)
1054 {
1055     int piDims[] = {1, _iSize};
1056     Double* pOut = new Double(2, piDims);
1057     for (int i = 0; i < _iSize; i++)
1058     {
1059         pOut->set(i, i + 1);
1060     }
1061     return pOut;
1062 }
1063
1064 bool checkArgValidity(typed_list& _Arg)
1065 {
1066     for (int i = 0; i < (int)_Arg.size(); i++)
1067     {
1068         if (_Arg[i]->isDouble() == false)
1069         {
1070             return false;
1071         }
1072
1073         Double* pDbl = _Arg[i]->getAs<Double>();
1074         double* pdbl = pDbl->get();
1075         for (int j = 0; j < pDbl->getSize(); j++)
1076         {
1077             if (pdbl[j] <= 0)
1078             {
1079                 return false;
1080             }
1081         }
1082     }
1083
1084     return true;
1085 }
1086
1087 }