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