Leak memory in elementary_functions tests
[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             return _pSource;
489         }
490
491         //vector case
492         if (pSource->isVector() && iCompteurNull == 1)
493         {
494             piMaxDim[iLastNull] = pSource->getSize();
495             pArg[iLastNull] = createDoubleVector(piMaxDim[iLastNull]);
496         }
497         else
498         {
499             //matrix and hypermatrix case
500             if (iCompteurNull < pSource->getDims())
501             {
502                 delete[] piMaxDim;
503                 delete[] piCountDim;
504                 //free pArg content
505                 cleanIndexesArguments(_pArgs, &pArg);
506                 //contain bad index, like <= 0, ...
507                 return NULL;
508             }
509
510             //replace ":" by know source dimensions
511             int iSource = 0;
512             for (int i = 0; i < iDims; ++i)
513             {
514                 if (pArg[i] == NULL)
515                 {
516                     if (iSource < iSourceDims)
517                     {
518                         piMaxDim[i] = piSourceDims[iSource];
519                         pArg[i] = createDoubleVector(piMaxDim[i]);
520                         ++iSource;
521                     }
522                     else
523                     {
524                         //fill dimensions after pSource->getDimes() with 1
525                         piMaxDim[i] = 1;
526                         pArg[i] = createDoubleVector(piMaxDim[i]);
527                     }
528                 }
529             }
530         }
531     }
532
533     //remove last dimension at size 1
534     //remove last dimension if are == 1
535     for (int i = (iDims - 1) ; i >= 2 ; i--)
536     {
537         if (piMaxDim[i] == 1)
538         {
539             iDims--;
540             pArg.back()->killMe();
541             pArg.pop_back();
542         }
543         else
544         {
545             break;
546         }
547     }
548
549     if (checkArgValidity(pArg) == false)
550     {
551         delete[] piMaxDim;
552         delete[] piCountDim;
553         //free pArg content
554         cleanIndexesArguments(_pArgs, &pArg);
555         //contain bad index, like <= 0, ...
556         return NULL;
557     }
558
559     if (iDims == 1)
560     {
561         if (pSource->getCols() == 1)
562         {
563             int piRealDim[2] = {piMaxDim[0], 1};
564             pOut = pSource->createEmpty(2, piRealDim, bComplex);
565         }
566         else
567         {
568             //rows == 1
569             int piRealDim[2] = {1, piMaxDim[0]};
570             pOut = pSource->createEmpty(2, piRealDim, bComplex);
571         }
572     }
573     else
574     {
575         pOut = pSource->createEmpty(iDims, piMaxDim, bComplex);
576     }
577
578     //fill with null item
579     ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
580     T* pRealData = pArrayOut->get();
581     if (bComplex)
582     {
583         T* pImgData = pArrayOut->getImg();
584         for (int i = 0 ; i < pArrayOut->getSize() ; i++)
585         {
586             pArrayOut->deleteData(pRealData[i]);
587             pRealData[i] = pSource->getNullValue();
588             pArrayOut->deleteData(pImgData[i]);
589             pImgData[i] = pSource->getNullValue();
590         }
591     }
592     else
593     {
594         for (int i = 0 ; i < pArrayOut->getSize() ; i++)
595         {
596             pArrayOut->deleteData(pRealData[i]);
597             pRealData[i] = pSource->getNullValue();
598         }
599     }
600
601     if (bIsImpli && (pArrayOut->getSize() != _pSource->getAs<types::GenericType>()->getSize()))
602     {
603         delete[] piMaxDim;
604         delete[] piCountDim;
605         //free pArg content
606         cleanIndexesArguments(_pArgs, &pArg);
607         return NULL;
608     }
609     //insert values in new matrix
610     InternalType* pOut2 = pArrayOut->insert(&pArg, _pSource);
611     if (pOut != pOut2)
612     {
613         delete pOut;
614     }
615
616     delete[] piMaxDim;
617     delete[] piCountDim;
618     //free pArg content
619     cleanIndexesArguments(_pArgs, &pArg);
620
621     return pOut2;
622 }
623
624 template <typename T>
625 bool ArrayOf<T>::append(int _iRows, int _iCols, InternalType* _poSource)
626 {
627     ArrayOf * pGT = _poSource->getAs<ArrayOf>();
628     int iRows = pGT->getRows();
629     int iCols = pGT->getCols();
630
631     //insert without resize
632     if (iRows + _iRows > m_iRows || iCols + _iCols > m_iCols)
633     {
634         return false;
635     }
636
637     //Update complexity if necessary
638     if (pGT->isComplex())
639     {
640         setComplex(true);
641     }
642     else if (isComplex())
643     {
644         pGT->setComplex(true);
645     }
646
647     if (pGT->isComplex())
648     {
649         for (int i = 0 ; i < iRows ; i++)
650         {
651             for (int j = 0 ; j < iCols ; j++)
652             {
653                 set(_iRows + i, _iCols + j, pGT->get(i, j));
654                 setImg(_iRows + i, _iCols + j, pGT->getImg(i, j));
655             }
656         }
657     }
658     else
659     {
660         for (int i = 0 ; i < iRows ; i++)
661         {
662             for (int j = 0 ; j < iCols ; j++)
663             {
664                 set(_iRows + i, _iCols + j, pGT->get(i, j));
665             }
666         }
667     }
668
669     return true;
670 }
671
672 template <typename T>
673 InternalType* ArrayOf<T>::remove(typed_list* _pArgs)
674 {
675     ArrayOf<T>* pOut    = NULL;
676     int iDims           = (int)_pArgs->size();
677     typed_list pArg;
678
679     int* piMaxDim       = new int[iDims];
680     int* piCountDim     = new int[iDims];
681
682     //evaluate each argument and replace by appropriate value and compute the count of combinations
683     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
684     delete[] piMaxDim;
685     delete[] piCountDim;
686     if (iSeqCount == 0)
687     {
688         //free pArg content
689         cleanIndexesArguments(_pArgs, &pArg);
690         //no Seq, no change but no error.
691         return this;
692     }
693
694     bool* pbFull = new bool[iDims];
695     //coord must represent all values on a dimension
696     for (int i = 0 ; i < iDims ; i++)
697     {
698         pbFull[i]       = false;
699         int iDimToCheck = getVarMaxDim(i, iDims);
700         int iIndexSize  = pArg[i]->getAs<GenericType>()->getSize();
701
702         //we can have index more than once
703         if (iIndexSize >= iDimToCheck)
704         {
705             //size is good, now check datas
706             double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
707             for (int j = 0 ; j < iDimToCheck ; j++)
708             {
709                 bool bFind = false;
710                 for (int k = 0 ; k < iIndexSize ; k++)
711                 {
712                     if ((int)pIndexes[k] == j + 1)
713                     {
714                         bFind = true;
715                         break;
716                     }
717                 }
718                 pbFull[i]  = bFind;
719             }
720         }
721     }
722
723     //only one dims can be not full/entire
724     bool bNotEntire = false;
725     int iNotEntire  = 0;
726     bool bTooMuchNotEntire = false;
727     for (int i = 0 ; i < iDims ; i++)
728     {
729         if (pbFull[i] == false)
730         {
731             if (bNotEntire == false)
732             {
733                 bNotEntire = true;
734                 iNotEntire = i;
735             }
736             else
737             {
738                 bTooMuchNotEntire = true;
739                 break;
740             }
741         }
742     }
743
744     if (bTooMuchNotEntire == true)
745     {
746         //free pArg content
747         cleanIndexesArguments(_pArgs, &pArg);
748         return NULL;
749     }
750
751     delete[] pbFull;
752
753     //find index to keep
754     int iNotEntireSize          = pArg[iNotEntire]->getAs<GenericType>()->getSize();
755     double* piNotEntireIndex    = getDoubleArrayFromDouble(pArg[iNotEntire]);
756     int iKeepSize               = getVarMaxDim(iNotEntire, iDims);
757     bool* pbKeep                = new bool[iKeepSize];
758
759     //fill pbKeep with true value
760     for (int i = 0 ; i < iKeepSize ; i++)
761     {
762         pbKeep[i] = true;
763     }
764
765     for (int i = 0 ; i < iNotEntireSize ; i++)
766     {
767         int idx = (int)piNotEntireIndex[i] - 1;
768
769         //don't care of value out of bounds
770         if (idx < iKeepSize)
771         {
772             pbKeep[idx] = false;
773         }
774     }
775
776     int iNewDimSize = 0;
777     for (int i = 0 ; i < iKeepSize ; i++)
778     {
779         if (pbKeep[i] == true)
780         {
781             iNewDimSize++;
782         }
783     }
784     delete[] pbKeep;
785
786     int* piNewDims = new int[iDims];
787     for (int i = 0 ; i < iDims ; i++)
788     {
789         if (i == iNotEntire)
790         {
791             piNewDims[i] = iNewDimSize;
792         }
793         else
794         {
795             piNewDims[i] = getVarMaxDim(i, iDims);
796         }
797     }
798
799     //remove last dimension if are == 1
800     int iOrigDims = iDims;
801     for (int i = (iDims - 1) ; i >= 2 ; i--)
802     {
803         if (piNewDims[i] == 1)
804         {
805             iDims--;
806         }
807         else
808         {
809             break;
810         }
811     }
812
813     if (iNewDimSize == 0)
814     {
815         //free pArg content
816         cleanIndexesArguments(_pArgs, &pArg);
817         delete[] piNewDims;
818         return createEmptyDouble();
819     }
820
821     if (iDims == 1)
822     {
823         //two cases, depends of original matrix/vector
824         if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
825         {
826             //special case for row vector
827             int piRealDim[2] = {1, iNewDimSize};
828             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
829             //in this case we have to care of 2nd dimension
830             //iNotEntire = 1;
831         }
832         else
833         {
834             int piRealDim[2] = {iNewDimSize, 1};
835             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
836         }
837     }
838     else
839     {
840         pOut = createEmpty(iDims, piNewDims, m_pImgData != NULL);
841     }
842
843     delete[] piNewDims;
844     //find a way to copy existing data to new variable ...
845     int iNewPos = 0;
846     int* piIndexes = new int[iOrigDims];
847     int* piViewDims = new int[iOrigDims];
848     for (int i = 0 ; i < iOrigDims ; i++)
849     {
850         piViewDims[i] = getVarMaxDim(i, iOrigDims);
851     }
852
853     for (int i = 0 ; i < getSize() ; i++)
854     {
855         bool bByPass = false;
856         getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
857
858         //check if piIndexes use removed indexes
859         for (int j = 0 ; j < iNotEntireSize ; j++)
860         {
861             if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
862             {
863                 //by pass this value
864                 bByPass = true;
865                 break;
866             }
867         }
868
869         if (bByPass == false)
870         {
871             //compute new index
872             pOut->set(iNewPos, get(i));
873             if (m_pImgData != NULL)
874             {
875                 pOut->setImg(iNewPos, getImg(i));
876             }
877             iNewPos++;
878         }
879     }
880
881     //free pArg content
882     cleanIndexesArguments(_pArgs, &pArg);
883
884     delete[] piIndexes;
885     delete[] piViewDims;
886     return pOut;
887 }
888
889 template <typename T>
890 InternalType* ArrayOf<T>::extract(typed_list* _pArgs)
891 {
892     ArrayOf<T>* pOut    = NULL;
893     int iDims           = (int)_pArgs->size();
894     typed_list pArg;
895
896     int* piMaxDim       = new int[iDims];
897     int* piCountDim     = new int[iDims];
898
899     //evaluate each argument and replace by appropriate value and compute the count of combinations
900     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
901     if (iSeqCount == 0)
902     {
903         delete[] piMaxDim;
904         delete[] piCountDim;
905         //free pArg content
906         cleanIndexesArguments(_pArgs, &pArg);
907         return createEmptyDouble();
908     }
909
910     if (iSeqCount < 0)
911     {
912         return NULL;
913     }
914
915     if (iDims < m_iDims)
916     {
917         for (int i = 0 ; i < iDims ; i++)
918         {
919             int iDimToCheck = 0;
920             if (i == (iDims - 1))
921             {
922                 iDimToCheck = getVarMaxDim(i, iDims);
923             }
924             else
925             {
926                 iDimToCheck = m_piDims[i];
927             }
928
929             if (piMaxDim[i] > iDimToCheck)
930             {
931                 delete[] piMaxDim;
932                 delete[] piCountDim;
933                 //free pArg content
934                 cleanIndexesArguments(_pArgs, &pArg);
935                 return NULL;
936             }
937         }
938     }
939     else
940     {
941         if (iDims > m_iDims)
942         {
943             for (int i = m_iDims ; i < iDims ; i++)
944             {
945                 if (piMaxDim[i] > 1)
946                 {
947                     delete[] piMaxDim;
948                     delete[] piCountDim;
949                     //free pArg content
950                     cleanIndexesArguments(_pArgs, &pArg);
951                     return NULL;
952                 }
953             }
954         }
955
956         //check MaxDim
957         for (int i = 0 ; i < m_iDims ; i++)
958         {
959             if (piMaxDim[i] > m_piDims[i])
960             {
961                 delete[] piMaxDim;
962                 delete[] piCountDim;
963                 //free pArg content
964                 cleanIndexesArguments(_pArgs, &pArg);
965                 //exrtact must be in dimension limits
966                 return NULL;
967             }
968         }
969     }
970
971     //remove last dimension if are == 1
972     for (int i = (iDims - 1) ; i >= 2 ; i--)
973     {
974         if (piCountDim[i] == 1)
975         {
976             (iDims)--;
977         }
978         else
979         {
980             break;
981         }
982     }
983
984     //vector
985     if (iDims == 1)
986     {
987         if (piCountDim[0] == 0)
988         {
989             delete[] piMaxDim;
990             delete[] piCountDim;
991             //free pArg content
992             cleanIndexesArguments(_pArgs, &pArg);
993             return createEmptyDouble();
994         }
995         else
996         {
997             //two cases, depends of original matrix/vector
998             if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[1] != 1 && m_piDims[0] == 1)
999             {
1000                 //special case for row vector
1001                 int piRealDim[2] = {1, piCountDim[0]};
1002                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1003             }
1004             else
1005             {
1006                 if (getSize() == 1)
1007                 {
1008                     //for extraction on scalar
1009                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), pArg[0]->getAs<GenericType>()->getDimsArray(), m_pImgData != NULL);
1010                 }
1011                 else
1012                 {
1013                     int piRealDim[2] = {piCountDim[0], 1};
1014                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1015                 }
1016             }
1017         }
1018     }
1019     else
1020     {
1021         //matrix
1022         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1023     }
1024
1025     int* piIndex    = new int[_pArgs->size()];
1026     int* piCoord    = new int[_pArgs->size()];
1027     int* piViewDims = new int[iDims];
1028     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1029
1030     for (int i = 0 ; i < iDims ; i++)
1031     {
1032         piViewDims[i] = getVarMaxDim(i, iDims);
1033     }
1034
1035     for (int i = 0 ; i < iSeqCount ; i++)
1036     {
1037         //increment last dimension
1038         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1039
1040         //std::cout << "[";
1041         for (int j = 0 ; j < (int)_pArgs->size() ; j++)
1042         {
1043             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1044             //InternalType* pVar = pArg[i];
1045             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1046             //std::cout << piCoord[j] << " ";
1047
1048             // try to access somewhere wrong.
1049             if (piCoord[j] < 0)
1050             {
1051                 delete[] piIndex;
1052                 delete[] piCoord;
1053                 delete[] piViewDims;
1054                 delete[] piMaxDim;
1055                 delete[] piCountDim;
1056
1057                 //free pArg content
1058                 cleanIndexesArguments(_pArgs, &pArg);
1059                 return NULL;
1060             }
1061         }
1062
1063         //std::cout << "]" << std::endl;
1064
1065         int iPos = 0;
1066         //put vlaue in the new matrix
1067         if ((int)_pArgs->size() < m_iDims)
1068         {
1069             //compute index based on viewed matrix
1070             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1071         }
1072         else
1073         {
1074             //compute vector index
1075             iPos = getIndex(piCoord);
1076         }
1077
1078         //convert flat dimension to 0
1079         for (int j = 0 ; j < iDims ; j++)
1080         {
1081             if (piCountDim[j] == 1)
1082             {
1083                 piCoord[j] = 0;
1084             }
1085         }
1086
1087         pOut->set(i, get(iPos));
1088         if (m_pImgData != NULL)
1089         {
1090             pOut->setImg(i, getImg(iPos));
1091         }
1092
1093
1094         piIndex[0]++;
1095     }
1096
1097     //free pArg content
1098     cleanIndexesArguments(_pArgs, &pArg);
1099
1100     delete[] piIndex;
1101     delete[] piCoord;
1102     delete[] piViewDims;
1103     delete[] piMaxDim;
1104     delete[] piCountDim;
1105
1106     return pOut;
1107 }
1108
1109 template <typename T>
1110 bool ArrayOf<T>::resize(int* _piDims, int _iDims)
1111 {
1112     if (_iDims == m_iDims)
1113     {
1114         bool bChange = false;
1115         for (int i = 0 ; i < _iDims ; i++)
1116         {
1117             if (m_piDims[i] != _piDims[i])
1118             {
1119                 bChange = true;
1120                 break;
1121             }
1122         }
1123
1124         if (bChange == false)
1125         {
1126             //nothing to do
1127             return true;
1128         }
1129     }
1130
1131     //alloc new data array
1132     T* pRealData = NULL;
1133     T* pImgData = NULL;
1134
1135     int iNewSize = 0;
1136     if (m_pImgData != NULL)
1137     {
1138         iNewSize = get_max_size(_piDims, _iDims);
1139         if (m_iSizeMax < iNewSize)
1140         {
1141             //alloc 10% bigger than asked to prevent future resize
1142             int iOldSizeMax = m_iSizeMax;
1143             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1144             pRealData = allocData(m_iSizeMax);
1145             pImgData  = allocData(m_iSizeMax);
1146
1147             //copy values into new one
1148             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1149             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1150             for (int i = 0; i < _iDims; i++)
1151             {
1152                 piIndexes[i] = 0;
1153             }
1154
1155             int iPreviousNewIdx = 0;
1156             for (int i = 0; i < m_iSize; i++)
1157             {
1158                 getIndexes(i, piIndexes);
1159                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1160                 pRealData[iNewIdx] = m_pRealData[i];
1161                 pImgData[iNewIdx]  = m_pImgData[i];
1162                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1163                 {
1164                     T pTemp = getNullValue();
1165                     pRealData[j] = copyValue(pTemp);
1166                     pImgData[j]  = copyValue(pTemp);
1167                     if (pTemp != pRealData[j])
1168                     {
1169                         deleteData(pTemp);
1170                     }
1171                 }
1172
1173                 iPreviousNewIdx = iNewIdx + 1;
1174             }
1175
1176             // if it's not the first resize,
1177             // fill new data with element of last allocation
1178             if (iPreviousNewIdx < iOldSizeMax)
1179             {
1180                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1181                 {
1182                     pRealData[i] = m_pRealData[i];
1183                     pImgData[i] = m_pImgData[i];
1184                 }
1185             }
1186             else
1187             {
1188                 // first resize, iOldSizeMax don't contain the 10%
1189                 iOldSizeMax = iPreviousNewIdx;
1190             }
1191
1192             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1193             {
1194                 T pTemp = getNullValue();
1195                 pRealData[i] = copyValue(pTemp);
1196                 pImgData[i]  = copyValue(pTemp);
1197                 if (pTemp != pRealData[i])
1198                 {
1199                     deleteData(pTemp);
1200                 }
1201             }
1202
1203             delete[] piIndexes;
1204             //delete all array
1205             delete[] m_pRealData;
1206             delete[] m_pImgData;
1207             //replace old array by new one
1208             m_pRealData = pRealData;
1209             m_pImgData = pImgData;
1210         }
1211         else
1212         {
1213             //check if only the last dims change
1214             bool bNonLastDimChange = false;
1215             for (int i = 0; i < (m_iDims - 1); i++)
1216             {
1217                 if (m_piDims[i] != _piDims[i])
1218                 {
1219                     bNonLastDimChange = true;
1220                     break;
1221                 }
1222             }
1223
1224             //if vector or if row dimension not change, we don't need to shift data
1225             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1226             {
1227                 //copy values into new one
1228                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1229                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1230                 for (int i = m_iSize - 1; i >= 0; i--)
1231                 {
1232                     getIndexes(i, piIndexes);
1233                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1234                     if (iNewIdx != i)
1235                     {
1236                         T pTemp = m_pRealData[iNewIdx];
1237                         m_pRealData[iNewIdx] = m_pRealData[i];
1238                         m_pRealData[i] = pTemp;
1239
1240                         pTemp = m_pImgData[iNewIdx];
1241                         m_pImgData[iNewIdx] = m_pImgData[i];
1242                         m_pImgData[i] = pTemp;
1243                     }
1244                 }
1245                 delete[] piIndexes;
1246             }
1247         }
1248     }
1249     else
1250     {
1251         iNewSize = get_max_size(_piDims, _iDims);
1252         if (m_iSizeMax < iNewSize)
1253         {
1254             //alloc 10% bigger than asked to prevent future resize
1255             int iOldSizeMax = m_iSizeMax;
1256             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1257             pRealData = allocData(m_iSizeMax);
1258
1259             //copy values into new one
1260             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1261             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1262             for (int i = 0 ; i < _iDims ; i++)
1263             {
1264                 piIndexes[i] = 0;
1265             }
1266
1267             int iPreviousNewIdx = 0;
1268             for (int i = 0 ; i < m_iSize ; i++)
1269             {
1270                 getIndexes(i, piIndexes);
1271                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1272                 pRealData[iNewIdx] = m_pRealData[i];
1273                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1274                 {
1275                     T pTemp = getNullValue();
1276                     T pTemp2 = copyValue(pTemp);
1277                     pRealData[j] = pTemp2;
1278                     if (pTemp != pTemp2)
1279                     {
1280                         deleteData(pTemp);
1281                     }
1282                 }
1283
1284                 iPreviousNewIdx = iNewIdx + 1;
1285             }
1286
1287             // if it's not the first resize,
1288             // fill new data with element of last allocation
1289             if (iPreviousNewIdx < iOldSizeMax)
1290             {
1291                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1292                 {
1293                     pRealData[i] = m_pRealData[i];
1294                 }
1295             }
1296             else
1297             {
1298                 // first resize, iOldSizeMax don't contain the 10%
1299                 iOldSizeMax = iPreviousNewIdx;
1300             }
1301
1302             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1303             {
1304                 T pTemp = getNullValue();
1305                 T pTemp2 = copyValue(pTemp);
1306                 pRealData[i] = pTemp2;
1307                 if (pTemp != pTemp2)
1308                 {
1309                     deleteData(pTemp);
1310                 }
1311             }
1312
1313             delete[] piIndexes;
1314             //delete all array
1315             delete[] m_pRealData;
1316             //replace old array by new one
1317             m_pRealData = pRealData;
1318         }
1319         else
1320         {
1321             //check if only the last dims change
1322             bool bNonLastDimChange = false;
1323             for (int i = 0 ; i < (m_iDims - 1) ; i++)
1324             {
1325                 if (m_piDims[i] != _piDims[i])
1326                 {
1327                     bNonLastDimChange = true;
1328                     break;
1329                 }
1330             }
1331
1332             //if vector or if row dimension not change, we don't need to shift data
1333             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1334             {
1335                 //copy values into new one
1336                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1337                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1338                 for (int i = m_iSize - 1 ; i >= 0  ; i--)
1339                 {
1340                     getIndexes(i, piIndexes);
1341                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1342                     if (iNewIdx != i)
1343                     {
1344                         T pTemp = m_pRealData[iNewIdx];
1345                         m_pRealData[iNewIdx] = m_pRealData[i];
1346                         m_pRealData[i] = pTemp;
1347                     }
1348                 }
1349                 delete[] piIndexes;
1350             }
1351         }
1352     }
1353
1354     if (_iDims != m_iDims)
1355     {
1356         //int* piDims = new int[_iDims];
1357         for (int i = 0 ; i < _iDims ; i++)
1358         {
1359             m_piDims[i] = _piDims[i];
1360         }
1361         //delete[] m_piDims;
1362         //m_piDims = piDims;
1363         m_iDims = _iDims;
1364     }
1365     else
1366     {
1367         for (int i = 0 ; i < m_iDims ; i++)
1368         {
1369             m_piDims[i] = _piDims[i];
1370         }
1371     }
1372     m_iRows = m_piDims[0];
1373     m_iCols = m_piDims[1];
1374     m_iSize = iNewSize;
1375     return true;
1376 }
1377
1378
1379 // used to allow definition of ArrayOf methode in this cpp file.
1380 template class EXTERN_AST ArrayOf<char>;
1381 template class EXTERN_AST ArrayOf<unsigned char>;
1382 template class EXTERN_AST ArrayOf<short>;
1383 template class EXTERN_AST ArrayOf<unsigned short>;
1384 template class EXTERN_AST ArrayOf<int>;
1385 template class EXTERN_AST ArrayOf<unsigned int>;
1386 template class EXTERN_AST ArrayOf<long long>;
1387 template class EXTERN_AST ArrayOf<unsigned long long>;
1388 template class EXTERN_AST ArrayOf<double>;
1389 template class EXTERN_AST ArrayOf<wchar_t*>;
1390 template class EXTERN_AST ArrayOf<SinglePoly*>;
1391 template class EXTERN_AST ArrayOf<SingleStruct*>;
1392 template class EXTERN_AST ArrayOf<InternalType*>; // Cell
1393 }