* Bug 14606 fixed: now `[names,mem]=who()` returns memory used by variables
[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)
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                 {        //evalute polynom with "MaxDim"
576                     int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
577     #if defined(_SCILAB_DEBUGREF_)
578                     Double* pdbl = new Double(iMaxDim);
579     #else
580                     Double dbl(iMaxDim);
581     #endif
582                     if (pIL->getStart()->isPoly())
583                     {
584                         Polynom *poPoly = pIL->getStart()->getAs<types::Polynom>();
585     #if defined(_SCILAB_DEBUGREF_)
586                         pIL->setStart(poPoly->evaluate(pdbl));
587     #else
588                         pIL->setStart(poPoly->evaluate(&dbl));
589     #endif
590                     }
591                     if (pIL->getStep()->isPoly())
592                     {
593                         Polynom *poPoly = pIL->getStep()->getAs<types::Polynom>();
594     #if defined(_SCILAB_DEBUGREF_)
595                         pIL->setStep(poPoly->evaluate(pdbl));
596     #else
597                         pIL->setStep(poPoly->evaluate(&dbl));
598     #endif
599                     }
600                     if (pIL->getEnd()->isPoly())
601                     {
602                         Polynom *poPoly = pIL->getEnd()->getAs<types::Polynom>();
603     #if defined(_SCILAB_DEBUGREF_)
604                         pIL->setEnd(poPoly->evaluate(pdbl));
605     #else
606                         pIL->setEnd(poPoly->evaluate(&dbl));
607     #endif
608                     }
609
610     #if defined(_SCILAB_DEBUGREF_)
611                     pdbl->killMe();
612 #endif
613                 }
614             }
615             if (_pRef != NULL || pIL->isComputable() == true)
616             {
617                 double start = getIndex(pIL->getStart());
618                 double step = getIndex(pIL->getStep());
619                 double end = getIndex(pIL->getEnd());
620
621                 pCurrentArg = (start < 1 && step > 0 || end < 1 && step < 0) ? NULL : pIL->extractFullMatrix()->getAs<Double>();
622             }
623
624             pIL->killMe();
625         }
626         else if (pIT->isString())
627         {
628             String* pStr = pIT->getAs<String>();
629             if(!_pRef)
630             {
631                 bUndefine = true;
632                 continue;
633             }
634             if (_pRef->isStruct())
635             {
636                 Struct* pStruct = _pRef->getAs<Struct>();
637
638                 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
639                 {
640                     bUndefine = true;
641                     continue;
642                 }
643
644                 wchar_t* pFieldName = pStr->get(0);
645
646                 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
647                 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
648                 if (iIndex == -1)
649                 {
650                     bUndefine = true;
651                     continue;
652                 }
653
654                 pCurrentArg = new Double((double)iIndex);
655             }
656             else if (_pRef->isTList())
657             {
658                 // List can't be extract by field and MList must call overload
659                 TList* pTL = _pRef->getAs<TList>();
660                 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
661                 double* pdbl = pCurrentArg->get();
662                 for (int i = 0; i < pStr->getSize(); i++)
663                 {
664                     wchar_t* pFieldName = pStr->get(i);
665                     int iIndex = pTL->getIndexFromString(pFieldName);
666                     if (iIndex == -1)
667                     {
668                         bUndefine = true;
669                         continue;
670                     }
671                     pdbl[i] = (double)(iIndex + 1);
672                 }
673             }
674             else if (_pRef->isList())
675             {
676                 bUndefine = true;
677                 break;
678             }
679             else if (_pRef->isCell())
680             {
681             }
682         }
683         else if (pIT->isPoly())
684         {
685             //$
686             Polynom* pMP = pIT->getAs<types::Polynom>();
687             int iMaxDim = 0;
688             //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
689             if (_pRef)
690             {
691                 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
692             }
693
694 #ifdef _SCILAB_DEBUGREF_
695             Double* pdbl = new Double(iMaxDim); // $
696             pCurrentArg = pMP->evaluate(pdbl);
697             pdbl->killMe();
698 #else
699             Double dbl(iMaxDim); // $
700             pCurrentArg = pMP->evaluate(&dbl);
701 #endif
702         }
703         else if (pIT->isBool())
704         {
705             //[T F F T F]
706             Bool *pB = pIT->getAs<types::Bool>();
707             int *piB = pB->get();
708             const int size = pB->getSize();
709
710             //find true item count
711             int iItemCount = 0;
712             for (int j = 0; j < size; j++)
713             {
714                 if (piB[j])
715                 {
716                     iItemCount++;
717                 }
718             }
719
720             //allow new Double variable
721             Double* pDbl = new Double(1, iItemCount);
722             double* pdbl = pDbl->getReal();
723
724             int j = 0;
725             for (int l = 0; l < size; l++)
726             {
727                 if (piB[l])
728                 {
729                     pdbl[j++] = l + 1;
730                 }
731             }
732             pCurrentArg = pDbl;
733         }
734         else if (pIT->isSparseBool())
735         {
736             types::SparseBool* pSb = pIT->getAs<types::SparseBool>();
737             int iItemCount = static_cast<int>(pSb->nbTrue());
738             int iRows = pSb->getRows();
739             int *pCoord = new int[iItemCount * 2];
740
741             //get (r,c) positions of True Elements
742             pSb->outputRowCol(pCoord);
743             int* pY = pCoord + iItemCount;
744             //allow new Double index variable
745             Double* pDbl = new Double(1, iItemCount);
746             double* pdbl = pDbl->getReal();
747             for (int i = 0; i < iItemCount; ++i)
748             {
749                 pdbl[i] = pCoord[i] + (pY[i] - 1) * iRows;
750             }
751
752             delete[] pCoord;
753             pCurrentArg = pDbl;
754         }
755         else if (pIT->isInt())
756         {
757             switch (pIT->getType())
758             {
759                 case InternalType::ScilabInt8:
760                 {
761                     pCurrentArg = convertIndex(pIT->getAs<Int8>());
762                     break;
763                 }
764                 case InternalType::ScilabInt16:
765                 {
766                     pCurrentArg = convertIndex(pIT->getAs<Int16>());
767                     break;
768                 }
769                 case InternalType::ScilabInt32:
770                 {
771                     pCurrentArg = convertIndex(pIT->getAs<Int32>());
772                     break;
773                 }
774                 case InternalType::ScilabInt64:
775                 {
776                     pCurrentArg = convertIndex(pIT->getAs<Int64>());
777                     break;
778                 }
779                 case InternalType::ScilabUInt8:
780                 {
781                     pCurrentArg = convertIndex(pIT->getAs<UInt8>());
782                     break;
783                 }
784                 case InternalType::ScilabUInt16:
785                 {
786                     pCurrentArg = convertIndex(pIT->getAs<UInt16>());
787                     break;
788                 }
789                 case InternalType::ScilabUInt32:
790                 {
791                     pCurrentArg = convertIndex(pIT->getAs<UInt32>());
792                     break;
793                 }
794                 case InternalType::ScilabUInt64:
795                 {
796                     pCurrentArg = convertIndex(pIT->getAs<UInt64>());
797                     break;
798                 }
799             }
800         }
801
802         if (bDeleteNeeded)
803         {
804             pIT->killMe();
805         }
806
807         if (pCurrentArg)
808         {
809             const int iCountDim = pCurrentArg->getSize();
810             _piMaxDim[i] = 0;
811             for (int j = 0; j < iCountDim; j++)
812             {
813                 //checks if size < size(int)
814                 if (pCurrentArg->get(j) >= INT_MAX)
815                 {
816                     wchar_t szError[bsiz];
817                     os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
818                     throw ast::InternalError(szError);
819                 }
820
821                 int d = static_cast<int>(pCurrentArg->get(j));
822                 if (d > _piMaxDim[i])
823                 {
824                     _piMaxDim[i] = d;
825                 }
826             }
827
828             iSeqCount *= iCountDim;
829             if (_piCountDim)
830             {
831                 _piCountDim[i] = iCountDim;
832             }
833         }
834         else
835         {
836             wchar_t szError[bsiz];
837             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
838
839             delete[] _piMaxDim;
840             delete[] _piCountDim;
841             cleanIndexesArguments(_pArgsIn, _pArgsOut);
842
843             throw ast::InternalError(szError);
844         }
845         _pArgsOut->push_back(pCurrentArg);
846
847     }
848
849
850     //return 0 to force extract to create an empty matrix
851     if (_pRef &&
852             (_pRef->isDouble() && _pRef->getAs<Double>()->isEmpty()))
853     {
854         return 0;
855     }
856
857     //returns a negative value if at least one parameter is undefined
858     //case with : or $ for creation by insertion
859     return (!bUndefine ? iSeqCount : -iSeqCount);
860 }
861
862 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
863 {
864     if (_pArgsNew)
865     {
866         //free pArg content
867         for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
868         {
869             if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
870             {
871                 if ((*_pArgsNew)[iArg])
872                 {
873                     (*_pArgsNew)[iArg]->killMe();
874                 }
875             }
876         }
877
878         _pArgsNew->clear();
879     }
880 }
881
882 void getIndexesWithDims(int _iIndex, int* _piIndexes, const int* _piDims, int _iDims)
883 {
884     int iMul = 1;
885     for (int i = 0; i < _iDims; i++)
886     {
887         _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
888         iMul *= _piDims[i];
889     }
890
891     //matrix [2,4,3]
892     //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
893     //loop 1
894     // (12 / 1) % 2 -> 0
895     //loop 2
896     // (12 / 2) % 4 -> 2
897     //loop 3
898     // (12 / 8) % 3 -> 1
899
900     //matrix [3,4,3]
901     //index = 22
902     //loop 1
903     // (22 / 1) % 3 -> 1
904     //loop 2
905     // (22 / 3) % 4 -> 3
906     //loop 3
907     // (22 / 12) % 3 -> 1
908
909     //matrix [3,4,3]
910     //index = 35
911     //loop 1
912     // (35 / 1) % 3 -> 2
913     //loop 2
914     // (35 / 3) % 4 -> 3
915     //loop 3
916     // (35 / 12) % 3 -> 2
917 }
918
919
920 int getIndexWithDims(int* _piIndexes, const int* _piDims, int _iDims)
921 {
922     int idx = 0;
923     int iMult = 1;
924     for (int i = 0; i < _iDims; i++)
925     {
926         idx += _piIndexes[i] * iMult;
927         iMult *= _piDims[i];
928     }
929     return idx;
930 }
931
932 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
933 {
934     if (pIT->hasToString() == false)
935     {
936         types::Function::ReturnValue ret = types::Function::Error;
937         //call overload %type_p
938         types::typed_list in;
939         types::typed_list out;
940
941         pIT->IncreaseRef();
942         in.push_back(pIT);
943
944         try
945         {
946             ret = Overload::generateNameAndCall(L"p", in, 1, out);
947             pIT->DecreaseRef();
948             return ret;
949         }
950         catch (const ast::InternalError &ie)
951         {
952             pIT->DecreaseRef();
953             throw ie;
954         }
955     }
956     else
957     {
958         std::wostringstream ostr;
959         if (pIT->isFunction())
960         {
961             pIT->getAs<types::Function>()->toString(ostr);
962         }
963         else if (pIT->isList() || pIT->isCallable())
964         {
965             ostr << wcsVarName;
966         }
967
968         //to manage lines information
969         int iLines = ConfigVariable::getConsoleLines();
970
971         bool bFinish = false;
972         do
973         {
974             //block by block
975             bFinish = pIT->toString(ostr);
976             if (ConfigVariable::isError())
977             {
978                 ConfigVariable::resetError();
979                 ostr.str(L"");
980                 ConfigVariable::resetExecutionBreak();
981                 return types::Function::Error;
982             }
983
984             if (bFinish == false && iLines != 0)
985             {
986                 //show message on prompt
987                 bFinish = linesmore() == 1;
988             }
989
990             if (ConfigVariable::isPrintCompact() == false && ConfigVariable::isPrintInput() == false)
991             {
992                 ostr << std::endl;
993             }
994
995             scilabForcedWriteW(ostr.str().c_str());
996             ostr.str(L"");
997         }
998         while (bFinish == false && ConfigVariable::isExecutionBreak() == false);
999
1000         if (bFinish == false)
1001         {
1002             ConfigVariable::resetExecutionBreak();
1003         }
1004         pIT->clearPrintState();
1005         return types::Function::OK;
1006     }
1007 }
1008
1009 //n-uplet in french
1010 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
1011 {
1012     //if bRet == 1, previous dims has reach max value.
1013     int iRet = 0;
1014
1015     if (_iCurrentDim == 0)
1016     {
1017         //last dims
1018         if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1019         {
1020             _piIndex[_iCurrentDim] = 0;
1021             return 1;
1022         }
1023     }
1024     else
1025     {
1026         iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
1027         if (iRet)
1028         {
1029             _piIndex[_iCurrentDim]++;
1030             if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
1031             {
1032                 _piIndex[_iCurrentDim] = 0;
1033                 return 1;
1034             }
1035         }
1036     }
1037     return 0;
1038 }
1039
1040 Double* createEmptyDouble()
1041 {
1042     return Double::Empty();
1043 }
1044
1045 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
1046 {
1047     return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
1048 }
1049
1050 double* getDoubleArrayFromDouble(InternalType* _pIT)
1051 {
1052     return _pIT->getAs<Double>()->get();
1053 }
1054
1055 Double* createDoubleVector(int _iSize)
1056 {
1057     int piDims[] = {1, _iSize};
1058     Double* pOut = new Double(2, piDims);
1059     for (int i = 0; i < _iSize; i++)
1060     {
1061         pOut->set(i, i + 1);
1062     }
1063     return pOut;
1064 }
1065
1066 bool checkArgValidity(typed_list& _Arg)
1067 {
1068     for (int i = 0; i < (int)_Arg.size(); i++)
1069     {
1070         if (_Arg[i]->isDouble() == false)
1071         {
1072             return false;
1073         }
1074
1075         Double* pDbl = _Arg[i]->getAs<Double>();
1076         double* pdbl = pDbl->get();
1077         for (int j = 0; j < pDbl->getSize(); j++)
1078         {
1079             if (pdbl[j] <= 0)
1080             {
1081                 return false;
1082             }
1083         }
1084     }
1085
1086     return true;
1087 }
1088
1089 }