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