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