fix ast tests memory leaks
[scilab.git] / scilab / modules / ast / src / cpp / types / arrayof.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010 - DIGITEO - Antoine ELIAS
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "double.hxx"
14 #include "bool.hxx"
15 #include "singlepoly.hxx"
16 #include "singlestruct.hxx"
17
18 extern "C"
19 {
20 #include "dynlib_ast.h"
21 }
22
23 namespace types
24 {
25 /*    template <typename T>
26     ArrayOf<T>* createEmptyDouble()
27     {
28         return Double::Empty();
29     }
30 */
31 //n-uplet in french
32 int computeTuples(int* _piCountDim, int _iDims, int _iCurrentDim, int* _piIndex)
33 {
34     //if bRet == 1, previous dims has reach max value.
35     int iRet = 0;
36
37     if (_iCurrentDim == 0)
38     {
39         //last dims
40         if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
41         {
42             _piIndex[_iCurrentDim] = 0;
43             return 1;
44         }
45     }
46     else
47     {
48         iRet = computeTuples(_piCountDim, _iDims, _iCurrentDim - 1, _piIndex);
49         if (iRet)
50         {
51             _piIndex[_iCurrentDim]++;
52             if (_piIndex[_iCurrentDim] >= _piCountDim[_iCurrentDim])
53             {
54                 _piIndex[_iCurrentDim] = 0;
55                 return 1;
56             }
57         }
58     }
59     return 0;
60 }
61
62 InternalType* createEmptyDouble()
63 {
64     return Double::Empty();
65 }
66
67 int getIntValueFromDouble(InternalType* _pIT, int _iPos)
68 {
69     return static_cast<int>(_pIT->getAs<Double>()->get(_iPos));
70 }
71
72 double* getDoubleArrayFromDouble(InternalType* _pIT)
73 {
74     return _pIT->getAs<Double>()->get();
75 }
76
77 InternalType* createDoubleVector(int _iSize)
78 {
79     int piDims[] = {1, _iSize};
80     Double* pOut = new Double(2, piDims);
81     for (int i = 0 ; i < _iSize ; i++)
82     {
83         pOut->set(i, i + 1);
84     }
85     return pOut;
86 }
87
88 bool checkArgValidity(typed_list& _Arg)
89 {
90     for (int i = 0 ; i < (int)_Arg.size() ; i++)
91     {
92         if ( _Arg[i]->isDouble() == false)
93         {
94             return false;
95         }
96
97         Double* pDbl = _Arg[i]->getAs<Double>();
98         double* pdbl = pDbl->get();
99         for (int j = 0 ; j < pDbl->getSize() ; j++)
100         {
101             if (pdbl[j] <= 0)
102             {
103                 return false;
104             }
105         }
106     }
107
108     return true;
109 }
110
111 template <typename T>
112 InternalType* ArrayOf<T>::insert(typed_list* _pArgs, InternalType* _pSource)
113 {
114     if (getRef() > 1)
115     {
116         // An ArrayOf content in more than one Scilab variable
117         // must be cloned before to be modified.
118         ArrayOf* pClone = clone()->template getAs<ArrayOf>();
119         InternalType* pIT = pClone->insert(_pArgs, _pSource);
120         if (pIT == NULL)
121         {
122             pClone->killMe();
123         }
124
125         return pIT;
126     }
127
128     bool bNeedToResize  = false;
129     int iDims           = (int)_pArgs->size();
130     int iDimsOrigine = m_iDims;
131     typed_list pArg;
132
133     int* piMaxDim       = new int[iDims];
134     int* piCountDim     = new int[iDims];
135
136     //on case of resize
137     int* piNewDims      = NULL;
138     int iNewDims        = 0;
139     ArrayOf* pSource = _pSource->getAs<ArrayOf>();
140
141     bool bIsColon = false;
142
143     //evaluate each argument and replace by appropriate value and compute the count of combinations
144     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
145     if (iSeqCount == 0)
146     {
147         //free pArg content
148         delete[] piCountDim;
149         delete[] piMaxDim;
150         cleanIndexesArguments(_pArgs, &pArg);
151         return this;
152     }
153
154     //only scalar can be used to ".=" operation
155     if (iSeqCount != pSource->getSize() && pSource->isScalar() == false)
156     {
157         return NULL;
158     }
159
160     //remove last dimension at size 1
161     //remove last dimension if are == 1
162     for (int i = (iDims - 1); i >= 2; i--)
163     {
164         if (piMaxDim[i] == 1)
165         {
166             iDims--;
167             pArg.back()->killMe();
168             pArg.pop_back();
169         }
170         else
171         {
172             break;
173         }
174     }
175
176
177     if (iDims >= m_iDims)
178     {
179         //all case are good, we can do almost everything
180         //check if resize is needed
181         if (iDims > m_iDims)
182         {
183             bNeedToResize = true;
184         }
185         else //_iDims == m_iDims
186         {
187             for (int i = 0 ; i < m_iDims ; i++)
188             {
189                 if (m_piDims[i] < piMaxDim[i])
190                 {
191                     bNeedToResize = true;
192                     break;
193                 }
194             }
195         }
196
197         //determine new dimension of the matrix
198         if (bNeedToResize == true)
199         {
200             iNewDims = iDims;
201             piNewDims = new int[iNewDims];
202             for (int i = 0 ; i < m_iDims ; i++)
203             {
204                 piNewDims[i] = std::max(piMaxDim[i], m_piDims[i]);
205             }
206
207             int iSource = (pSource->getDims() - 1);
208             bool bPassed = false;
209             int *piSourceDims = pSource->getDimsArray();
210
211             for (int i = m_iDims; i < iNewDims; ++i)
212             {
213                 piNewDims[i] = piMaxDim[i];
214             }
215         }
216     }
217     else // _iDims < m_iDims
218     {
219         if (isVector() || isScalar() || getSize() == 0) //getSize() == 0, only for [] and {}
220         {
221             if (getSize() < piMaxDim[0])
222             {
223                 bNeedToResize = true;
224                 iNewDims = 2;
225                 piNewDims = new int[2];
226
227                 if (getCols() == 1 || getSize() == 0)
228                 {
229                     //column vector
230                     piNewDims[0] = piMaxDim[0];
231                     piNewDims[1] = 1;
232                 }
233                 else if (getRows() == 1)
234                 {
235                     //row vector
236                     piNewDims[0] = 1;
237                     piNewDims[1] = piMaxDim[0];
238                 }
239             }
240         }
241         else
242         {
243             //each index before last index must be in range of his dimension
244             //and last given dimension can not be > prod(last dimensions)
245             for (int i = 0 ; i < iDims - 1 ; i++)
246             {
247                 //indexes are always doubles
248                 double* pIdx = getDoubleArrayFromDouble(pArg[i]);
249                 //InternalType* pVar = pArg[i];
250                 //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
251                 int iSize = pArg[i]->getAs<ArrayOf>()->getSize();
252                 for (int j = 0 ; j < iSize ; j++)
253                 {
254                     if (pIdx[j] > m_piDims[i])
255                     {
256                         delete[] piCountDim;
257                         delete[] piMaxDim;
258                         //free pArg content
259                         cleanIndexesArguments(_pArgs, &pArg);
260                         return NULL;
261                     }
262                 }
263             }
264
265             //check last dim
266             int iMaxLastDim = getVarMaxDim(iDims - 1, iDims);
267             double* pIdx = getDoubleArrayFromDouble(pArg[pArg.size() - 1]);
268             //InternalType* pVar = pArg[pArg.size() - 1];
269             //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
270             int iSize = pArg[pArg.size() - 1]->getAs<GenericType>()->getSize();
271             for (int i = 0 ; i < iSize ; i++)
272             {
273                 if (pIdx[i] > iMaxLastDim)
274                 {
275                     delete[] piCountDim;
276                     delete[] piMaxDim;
277                     //free pArg content
278                     cleanIndexesArguments(_pArgs, &pArg);
279                     return NULL;
280                 }
281             }
282         }
283     }
284
285     //before resize, check input dimension
286
287     if (bNeedToResize)
288     {
289         bool bPass = resize(piNewDims, iNewDims);
290         if (bPass == false)
291         {
292             delete[] piCountDim;
293             delete[] piMaxDim;
294             //free pArg content
295             cleanIndexesArguments(_pArgs, &pArg);
296             return NULL;
297         }
298     }
299     else
300     {
301         piNewDims   = m_piDims;
302         iNewDims    = m_iDims;
303     }
304
305     //update complexity
306     if (pSource->isComplex() && m_pImgData == NULL)
307     {
308         setComplex(true);
309     }
310
311     int argSize = static_cast<int>(pArg.size());
312     int* piIndex = new int[argSize];
313     int* piCoord = new int[argSize];
314     int* piViewDims = new int[iDims];
315     memset(piIndex, 0x00, sizeof(int) * argSize);
316
317     //convert  current dimension to view dimension
318     for (int i = 0 ; i < iDims ; i++)
319     {
320         piViewDims[i] = getVarMaxDim(i, iDims);
321     }
322
323     T* pRealData    = pSource->get();
324     T* pImgData     = pSource->getImg();
325     bool bComplex   = pSource->isComplex();
326
327     for (int i = 0 ; i < iSeqCount ; i++)
328     {
329         computeTuples(piCountDim, argSize, argSize - 1, piIndex);
330
331         //std::cout << "[";
332         for (int j = 0; j < argSize; j++)
333         {
334             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
335             //InternalType* pVar = pArg[j];
336             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
337             //std::cout << piCoord[j] << " ";
338         }
339
340         //std::cout << "]" << std::endl;
341
342         int iPos = getIndexWithDims(piCoord, piViewDims, iDims);
343         if (iPos < 0)
344         {
345             if (bNeedToResize)
346             {
347                 delete[] piNewDims;
348             }
349
350             delete[] piMaxDim;
351             delete[] piCountDim;
352             delete[] piIndex;
353             delete[] piCoord;
354             delete[] piViewDims;
355
356             //free pArg content
357             cleanIndexesArguments(_pArgs, &pArg);
358
359             wchar_t szError[bsiz];
360             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
361             throw ast::ScilabError(szError);
362         }
363
364         if (pSource->isScalar())
365         {
366             //element-wise insertion
367             set(iPos, pRealData[0]);
368             if (pImgData != NULL && bComplex)
369             {
370                 setImg(iPos, pImgData[0]);
371             }
372         }
373         else
374         {
375             if ( bIsColon)
376             {
377                 int iPas = 1;
378                 for (int j = 0; j < iDimsOrigine; j++)
379                 {
380                     iPas = iPas * m_piDims[j];
381                 }
382
383                 for (int iPost = iPos; iPost < this->getSize(); iPost += iPas)
384                 {
385                     set(iPost, pRealData[i]);
386                     if (pImgData != NULL && bComplex)
387                     {
388                         setImg(iPost, pImgData[i]);
389                     }
390                     i++;
391                 }
392             }
393             else
394             {
395                 set(iPos, pRealData[i]);
396                 if (pImgData != NULL && bComplex)
397                 {
398                     setImg(iPos, pImgData[i]);
399                 }
400             }
401         }
402
403         // reset imaginary part
404         if (m_pImgData != NULL && bComplex == false)
405         {
406             setImg(iPos, 0);
407         }
408
409         //update index
410         piIndex[0]++;
411     }
412
413     if (bNeedToResize)
414     {
415         delete[] piNewDims;
416     }
417
418     delete[] piMaxDim;
419     delete[] piCountDim;
420     delete[] piIndex;
421     delete[] piCoord;
422     delete[] piViewDims;
423
424     //free pArg content
425     cleanIndexesArguments(_pArgs, &pArg);
426
427     return this;
428 }
429
430 template <typename T>
431 InternalType* ArrayOf<T>::insertNew(typed_list* _pArgs, InternalType* _pSource)
432 {
433     typed_list pArg;
434     InternalType *pOut  = NULL;
435     ArrayOf* pSource = _pSource->getAs<ArrayOf>();
436
437     int iDims           = (int)_pArgs->size();
438     int* piMaxDim       = new int[iDims];
439     int* piCountDim     = new int[iDims];
440     bool bComplex       = pSource->getImg() != NULL;
441     bool bUndefine      = false;
442     bool bIsImpli       = false;
443
444     //evaluate each argument and replace by appropriate value and compute the count of combinations
445     int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
446
447     if (iSeqCount == 0)
448     {
449         delete[] piMaxDim;
450         delete[] piCountDim;
451         //free pArg content
452         cleanIndexesArguments(_pArgs, &pArg);
453         return createEmptyDouble();
454     }
455
456     if (iSeqCount < 0)
457     {
458         iSeqCount = -iSeqCount;
459         bUndefine = true;
460     }
461
462     if (bUndefine)
463     {
464         //manage : and $ in creation by insertion
465         int *piSourceDims = pSource->getDimsArray();
466         int iSourceDims = pSource->getDims();
467         int iCompteurNull = 0;
468         int iLastNull = 0;
469         for (int i = 0; i < iDims; i++)
470         {
471             if (pArg[i] == NULL)
472             {
473                 iCompteurNull++;
474                 iLastNull = i;
475             }
476             else
477             {
478                 if ((*_pArgs)[i]->isImplicitList())
479                 {
480                     bIsImpli = true;
481                 }
482             }
483         }
484
485         //if all index are : -> a = x
486         if (iCompteurNull == pArg.size())
487         {
488             delete[] piMaxDim;
489             delete[] piCountDim;
490             //free pArg content
491             cleanIndexesArguments(_pArgs, &pArg);
492             return _pSource;
493         }
494
495         //vector case
496         if (pSource->isVector() && iCompteurNull == 1)
497         {
498             piMaxDim[iLastNull] = pSource->getSize();
499             pArg[iLastNull] = createDoubleVector(piMaxDim[iLastNull]);
500         }
501         else
502         {
503             //matrix and hypermatrix case
504             if (iCompteurNull < pSource->getDims())
505             {
506                 delete[] piMaxDim;
507                 delete[] piCountDim;
508                 //free pArg content
509                 cleanIndexesArguments(_pArgs, &pArg);
510                 //contain bad index, like <= 0, ...
511                 return NULL;
512             }
513
514             //replace ":" by know source dimensions
515             int iSource = 0;
516             for (int i = 0; i < iDims; ++i)
517             {
518                 if (pArg[i] == NULL)
519                 {
520                     if (iSource < iSourceDims)
521                     {
522                         piMaxDim[i] = piSourceDims[iSource];
523                         pArg[i] = createDoubleVector(piMaxDim[i]);
524                         ++iSource;
525                     }
526                     else
527                     {
528                         //fill dimensions after pSource->getDimes() with 1
529                         piMaxDim[i] = 1;
530                         pArg[i] = createDoubleVector(piMaxDim[i]);
531                     }
532                 }
533             }
534         }
535     }
536
537     //remove last dimension at size 1
538     //remove last dimension if are == 1
539     for (int i = (iDims - 1) ; i >= 2 ; i--)
540     {
541         if (piMaxDim[i] == 1)
542         {
543             iDims--;
544             pArg.back()->killMe();
545             pArg.pop_back();
546         }
547         else
548         {
549             break;
550         }
551     }
552
553     if (checkArgValidity(pArg) == false)
554     {
555         delete[] piMaxDim;
556         delete[] piCountDim;
557         //free pArg content
558         cleanIndexesArguments(_pArgs, &pArg);
559         //contain bad index, like <= 0, ...
560         return NULL;
561     }
562
563     if (iDims == 1)
564     {
565         if (pSource->getCols() == 1)
566         {
567             int piRealDim[2] = {piMaxDim[0], 1};
568             pOut = pSource->createEmpty(2, piRealDim, bComplex);
569         }
570         else
571         {
572             //rows == 1
573             int piRealDim[2] = {1, piMaxDim[0]};
574             pOut = pSource->createEmpty(2, piRealDim, bComplex);
575         }
576     }
577     else
578     {
579         pOut = pSource->createEmpty(iDims, piMaxDim, bComplex);
580     }
581
582     //fill with null item
583     ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
584     T* pRealData = pArrayOut->get();
585     if (bComplex)
586     {
587         T* pImgData = pArrayOut->getImg();
588         for (int i = 0 ; i < pArrayOut->getSize() ; i++)
589         {
590             pArrayOut->deleteData(pRealData[i]);
591             pRealData[i] = pSource->getNullValue();
592             pArrayOut->deleteData(pImgData[i]);
593             pImgData[i] = pSource->getNullValue();
594         }
595     }
596     else
597     {
598         for (int i = 0 ; i < pArrayOut->getSize() ; i++)
599         {
600             pArrayOut->deleteData(pRealData[i]);
601             pRealData[i] = pSource->getNullValue();
602         }
603     }
604
605     if (bIsImpli && (pArrayOut->getSize() != _pSource->getAs<types::GenericType>()->getSize()))
606     {
607         delete[] piMaxDim;
608         delete[] piCountDim;
609         //free pArg content
610         cleanIndexesArguments(_pArgs, &pArg);
611         return NULL;
612     }
613     //insert values in new matrix
614     InternalType* pOut2 = pArrayOut->insert(&pArg, _pSource);
615     if (pOut != pOut2)
616     {
617         delete pOut;
618     }
619
620     delete[] piMaxDim;
621     delete[] piCountDim;
622     //free pArg content
623     cleanIndexesArguments(_pArgs, &pArg);
624
625     return pOut2;
626 }
627
628 template <typename T>
629 bool ArrayOf<T>::append(int _iRows, int _iCols, InternalType* _poSource)
630 {
631     ArrayOf * pGT = _poSource->getAs<ArrayOf>();
632     int iRows = pGT->getRows();
633     int iCols = pGT->getCols();
634
635     //insert without resize
636     if (iRows + _iRows > m_iRows || iCols + _iCols > m_iCols)
637     {
638         return false;
639     }
640
641     //Update complexity if necessary
642     if (pGT->isComplex())
643     {
644         setComplex(true);
645     }
646     else if (isComplex())
647     {
648         pGT->setComplex(true);
649     }
650
651     if (pGT->isComplex())
652     {
653         for (int i = 0 ; i < iRows ; i++)
654         {
655             for (int j = 0 ; j < iCols ; j++)
656             {
657                 set(_iRows + i, _iCols + j, pGT->get(i, j));
658                 setImg(_iRows + i, _iCols + j, pGT->getImg(i, j));
659             }
660         }
661     }
662     else
663     {
664         for (int i = 0 ; i < iRows ; i++)
665         {
666             for (int j = 0 ; j < iCols ; j++)
667             {
668                 set(_iRows + i, _iCols + j, pGT->get(i, j));
669             }
670         }
671     }
672
673     return true;
674 }
675
676 template <typename T>
677 InternalType* ArrayOf<T>::remove(typed_list* _pArgs)
678 {
679     ArrayOf<T>* pOut    = NULL;
680     int iDims           = (int)_pArgs->size();
681     typed_list pArg;
682
683     int* piMaxDim       = new int[iDims];
684     int* piCountDim     = new int[iDims];
685
686     //evaluate each argument and replace by appropriate value and compute the count of combinations
687     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
688     delete[] piMaxDim;
689     delete[] piCountDim;
690     if (iSeqCount == 0)
691     {
692         //free pArg content
693         cleanIndexesArguments(_pArgs, &pArg);
694         //no Seq, no change but no error.
695         return this;
696     }
697
698     bool* pbFull = new bool[iDims];
699     //coord must represent all values on a dimension
700     for (int i = 0 ; i < iDims ; i++)
701     {
702         pbFull[i]       = false;
703         int iDimToCheck = getVarMaxDim(i, iDims);
704         int iIndexSize  = pArg[i]->getAs<GenericType>()->getSize();
705
706         //we can have index more than once
707         if (iIndexSize >= iDimToCheck)
708         {
709             //size is good, now check datas
710             double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
711             for (int j = 0 ; j < iDimToCheck ; j++)
712             {
713                 bool bFind = false;
714                 for (int k = 0 ; k < iIndexSize ; k++)
715                 {
716                     if ((int)pIndexes[k] == j + 1)
717                     {
718                         bFind = true;
719                         break;
720                     }
721                 }
722                 pbFull[i]  = bFind;
723             }
724         }
725     }
726
727     //only one dims can be not full/entire
728     bool bNotEntire = false;
729     int iNotEntire  = 0;
730     bool bTooMuchNotEntire = false;
731     for (int i = 0 ; i < iDims ; i++)
732     {
733         if (pbFull[i] == false)
734         {
735             if (bNotEntire == false)
736             {
737                 bNotEntire = true;
738                 iNotEntire = i;
739             }
740             else
741             {
742                 bTooMuchNotEntire = true;
743                 break;
744             }
745         }
746     }
747
748     if (bTooMuchNotEntire == true)
749     {
750         //free pArg content
751         cleanIndexesArguments(_pArgs, &pArg);
752         return NULL;
753     }
754
755     delete[] pbFull;
756
757     //find index to keep
758     int iNotEntireSize          = pArg[iNotEntire]->getAs<GenericType>()->getSize();
759     double* piNotEntireIndex    = getDoubleArrayFromDouble(pArg[iNotEntire]);
760     int iKeepSize               = getVarMaxDim(iNotEntire, iDims);
761     bool* pbKeep                = new bool[iKeepSize];
762
763     //fill pbKeep with true value
764     for (int i = 0 ; i < iKeepSize ; i++)
765     {
766         pbKeep[i] = true;
767     }
768
769     for (int i = 0 ; i < iNotEntireSize ; i++)
770     {
771         int idx = (int)piNotEntireIndex[i] - 1;
772
773         //don't care of value out of bounds
774         if (idx < iKeepSize)
775         {
776             pbKeep[idx] = false;
777         }
778     }
779
780     int iNewDimSize = 0;
781     for (int i = 0 ; i < iKeepSize ; i++)
782     {
783         if (pbKeep[i] == true)
784         {
785             iNewDimSize++;
786         }
787     }
788     delete[] pbKeep;
789
790     int* piNewDims = new int[iDims];
791     for (int i = 0 ; i < iDims ; i++)
792     {
793         if (i == iNotEntire)
794         {
795             piNewDims[i] = iNewDimSize;
796         }
797         else
798         {
799             piNewDims[i] = getVarMaxDim(i, iDims);
800         }
801     }
802
803     //remove last dimension if are == 1
804     int iOrigDims = iDims;
805     for (int i = (iDims - 1) ; i >= 2 ; i--)
806     {
807         if (piNewDims[i] == 1)
808         {
809             iDims--;
810         }
811         else
812         {
813             break;
814         }
815     }
816
817     if (iNewDimSize == 0)
818     {
819         //free pArg content
820         cleanIndexesArguments(_pArgs, &pArg);
821         delete[] piNewDims;
822         return createEmptyDouble();
823     }
824
825     if (iDims == 1)
826     {
827         //two cases, depends of original matrix/vector
828         if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
829         {
830             //special case for row vector
831             int piRealDim[2] = {1, iNewDimSize};
832             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
833             //in this case we have to care of 2nd dimension
834             //iNotEntire = 1;
835         }
836         else
837         {
838             int piRealDim[2] = {iNewDimSize, 1};
839             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
840         }
841     }
842     else
843     {
844         pOut = createEmpty(iDims, piNewDims, m_pImgData != NULL);
845     }
846
847     delete[] piNewDims;
848     //find a way to copy existing data to new variable ...
849     int iNewPos = 0;
850     int* piIndexes = new int[iOrigDims];
851     int* piViewDims = new int[iOrigDims];
852     for (int i = 0 ; i < iOrigDims ; i++)
853     {
854         piViewDims[i] = getVarMaxDim(i, iOrigDims);
855     }
856
857     for (int i = 0 ; i < getSize() ; i++)
858     {
859         bool bByPass = false;
860         getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
861
862         //check if piIndexes use removed indexes
863         for (int j = 0 ; j < iNotEntireSize ; j++)
864         {
865             if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
866             {
867                 //by pass this value
868                 bByPass = true;
869                 break;
870             }
871         }
872
873         if (bByPass == false)
874         {
875             //compute new index
876             pOut->set(iNewPos, get(i));
877             if (m_pImgData != NULL)
878             {
879                 pOut->setImg(iNewPos, getImg(i));
880             }
881             iNewPos++;
882         }
883     }
884
885     //free pArg content
886     cleanIndexesArguments(_pArgs, &pArg);
887
888     delete[] piIndexes;
889     delete[] piViewDims;
890     return pOut;
891 }
892
893 template <typename T>
894 InternalType* ArrayOf<T>::extract(typed_list* _pArgs)
895 {
896     ArrayOf<T>* pOut    = NULL;
897     int iDims           = (int)_pArgs->size();
898     typed_list pArg;
899
900     int* piMaxDim       = new int[iDims];
901     int* piCountDim     = new int[iDims];
902
903     //evaluate each argument and replace by appropriate value and compute the count of combinations
904     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
905     if (iSeqCount == 0)
906     {
907         delete[] piMaxDim;
908         delete[] piCountDim;
909         //free pArg content
910         cleanIndexesArguments(_pArgs, &pArg);
911         return createEmptyDouble();
912     }
913
914     if (iSeqCount < 0)
915     {
916         delete[] piMaxDim;
917         delete[] piCountDim;
918         //free pArg content
919         cleanIndexesArguments(_pArgs, &pArg);
920         return NULL;
921     }
922
923     if (iDims < m_iDims)
924     {
925         for (int i = 0 ; i < iDims ; i++)
926         {
927             int iDimToCheck = 0;
928             if (i == (iDims - 1))
929             {
930                 iDimToCheck = getVarMaxDim(i, iDims);
931             }
932             else
933             {
934                 iDimToCheck = m_piDims[i];
935             }
936
937             if (piMaxDim[i] > iDimToCheck)
938             {
939                 delete[] piMaxDim;
940                 delete[] piCountDim;
941                 //free pArg content
942                 cleanIndexesArguments(_pArgs, &pArg);
943                 return NULL;
944             }
945         }
946     }
947     else
948     {
949         if (iDims > m_iDims)
950         {
951             for (int i = m_iDims ; i < iDims ; i++)
952             {
953                 if (piMaxDim[i] > 1)
954                 {
955                     delete[] piMaxDim;
956                     delete[] piCountDim;
957                     //free pArg content
958                     cleanIndexesArguments(_pArgs, &pArg);
959                     return NULL;
960                 }
961             }
962         }
963
964         //check MaxDim
965         for (int i = 0 ; i < m_iDims ; i++)
966         {
967             if (piMaxDim[i] > m_piDims[i])
968             {
969                 delete[] piMaxDim;
970                 delete[] piCountDim;
971                 //free pArg content
972                 cleanIndexesArguments(_pArgs, &pArg);
973                 //exrtact must be in dimension limits
974                 return NULL;
975             }
976         }
977     }
978
979     //remove last dimension if are == 1
980     for (int i = (iDims - 1) ; i >= 2 ; i--)
981     {
982         if (piCountDim[i] == 1)
983         {
984             (iDims)--;
985         }
986         else
987         {
988             break;
989         }
990     }
991
992     //vector
993     if (iDims == 1)
994     {
995         if (piCountDim[0] == 0)
996         {
997             delete[] piMaxDim;
998             delete[] piCountDim;
999             //free pArg content
1000             cleanIndexesArguments(_pArgs, &pArg);
1001             return createEmptyDouble();
1002         }
1003         else
1004         {
1005             //two cases, depends of original matrix/vector
1006             if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[1] != 1 && m_piDims[0] == 1)
1007             {
1008                 //special case for row vector
1009                 int piRealDim[2] = {1, piCountDim[0]};
1010                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1011             }
1012             else
1013             {
1014                 if (getSize() == 1)
1015                 {
1016                     //for extraction on scalar
1017                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), pArg[0]->getAs<GenericType>()->getDimsArray(), m_pImgData != NULL);
1018                 }
1019                 else
1020                 {
1021                     int piRealDim[2] = {piCountDim[0], 1};
1022                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1023                 }
1024             }
1025         }
1026     }
1027     else
1028     {
1029         //matrix
1030         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1031     }
1032
1033     int* piIndex    = new int[_pArgs->size()];
1034     int* piCoord    = new int[_pArgs->size()];
1035     int* piViewDims = new int[iDims];
1036     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1037
1038     for (int i = 0 ; i < iDims ; i++)
1039     {
1040         piViewDims[i] = getVarMaxDim(i, iDims);
1041     }
1042
1043     for (int i = 0 ; i < iSeqCount ; i++)
1044     {
1045         //increment last dimension
1046         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1047
1048         //std::cout << "[";
1049         for (int j = 0 ; j < (int)_pArgs->size() ; j++)
1050         {
1051             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1052             //InternalType* pVar = pArg[i];
1053             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1054             //std::cout << piCoord[j] << " ";
1055
1056             // try to access somewhere wrong.
1057             if (piCoord[j] < 0)
1058             {
1059                 delete[] piIndex;
1060                 delete[] piCoord;
1061                 delete[] piViewDims;
1062                 delete[] piMaxDim;
1063                 delete[] piCountDim;
1064
1065                 //free pArg content
1066                 cleanIndexesArguments(_pArgs, &pArg);
1067                 return NULL;
1068             }
1069         }
1070
1071         //std::cout << "]" << std::endl;
1072
1073         int iPos = 0;
1074         //put vlaue in the new matrix
1075         if ((int)_pArgs->size() < m_iDims)
1076         {
1077             //compute index based on viewed matrix
1078             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1079         }
1080         else
1081         {
1082             //compute vector index
1083             iPos = getIndex(piCoord);
1084         }
1085
1086         //convert flat dimension to 0
1087         for (int j = 0 ; j < iDims ; j++)
1088         {
1089             if (piCountDim[j] == 1)
1090             {
1091                 piCoord[j] = 0;
1092             }
1093         }
1094
1095         pOut->set(i, get(iPos));
1096         if (m_pImgData != NULL)
1097         {
1098             pOut->setImg(i, getImg(iPos));
1099         }
1100
1101
1102         piIndex[0]++;
1103     }
1104
1105     //free pArg content
1106     cleanIndexesArguments(_pArgs, &pArg);
1107
1108     delete[] piIndex;
1109     delete[] piCoord;
1110     delete[] piViewDims;
1111     delete[] piMaxDim;
1112     delete[] piCountDim;
1113
1114     return pOut;
1115 }
1116
1117 template <typename T>
1118 bool ArrayOf<T>::resize(int* _piDims, int _iDims)
1119 {
1120     if (_iDims == m_iDims)
1121     {
1122         bool bChange = false;
1123         for (int i = 0 ; i < _iDims ; i++)
1124         {
1125             if (m_piDims[i] != _piDims[i])
1126             {
1127                 bChange = true;
1128                 break;
1129             }
1130         }
1131
1132         if (bChange == false)
1133         {
1134             //nothing to do
1135             return true;
1136         }
1137     }
1138
1139     //alloc new data array
1140     T* pRealData = NULL;
1141     T* pImgData = NULL;
1142
1143     int iNewSize = 0;
1144     if (m_pImgData != NULL)
1145     {
1146         iNewSize = get_max_size(_piDims, _iDims);
1147         if (m_iSizeMax < iNewSize)
1148         {
1149             //alloc 10% bigger than asked to prevent future resize
1150             int iOldSizeMax = m_iSizeMax;
1151             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1152             pRealData = allocData(m_iSizeMax);
1153             pImgData  = allocData(m_iSizeMax);
1154
1155             //copy values into new one
1156             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1157             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1158             for (int i = 0; i < _iDims; i++)
1159             {
1160                 piIndexes[i] = 0;
1161             }
1162
1163             int iPreviousNewIdx = 0;
1164             for (int i = 0; i < m_iSize; i++)
1165             {
1166                 getIndexes(i, piIndexes);
1167                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1168                 pRealData[iNewIdx] = m_pRealData[i];
1169                 pImgData[iNewIdx]  = m_pImgData[i];
1170                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1171                 {
1172                     T pTemp = getNullValue();
1173                     pRealData[j] = copyValue(pTemp);
1174                     pImgData[j]  = copyValue(pTemp);
1175                     if (pTemp != pRealData[j])
1176                     {
1177                         deleteData(pTemp);
1178                     }
1179                 }
1180
1181                 iPreviousNewIdx = iNewIdx + 1;
1182             }
1183
1184             // if it's not the first resize,
1185             // fill new data with element of last allocation
1186             if (iPreviousNewIdx < iOldSizeMax)
1187             {
1188                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1189                 {
1190                     pRealData[i] = m_pRealData[i];
1191                     pImgData[i] = m_pImgData[i];
1192                 }
1193             }
1194             else
1195             {
1196                 // first resize, iOldSizeMax don't contain the 10%
1197                 iOldSizeMax = iPreviousNewIdx;
1198             }
1199
1200             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1201             {
1202                 T pTemp = getNullValue();
1203                 pRealData[i] = copyValue(pTemp);
1204                 pImgData[i]  = copyValue(pTemp);
1205                 if (pTemp != pRealData[i])
1206                 {
1207                     deleteData(pTemp);
1208                 }
1209             }
1210
1211             delete[] piIndexes;
1212             //delete all array
1213             delete[] m_pRealData;
1214             delete[] m_pImgData;
1215             //replace old array by new one
1216             m_pRealData = pRealData;
1217             m_pImgData = pImgData;
1218         }
1219         else
1220         {
1221             //check if only the last dims change
1222             bool bNonLastDimChange = false;
1223             for (int i = 0; i < (m_iDims - 1); i++)
1224             {
1225                 if (m_piDims[i] != _piDims[i])
1226                 {
1227                     bNonLastDimChange = true;
1228                     break;
1229                 }
1230             }
1231
1232             //if vector or if row dimension not change, we don't need to shift data
1233             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1234             {
1235                 //copy values into new one
1236                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1237                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1238                 for (int i = m_iSize - 1; i >= 0; i--)
1239                 {
1240                     getIndexes(i, piIndexes);
1241                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1242                     if (iNewIdx != i)
1243                     {
1244                         T pTemp = m_pRealData[iNewIdx];
1245                         m_pRealData[iNewIdx] = m_pRealData[i];
1246                         m_pRealData[i] = pTemp;
1247
1248                         pTemp = m_pImgData[iNewIdx];
1249                         m_pImgData[iNewIdx] = m_pImgData[i];
1250                         m_pImgData[i] = pTemp;
1251                     }
1252                 }
1253                 delete[] piIndexes;
1254             }
1255         }
1256     }
1257     else
1258     {
1259         iNewSize = get_max_size(_piDims, _iDims);
1260         if (iNewSize > m_iSizeMax)
1261         {
1262             //alloc 10% bigger than asked to prevent future resize
1263             int iOldSizeMax = m_iSizeMax;
1264             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1265             pRealData = allocData(m_iSizeMax);
1266
1267             //copy values into new one
1268             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1269             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1270             for (int i = 0 ; i < _iDims ; i++)
1271             {
1272                 piIndexes[i] = 0;
1273             }
1274
1275             int iPreviousNewIdx = 0;
1276             for (int i = 0 ; i < m_iSize ; i++)
1277             {
1278                 getIndexes(i, piIndexes);
1279                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1280                 pRealData[iNewIdx] = m_pRealData[i];
1281                 m_pRealData[i] = NULL;
1282                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1283                 {
1284                     T pTemp = getNullValue();
1285                     T pTemp2 = copyValue(pTemp);
1286                     pRealData[j] = pTemp2;
1287                     if (pTemp != pTemp2)
1288                     {
1289                         deleteData(pTemp);
1290                     }
1291                 }
1292
1293                 iPreviousNewIdx = iNewIdx + 1;
1294             }
1295
1296             //clean section between m_iSize and iOldSizeMax
1297             for (int i = m_iSize; i < iOldSizeMax; ++i)
1298             {
1299                 deleteData(m_pRealData[i]);
1300                 m_pRealData[i] = NULL;
1301             }
1302
1303             //if (iPreviousNewIdx < iOldSizeMax)
1304             //{
1305             //    for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1306             //    {
1307             //        pRealData[i] = m_pRealData[i];
1308             //        m_pRealData[i] = NULL;
1309             //    }
1310             //}
1311             //else
1312             //{
1313             //    iOldSizeMax = iPreviousNewIdx;
1314             //}
1315
1316             //fill exceeded with NullValue
1317             for (int i = iPreviousNewIdx; i < m_iSizeMax; ++i)
1318             {
1319                 T pTemp = getNullValue();
1320                 T pTemp2 = copyValue(pTemp);
1321                 pRealData[i] = pTemp2;
1322                 if (pTemp != pTemp2)
1323                 {
1324                     deleteData(pTemp);
1325                 }
1326             }
1327
1328             delete[] piIndexes;
1329             //delete all array
1330             delete[] m_pRealData;
1331             //replace old array by new one
1332             m_pRealData = pRealData;
1333         }
1334         else
1335         {
1336             //check if only the last dims change
1337             bool bNonLastDimChange = false;
1338             for (int i = 0 ; i < (m_iDims - 1) ; i++)
1339             {
1340                 if (m_piDims[i] != _piDims[i])
1341                 {
1342                     bNonLastDimChange = true;
1343                     break;
1344                 }
1345             }
1346
1347             //if vector or if row dimension not change, we don't need to shift data
1348             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1349             {
1350                 //copy values into new one
1351                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1352                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1353                 for (int i = m_iSize - 1 ; i >= 0  ; i--)
1354                 {
1355                     getIndexes(i, piIndexes);
1356                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1357                     if (iNewIdx != i)
1358                     {
1359                         T pTemp = m_pRealData[iNewIdx];
1360                         m_pRealData[iNewIdx] = m_pRealData[i];
1361                         m_pRealData[i] = pTemp;
1362                     }
1363                 }
1364                 delete[] piIndexes;
1365             }
1366         }
1367     }
1368
1369     if (_iDims != m_iDims)
1370     {
1371         //int* piDims = new int[_iDims];
1372         for (int i = 0 ; i < _iDims ; i++)
1373         {
1374             m_piDims[i] = _piDims[i];
1375         }
1376         //delete[] m_piDims;
1377         //m_piDims = piDims;
1378         m_iDims = _iDims;
1379     }
1380     else
1381     {
1382         for (int i = 0 ; i < m_iDims ; i++)
1383         {
1384             m_piDims[i] = _piDims[i];
1385         }
1386     }
1387     m_iRows = m_piDims[0];
1388     m_iCols = m_piDims[1];
1389     m_iSize = iNewSize;
1390     return true;
1391 }
1392
1393
1394 // used to allow definition of ArrayOf methode in this cpp file.
1395 template class EXTERN_AST ArrayOf<char>;
1396 template class EXTERN_AST ArrayOf<unsigned char>;
1397 template class EXTERN_AST ArrayOf<short>;
1398 template class EXTERN_AST ArrayOf<unsigned short>;
1399 template class EXTERN_AST ArrayOf<int>;
1400 template class EXTERN_AST ArrayOf<unsigned int>;
1401 template class EXTERN_AST ArrayOf<long long>;
1402 template class EXTERN_AST ArrayOf<unsigned long long>;
1403 template class EXTERN_AST ArrayOf<double>;
1404 template class EXTERN_AST ArrayOf<wchar_t*>;
1405 template class EXTERN_AST ArrayOf<SinglePoly*>;
1406 template class EXTERN_AST ArrayOf<SingleStruct*>;
1407 template class EXTERN_AST ArrayOf<InternalType*>; // Cell
1408 }