* Bug 15087 fixed: deleting rows or cols from matrix was slow
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16 #include "arrayof.hxx"
17 #include "double.hxx"
18 #include "bool.hxx"
19 #include "singlepoly.hxx"
20 #include "singlestruct.hxx"
21 #include "type_traits.hxx"
22 #include "exp.hxx"
23 #include "types_tools.hxx"
24
25 extern "C"
26 {
27 #include "dynlib_ast.h"
28 #include "sciprint.h"
29 }
30
31 namespace types
32 {
33
34 static int get_max_size(int* _piDims, int _iDims)
35 {
36     if (_iDims == 0)
37     {
38         return 0;
39     }
40
41     int iMax = 1;
42     for (int i = 0 ; i < _iDims ; i++)
43     {
44         iMax *= _piDims[i];
45     }
46     return iMax;
47 }
48
49 template <typename T>
50 GenericType* ArrayOf<T>::createEmpty()
51 {
52     return createEmptyDouble();
53 }
54
55 template <typename T>
56 bool ArrayOf<T>::getMemory(int* _piSize, int* _piSizePlusType)
57 {
58     *_piSize = getSize() * sizeof(T) * (isComplex() ? 2 : 1);
59     *_piSizePlusType = *_piSize + sizeof(*this);
60     return true;
61 }
62
63 template <typename T>
64 void ArrayOf<T>::getIndexes(int _iIndex, int* _piIndexes)
65 {
66     getIndexesWithDims(_iIndex, _piIndexes, m_piDims, m_iDims);
67 }
68
69 template <typename T>
70 ArrayOf<T>* ArrayOf<T>::insert(typed_list* _pArgs, InternalType* _pSource)
71 {
72     ArrayOf<T>* pIT = checkRef(this, &ArrayOf::insert, _pArgs, _pSource);
73     if (pIT != this)
74     {
75         return pIT;
76     }
77
78     int index;
79     if (getScalarIndex(this, _pArgs, &index))
80     {
81         ArrayOf* pIns = _pSource->getAs<ArrayOf>();
82         int sizeIn = pIns->getSize();
83         //only scalar can be used to ".=" operation
84         if (sizeIn != 1)
85         {
86             return NULL;
87         }
88
89         T* pRealData = pIns->get();
90         T* pImgData = pIns->getImg();
91
92         if (isComplex() == false && pIns->isComplex() == false)
93         {
94             if (isNativeType() && index < m_iSize)
95             {
96                 m_pRealData[index] = *pRealData;
97                 return this;
98             }
99             else
100             {
101                 if (set(index, *pRealData) != NULL)
102                 {
103                     return this;
104                 }
105             }
106         }
107
108         //if complex continue
109     }
110
111     typed_list pArg;
112     int iDims = (int)_pArgs->size();
113     int* piMaxDim = new int[iDims];
114     int* piCountDim = new int[iDims];
115     //evaluate each argument and replace by appropriate value and compute the count of combinations
116     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
117
118     if (iSeqCount == 0)
119     {
120         //free pArg content
121         delete[] piCountDim;
122         delete[] piMaxDim;
123         cleanIndexesArguments(_pArgs, &pArg);
124         return this;
125     }
126
127     ArrayOf* pSource = _pSource->getAs<ArrayOf>();
128
129     //only scalar can be used to ".=" operation
130     if (iSeqCount != pSource->getSize() && pSource->isScalar() == false)
131     {
132         delete[] piCountDim;
133         delete[] piMaxDim;
134         //free pArg content
135         cleanIndexesArguments(_pArgs, &pArg);
136         return NULL;
137     }
138
139     //remove last dimension at size 1
140     //remove last dimension if are == 1
141     for (int i = (iDims - 1); i >= m_iDims; i--)
142     {
143         if (piMaxDim[i] == 1)
144         {
145             iDims--;
146             pArg.back()->killMe();
147             pArg.pop_back();
148         }
149         else
150         {
151             break;
152         }
153     }
154
155
156     //insertion of a scalar is always possible regardless of index dimensions
157     if (pSource->isScalar() == false)
158     {
159         int *piSourceDims = pSource->getDimsArray();
160         int sDims = pSource->getDims();
161         int j=0;
162
163         for (int i=0; i<iDims; i++)
164         {
165             if (piCountDim[i]==1)
166             {
167                 continue;
168             }
169             while (j<sDims && piSourceDims[j]==1) j++;
170             if (piSourceDims[j] != piCountDim[i])
171             {
172                 delete[] piCountDim;
173                 delete[] piMaxDim;
174                 //free pArg content
175                 cleanIndexesArguments(_pArgs, &pArg);
176                 return NULL;
177             }
178             j++;
179         }
180     }
181
182     std::vector<int> indexes;
183     std::vector<int> dims;
184     if (getImplicitIndex(this, _pArgs, indexes, dims))
185     {
186         if (indexes.size() == 0)
187         {
188             delete[] piCountDim;
189             delete[] piMaxDim;
190             //free pArg content
191             cleanIndexesArguments(_pArgs, &pArg);
192             return this;
193         }
194
195         ArrayOf* pIns = _pSource->getAs<ArrayOf>();
196         int sizeIn = pIns->getSize();
197         int count = static_cast<int>(indexes.size());
198         //only scalar can be used to ".=" operation
199         if (sizeIn != 1 && count != sizeIn)
200         {
201             delete[] piCountDim;
202             delete[] piMaxDim;
203             //free pArg content
204             cleanIndexesArguments(_pArgs, &pArg);
205             return NULL;
206         }
207
208         T* pRealData = pIns->get();
209         T* pImgData = pIns->getImg();
210
211         bool status = true;
212         if (isComplex() == false && pIns->isComplex() == false)
213         {
214             if (sizeIn == 1)
215             {
216                 if (isNativeType())
217                 {
218                     for (int i : indexes)
219                     {
220                         if (i >= m_iSize)
221                         {
222                             status = false;
223                             break;
224                         }
225
226                         m_pRealData[i] = *pRealData;
227                     }
228                 }
229                 else
230                 {
231                     for (int i : indexes)
232                     {
233                         if (set(i, *pRealData) == NULL)
234                         {
235                             status = false;
236                             break;
237                         }
238                     }
239                 }
240             }
241             else
242             {
243                 if (isNativeType())
244                 {
245                     for (int i : indexes)
246                     {
247                         if (i >= m_iSize)
248                         {
249                             status = false;
250                             break;
251                         }
252
253                         m_pRealData[i] = *pRealData;
254                         ++pRealData;
255                     }
256                 }
257                 else
258                 {
259                     for (int i : indexes)
260                     {
261                         if (set(i, *pRealData) == NULL)
262                         {
263                             status = false;
264                             break;
265                         }
266                         ++pRealData;
267                     }
268                 }
269             }
270
271             if (status)
272             {
273                 delete[] piCountDim;
274                 delete[] piMaxDim;
275                 //free pArg content
276                 cleanIndexesArguments(_pArgs, &pArg);
277                 return this;
278             }
279
280             //if status is false, continue to entire process
281         }
282     }
283
284     bool bNeedToResize = false;
285     int iDimsOrigine = m_iDims;
286
287     //on case of resize
288     int* piNewDims = NULL;
289     int iNewDims = 0;
290
291     bool bIsColon = false;
292
293     if (iDims >= m_iDims)
294     {
295         //all case are good, we can do almost everything
296         //check if resize is needed
297         if (iDims > m_iDims)
298         {
299             bNeedToResize = true;
300         }
301         else //_iDims == m_iDims
302         {
303             for (int i = 0; i < m_iDims; i++)
304             {
305                 if (m_piDims[i] < piMaxDim[i])
306                 {
307                     bNeedToResize = true;
308                     break;
309                 }
310             }
311         }
312
313         //determine new dimension of the matrix
314         if (bNeedToResize == true)
315         {
316             iNewDims = iDims;
317             piNewDims = new int[iNewDims];
318             for (int i = 0; i < m_iDims; i++)
319             {
320                 piNewDims[i] = std::max(piMaxDim[i], m_piDims[i]);
321             }
322
323             int iSource = (pSource->getDims() - 1);
324             bool bPassed = false;
325             int *piSourceDims = pSource->getDimsArray();
326
327             for (int i = m_iDims; i < iNewDims; ++i)
328             {
329                 piNewDims[i] = piMaxDim[i];
330             }
331         }
332     }
333     else // _iDims < m_iDims
334     {
335         if (isVector() || isScalar() || getSize() == 0) //getSize() == 0, only for [] and {}
336         {
337             if (getSize() < piMaxDim[0])
338             {
339                 bNeedToResize = true;
340                 iNewDims = 2;
341                 piNewDims = new int[2]{1,1};
342
343                 if (isScalar() || getSize() == 0)
344                 {
345                     int *piSourceDims = pSource->getDimsArray();
346                     // if source is scalar then resize indexed array as a column vector
347                     // otherwise resize with shape of source
348                     piNewDims[(int)(piSourceDims[0] == 1 && pSource->getSize()>1)]=piMaxDim[0];
349                 }
350                 else // resize with same shape as indexed array
351                 {
352                     piNewDims[(int)(getRows() == 1)]=piMaxDim[0];
353                 }
354             }
355         }
356         else
357         {
358             //each index before last index must be in range of his dimension
359             //and last given dimension can not be > prod(last dimensions)
360             for (int i = 0; i < iDims - 1; i++)
361             {
362                 //indexes are always doubles
363                 double* pIdx = getDoubleArrayFromDouble(pArg[i]);
364                 //InternalType* pVar = pArg[i];
365                 //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
366                 int iSize = pArg[i]->getAs<ArrayOf>()->getSize();
367                 for (int j = 0; j < iSize; j++)
368                 {
369                     if (pIdx[j] > m_piDims[i])
370                     {
371                         delete[] piCountDim;
372                         delete[] piMaxDim;
373                         //free pArg content
374                         cleanIndexesArguments(_pArgs, &pArg);
375                         return NULL;
376                     }
377                 }
378             }
379
380             //check last dim
381             int iMaxLastDim = getVarMaxDim(iDims - 1, iDims);
382             double* pIdx = getDoubleArrayFromDouble(pArg[pArg.size() - 1]);
383             //InternalType* pVar = pArg[pArg.size() - 1];
384             //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
385             int iSize = pArg[pArg.size() - 1]->getAs<GenericType>()->getSize();
386             for (int i = 0; i < iSize; i++)
387             {
388                 if (pIdx[i] > iMaxLastDim)
389                 {
390                     delete[] piCountDim;
391                     delete[] piMaxDim;
392                     //free pArg content
393                     cleanIndexesArguments(_pArgs, &pArg);
394                     return NULL;
395                 }
396             }
397         }
398     }
399
400     //update complexity *before* first resizing
401     if (pSource->isComplex() && m_pImgData == NULL)
402     {
403         setComplex(true);
404     }
405
406     //before resize, check input dimension
407     if (bNeedToResize)
408     {
409         ArrayOf<T>* pTemp = resize(piNewDims, iNewDims);
410         if (pTemp == NULL)
411         {
412             delete[] piCountDim;
413             delete[] piMaxDim;
414             //free pArg content
415             cleanIndexesArguments(_pArgs, &pArg);
416             return NULL;
417         }
418     }
419     else
420     {
421         piNewDims = m_piDims;
422         iNewDims = m_iDims;
423     }
424
425     int argSize = static_cast<int>(pArg.size());
426     int* piIndex = new int[argSize];
427     int* piCoord = new int[argSize];
428     int* piViewDims = new int[iDims];
429     memset(piIndex, 0x00, sizeof(int) * argSize);
430
431     //convert  current dimension to view dimension
432     for (int i = 0; i < iDims; i++)
433     {
434         piViewDims[i] = getVarMaxDim(i, iDims);
435     }
436
437     T* pRealData = pSource->get();
438     T* pImgData = pSource->getImg();
439     bool bComplex = pSource->isComplex();
440
441     for (int i = 0; i < iSeqCount; i++)
442     {
443         computeTuples(piCountDim, argSize, argSize - 1, piIndex);
444
445         //std::cout << "[";
446         for (int j = 0; j < argSize; j++)
447         {
448             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
449             //InternalType* pVar = pArg[j];
450             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
451             //std::cout << piCoord[j] << " ";
452         }
453
454         //std::cout << "]" << std::endl;
455
456         int iPos = getIndexWithDims(piCoord, piViewDims, iDims);
457         if (iPos < 0)
458         {
459             if (bNeedToResize)
460             {
461                 delete[] piNewDims;
462             }
463
464             delete[] piMaxDim;
465             delete[] piCountDim;
466             delete[] piIndex;
467             delete[] piCoord;
468             delete[] piViewDims;
469
470             //free pArg content
471             cleanIndexesArguments(_pArgs, &pArg);
472
473             wchar_t szError[bsiz];
474             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
475             throw ast::InternalError(szError);
476         }
477
478         if (pSource->isScalar())
479         {
480             //element-wise insertion
481             set(iPos, pRealData[0]);
482             if (pImgData != NULL && bComplex)
483             {
484                 setImg(iPos, pImgData[0]);
485             }
486         }
487         else
488         {
489             if (bIsColon)
490             {
491                 int iPas = 1;
492                 for (int j = 0; j < iDimsOrigine; j++)
493                 {
494                     iPas = iPas * m_piDims[j];
495                 }
496
497                 for (int iPost = iPos; iPost < this->getSize(); iPost += iPas)
498                 {
499                     set(iPost, pRealData[i]);
500                     if (pImgData != NULL && bComplex)
501                     {
502                         setImg(iPost, pImgData[i]);
503                     }
504                     i++;
505                 }
506             }
507             else
508             {
509                 set(iPos, pRealData[i]);
510                 if (pImgData != NULL && bComplex)
511                 {
512                     setImg(iPos, pImgData[i]);
513                 }
514             }
515         }
516
517         // reset imaginary part
518         if (m_pImgData != NULL && bComplex == false)
519         {
520             setImg(iPos, 0);
521         }
522
523         //update index
524         piIndex[0]++;
525     }
526
527     if (bNeedToResize)
528     {
529         delete[] piNewDims;
530     }
531
532     delete[] piMaxDim;
533     delete[] piCountDim;
534     delete[] piIndex;
535     delete[] piCoord;
536     delete[] piViewDims;
537
538     //free pArg content
539     cleanIndexesArguments(_pArgs, &pArg);
540
541     return this;
542 }
543
544 template <typename T>
545 GenericType* ArrayOf<T>::insertNew(typed_list* _pArgs)
546 {
547     bool bComplex = getImg() != NULL;
548     std::vector<int> dims;
549     if (getArgsDims(_pArgs, dims))
550     {
551         InternalType *pOut = NULL;
552
553         if (dims.size() == 1 && getDims() == 2)
554         {
555             if (getCols() != 1)
556             {
557                 dims.insert(dims.begin(), 1);
558             }
559             else
560             {
561                 dims.push_back(1);
562             }
563         }
564
565         while (dims.size() < 2)
566         {
567             dims.push_back(1);
568         }
569
570         pOut = createEmpty((int)dims.size(), dims.data(), bComplex);
571         ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
572         pArrayOut->fillDefaultValues();
573         ArrayOf* pOut2 = pArrayOut->insert(_pArgs, this);
574         if (pOut != pOut2)
575         {
576             delete pOut;
577         }
578
579         return pOut2;
580     }
581
582     typed_list pArg;
583     InternalType *pOut = NULL;
584
585     int iDims = (int)_pArgs->size();
586     int* piMaxDim = new int[iDims];
587     int* piCountDim = new int[iDims];
588
589     //evaluate each argument and replace by appropriate value and compute the count of combinations
590     int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
591
592     if (iSeqCount == 0)
593     {
594         delete[] piMaxDim;
595         delete[] piCountDim;
596         //free pArg content
597         cleanIndexesArguments(_pArgs, &pArg);
598         return createEmptyDouble();
599     }
600
601     if (iSeqCount < 0)
602     {
603         //manage : and $ in creation by insertion
604         int iSourceDims = getDims();
605         int iSource = 0;
606         int iNbColon = 0;
607
608         for (int i = 0; i < iDims; ++i)
609         {
610             if (pArg[i] == NULL)
611             {
612                 ++iNbColon;
613             }
614         }
615
616         if (iNbColon == iDims)
617         {
618             delete[] piMaxDim;
619             delete[] piCountDim;
620             //free pArg content
621             cleanIndexesArguments(_pArgs, &pArg);
622             return this;
623         }
624
625         int *piSourceDims = new int[iSourceDims];
626         memcpy(piSourceDims, getDimsArray(), iSourceDims * sizeof(int));
627
628         if (iNbColon == 1 && isVector())
629         {
630             iSourceDims = 1;
631             piSourceDims[0] = getSize();
632         }
633
634         //vector or matrix case
635         for (int i = 0; i < iDims; ++i)
636         {
637             //if these do not match another following explicit index, replace ":" by known source dimensions
638             if (pArg[i] == NULL)
639             {
640                 if (iSource < iSourceDims)
641                 {
642                     //by default, replace colon by current source dimension
643                     piMaxDim[i] = piSourceDims[iSource];
644                     //if there are more index dimensions left than source dimensions left
645                     if (iDims-i > iSourceDims-iSource)
646                     {
647                         for (int j = i+1; j < iDims - iSourceDims + iSource +1; ++j)
648                         {
649                             //when first explicit index is reached
650                             if (pArg[j] != NULL)
651                             {
652                                 //if future index #j and current source dimensions match
653                                 if (piCountDim[j] == piSourceDims[iSource])
654                                 {
655                                     piMaxDim[i] = 1;
656                                     --iSource;
657                                 }
658                                 break;
659                             }
660                         }
661                     }
662                     ++iSource;
663                 }
664                 else
665                 {
666                     //fill dimensions after iSourceDims with 1
667                     piMaxDim[i] = 1;
668                 }
669                 pArg[i] = createDoubleVector(piMaxDim[i]);
670                 --iNbColon;
671             }
672             else if (piCountDim[i] == piSourceDims[iSource] && (piCountDim[i]>1 || iNbColon < iSourceDims))
673             {
674                 ++iSource;
675             }
676         }
677         delete[] piSourceDims;
678     }
679
680     //remove last dimension at size 1
681     //remove last dimension if are == 1
682     for (int i = (iDims - 1); i >= 2; i--)
683     {
684         if (piMaxDim[i] == 1)
685         {
686             iDims--;
687             pArg.back()->killMe();
688             pArg.pop_back();
689         }
690         else
691         {
692             break;
693         }
694     }
695
696     if (checkArgValidity(pArg) == false)
697     {
698         delete[] piMaxDim;
699         delete[] piCountDim;
700         //free pArg content
701         cleanIndexesArguments(_pArgs, &pArg);
702         //contain bad index, like <= 0, ...
703         return NULL;
704     }
705
706     if (iDims == 1)
707     {
708         if (getCols() == 1)
709         {
710             int piRealDim[2] = {piMaxDim[0], 1};
711             pOut = createEmpty(2, piRealDim, bComplex);
712         }
713         else
714         {
715             //rows == 1
716             int piRealDim[2] = {1, piMaxDim[0]};
717             pOut = createEmpty(2, piRealDim, bComplex);
718         }
719     }
720     else
721     {
722         pOut = createEmpty(iDims, piMaxDim, bComplex);
723     }
724
725
726     //fill with null item
727     ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
728     pArrayOut->fillDefaultValues();
729     //T* pRealData = pArrayOut->get();
730     //if (bComplex)
731     //{
732     //    int size = pArrayOut->getSize();
733     //    T* pImgData = pArrayOut->getImg();
734
735     //    if (isNativeType())
736     //    {
737     //        T val = getNullValue();
738     //        for (int i = 0; i < size; i++)
739     //        {
740     //            pRealData[i] = val;
741     //            pImgData[i] = val;
742     //        }
743     //    }
744     //    else
745     //    {
746     //        for (int i = 0; i < size; i++)
747     //        {
748     //            pArrayOut->deleteData(pRealData[i]);
749     //            pRealData[i] = getNullValue();
750     //            pArrayOut->deleteData(pImgData[i]);
751     //            pImgData[i] = getNullValue();
752     //        }
753     //    }
754     //}
755     //else
756     //{
757     //    int size = pArrayOut->getSize();
758     //    if (isNativeType())
759     //    {
760     //        T val = getNullValue();
761     //        for (int i = 0; i < size; i++)
762     //        {
763     //            pRealData[i] = val;
764     //        }
765     //    }
766     //    else
767     //    {
768     //        for (int i = 0; i < size; i++)
769     //        {
770     //            pArrayOut->deleteData(pRealData[i]);
771     //            pRealData[i] = getNullValue();
772     //        }
773     //    }
774     //}
775
776     //insert values in new matrix
777     ArrayOf* pOut2 = pArrayOut->insert(&pArg, this);
778     if (pOut != pOut2)
779     {
780         delete pOut;
781     }
782
783     delete[] piMaxDim;
784     delete[] piCountDim;
785     //free pArg content
786     cleanIndexesArguments(_pArgs, &pArg);
787
788     return pOut2;
789 }
790
791 template <typename T>
792 ArrayOf<T>* ArrayOf<T>::append(int _iRows, int _iCols, InternalType* _poSource)
793 {
794     ArrayOf<T>* pIT = checkRef(this, &ArrayOf::append, _iRows, _iCols, _poSource);
795     if (pIT != this)
796     {
797         return pIT;
798     }
799
800     _poSource->IncreaseRef();
801     ArrayOf * pGT = _poSource->getAs<ArrayOf>();
802     int iRows = pGT->getRows();
803     int iCols = pGT->getCols();
804
805     //insert without resize
806     if (iRows + _iRows > m_iRows || iCols + _iCols > m_iCols)
807     {
808         return NULL;
809     }
810
811     //Update complexity if necessary
812     if (pGT->isComplex())
813     {
814         setComplex(true);
815     }
816     else if (isComplex())
817     {
818         pGT = pGT->setComplex(true);
819     }
820
821     if (pGT->isComplex())
822     {
823         for (int i = 0; i < iRows; i++)
824         {
825             for (int j = 0; j < iCols; j++)
826             {
827                 set(_iRows + i, _iCols + j, pGT->get(i, j));
828                 setImg(_iRows + i, _iCols + j, pGT->getImg(i, j));
829             }
830         }
831     }
832     else
833     {
834         for (int i = 0; i < iRows; i++)
835         {
836             for (int j = 0; j < iCols; j++)
837             {
838                 set(_iRows + i, _iCols + j, pGT->get(i, j));
839             }
840         }
841     }
842
843     pGT->killMe();
844     _poSource->DecreaseRef();
845
846     return this;
847 }
848
849 template <typename T>
850 GenericType* ArrayOf<T>::remove(typed_list* _pArgs)
851 {
852     ArrayOf<T>* pOut = NULL;
853     int iDims = (int)_pArgs->size();
854     typed_list pArg;
855
856     int* piMaxDim = new int[iDims];
857     int* piCountDim = new int[iDims];
858
859     //evaluate each argument and replace by appropriate value and compute the count of combinations
860     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
861     delete[] piMaxDim;
862     delete[] piCountDim;
863     if (iSeqCount == 0)
864     {
865         //free pArg content
866         cleanIndexesArguments(_pArgs, &pArg);
867         //no Seq, no change but no error.
868         return this;
869     }
870
871     int iToDelIndex = -1;
872     std::vector<int> toDelIndexVect;
873
874     // dimensions not subject to deletion must be indexed with colon or equivalent
875     for (int i = 0; i < iDims; i++)
876     {
877         int iDimToCheck = getVarMaxDim(i, iDims);
878         int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
879         if ((*_pArgs)[i]->isColon() == false)
880         {
881             //if equivalent to colon, should be 1:iDimToCheck after sorting and removing duplicates
882             double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
883             std::vector<int> pIndexesVect(pIndexes, pIndexes + iIndexSize);
884             std::sort(pIndexesVect.begin(), pIndexesVect.end());
885             pIndexesVect.erase(unique(pIndexesVect.begin(), pIndexesVect.end()), pIndexesVect.end());
886             //remove index > iDimToCheck to allow a[10, 10](1, 1:100) = [] and a[10, 10]([1 5 20], :) = []
887             auto lastUnique = std::find_if(pIndexesVect.begin(), pIndexesVect.end(),
888                                            [&iDimToCheck](int idx) { return idx > iDimToCheck; });
889             pIndexesVect.erase(lastUnique, pIndexesVect.end());
890
891             if (pIndexesVect.size() != iDimToCheck)
892             {
893                 // index is not equivalent to colon -> index to delete
894                 if (iToDelIndex < 0)
895                 {
896                     iToDelIndex = i;
897                     toDelIndexVect = pIndexesVect;
898                 }
899                 else
900                 {
901                     //cannot delete indexes on more than one dimension
902                     //free pArg content
903                     cleanIndexesArguments(_pArgs, &pArg);
904                     return NULL;
905                 }
906             }
907         }
908     }
909
910     if (iToDelIndex < 0)
911     {
912         // overall removal x(:,...,:) = []
913         int piDims[2] = {0,0};
914         pOut = createEmpty(2, piDims, false);
915         cleanIndexesArguments(_pArgs, &pArg);
916         return pOut;
917     }
918
919     if (toDelIndexVect.size() == 0)
920     {
921         // no removal because of too large indexes
922         cleanIndexesArguments(_pArgs, &pArg);
923         return this;
924     }
925
926     int iNewDimSize = getVarMaxDim(iToDelIndex, iDims) - toDelIndexVect.size();
927
928     int* piNewDims = new int[iDims];
929     for (int i = 0; i < iDims; i++)
930     {
931         piNewDims[i] = getVarMaxDim(i, iDims);
932     }
933     piNewDims[iToDelIndex] = iNewDimSize;
934
935     //remove last dimension if are == 1
936     int iOrigDims = iDims;
937     for (int i = (iDims - 1); i >= 2; i--)
938     {
939         if (piNewDims[i] == 1)
940         {
941             iDims--;
942         }
943         else
944         {
945             break;
946         }
947     }
948
949     if (iDims == 1)
950     {
951         //two cases, depends of original matrix/vector
952         if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
953         {
954             //special case for row vector
955             int piRealDim[2] = {1, iNewDimSize};
956             //in this case we have to care of 2nd dimension
957             //iToDelIndex = 1;
958             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
959         }
960         else
961         {
962             int piRealDim[2] = {iNewDimSize, 1};
963             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
964         }
965     }
966     else
967     {
968         pOut = createEmpty(iDims, piNewDims, m_pImgData != NULL);
969     }
970
971     // find a way to copy existing data to new variable ...
972     int* piViewDims = new int[iOrigDims];
973     int* piOffset = new int[iOrigDims+1];
974
975     // offsets
976     piOffset[0] = 1;
977     for (int i = 0; i < iOrigDims; i++)
978     {
979         piViewDims[i] = getVarMaxDim(i, iOrigDims);
980         piOffset[i+1] = piViewDims[i]*piOffset[i];
981     }
982
983     // indexes to remove -> [ 0, toDelIndexVect, piViewDims[iToDelIndex]+1 ] to facilitate loop
984     toDelIndexVect.insert(toDelIndexVect.begin(),0);
985     toDelIndexVect.push_back(piViewDims[iToDelIndex]+1);
986
987     int iStart;
988     int iSize;
989     int iOffset1 = piOffset[iToDelIndex];
990     int iOffset2 = piOffset[iToDelIndex+1];
991     int iNbChunks = getSize()/iOffset2;
992
993     // fast algorithm (allowing in place removal if necessary)
994     for (int k = 0, iDest = 0; k < iNbChunks; k++)
995     {
996         iStart = k*iOffset2;
997         // loop on indexes to remove
998         for (int j = 0; j < toDelIndexVect.size()-1; j++)
999         {
1000             iSize =  (toDelIndexVect[j+1]-toDelIndexVect[j]-1)*iOffset1;
1001             if (isNativeType())
1002             {
1003                 memcpy(pOut->m_pRealData + iDest, m_pRealData + iStart, iSize*sizeof(T));
1004                 if (m_pImgData != NULL)
1005                 {
1006                     memcpy(pOut->m_pImgData + iDest, m_pImgData + iStart, iSize*sizeof(T));
1007                 }
1008                 iDest += iSize;
1009             }
1010             else
1011             {
1012                 for (int i = iStart; i < iStart+iSize; i++, iDest++)
1013                 {
1014                     pOut->set(iDest, get(i));
1015                     if (m_pImgData != NULL)
1016                     {
1017                         pOut->setImg(iDest, getImg(i));
1018                     }
1019                 }
1020             }
1021             iStart += iSize + iOffset1;
1022         }
1023     }
1024
1025     delete[] piViewDims;
1026     delete[] piOffset;
1027     delete[] piNewDims;
1028
1029     //free pArg content
1030     cleanIndexesArguments(_pArgs, &pArg);
1031
1032     return pOut;
1033 }
1034
1035 template <typename T>
1036 GenericType* ArrayOf<T>::extract(typed_list* _pArgs)
1037 {
1038     ArrayOf<T>* pOut = NULL;
1039     int iDims = (int)_pArgs->size();
1040     typed_list pArg;
1041
1042     int index;
1043     if (getScalarIndex(this, _pArgs, &index))
1044     {
1045         if (index < 0)
1046         {
1047             return NULL;
1048         }
1049
1050         if (getSize() == 0)
1051         {
1052             return createEmpty();
1053         }
1054
1055         if (index >= getSize())
1056         {
1057             return NULL;
1058         }
1059
1060         int dims[2] = {1, 1};
1061         pOut = createEmpty(2, dims, isComplex());;
1062         pOut->set(0, get(index));
1063         if (isComplex())
1064         {
1065             pOut->setImg(0, getImg(index));
1066         }
1067
1068         return pOut;
1069     }
1070
1071     std::vector<double> il;
1072     if (getScalarImplicitIndex(this, _pArgs, il))
1073     {
1074         double start = il[0];
1075         double step = il[1];
1076         double end = il[2];
1077         //index are ":"
1078         bool isForceColVector = il.size() == 4;
1079
1080         //std::cout << start << ":" << step << ":" << end << std::endl;
1081         int size = static_cast<int>((end - start) / step + 1);
1082
1083         if (size <= 0 || m_iSize == 0)
1084         {
1085             return createEmpty();
1086         }
1087
1088         //check bounds
1089         if (step > 0 && ((size - 1) * step + start > m_iSize || start < 1) ||
1090                 (step < 0 && (start > m_iSize || end < 1)))
1091         {
1092             return NULL;
1093         }
1094
1095         bool isRowVector = m_iRows == 1;
1096         isRowVector = isRowVector && !isForceColVector;
1097         int dims[2] = {isRowVector ? 1 : size, isRowVector ? size : 1};
1098         pOut = createEmpty(2, dims, isComplex());
1099         double idx = start;
1100
1101         if (isComplex())
1102         {
1103             for (int i = 0; i < size; ++i)
1104             {
1105                 int index = static_cast<int>(idx) - 1;
1106                 pOut->set(i, get(index));
1107                 pOut->setImg(i, getImg(index));
1108                 idx += step;
1109             }
1110         }
1111         else
1112         {
1113             for (int i = 0; i < size; ++i)
1114             {
1115                 pOut->set(i, get(static_cast<int>(idx) - 1));
1116                 idx += step;
1117             }
1118         }
1119         return pOut;
1120     }
1121
1122     std::vector<int> indexes;
1123     std::vector<int> dims;
1124     if (getImplicitIndex(this, _pArgs, indexes, dims))
1125     {
1126         if (indexes.size() == 0)
1127         {
1128             return createEmpty();
1129         }
1130
1131         if (dims.size() == 1)
1132         {
1133             int d[2] = {1, dims[0]};
1134             pOut = createEmpty(2, d, isComplex());
1135         }
1136         else
1137         {
1138             pOut = createEmpty(static_cast<int>(dims.size()), dims.data(), isComplex());
1139         }
1140
1141         int size = getSize();
1142         if (isComplex())
1143         {
1144             int idx = 0;
1145             for (int & i : indexes)
1146             {
1147                 if (i < 0 || i >= size)
1148                 {
1149                     pOut->killMe();
1150                     return NULL;
1151                 }
1152
1153                 pOut->set(idx, get(i));
1154                 pOut->setImg(idx, getImg(i));
1155                 ++idx;
1156             }
1157         }
1158         else
1159         {
1160             int idx = 0;
1161             for (int & i : indexes)
1162             {
1163                 pOut->set(idx, get(i));
1164                 ++idx;
1165             }
1166         }
1167
1168         return pOut;
1169     }
1170
1171
1172     int* piMaxDim = new int[iDims];
1173     int* piCountDim = new int[iDims];
1174
1175     //evaluate each argument and replace by appropriate value and compute the count of combinations
1176     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1177     if (iSeqCount == 0)
1178     {
1179         delete[] piMaxDim;
1180         delete[] piCountDim;
1181         //free pArg content
1182         cleanIndexesArguments(_pArgs, &pArg);
1183         return createEmpty();
1184     }
1185
1186     if (iSeqCount < 0)
1187     {
1188         delete[] piMaxDim;
1189         delete[] piCountDim;
1190         //free pArg content
1191         cleanIndexesArguments(_pArgs, &pArg);
1192         return NULL;
1193     }
1194
1195     //a = {};a(1:2, 1:2) -> {}
1196     if (getSize() == 0)
1197     {
1198         delete[] piMaxDim;
1199         delete[] piCountDim;
1200         //free pArg content
1201         cleanIndexesArguments(_pArgs, &pArg);
1202         return createEmpty();
1203     }
1204
1205     if (iDims < m_iDims)
1206     {
1207         for (int i = 0; i < iDims; i++)
1208         {
1209             int iDimToCheck = 0;
1210             if (i == (iDims - 1))
1211             {
1212                 iDimToCheck = getVarMaxDim(i, iDims);
1213             }
1214             else
1215             {
1216                 iDimToCheck = m_piDims[i];
1217             }
1218
1219             if (piMaxDim[i] > iDimToCheck)
1220             {
1221                 delete[] piMaxDim;
1222                 delete[] piCountDim;
1223                 //free pArg content
1224                 cleanIndexesArguments(_pArgs, &pArg);
1225                 return NULL;
1226             }
1227         }
1228     }
1229     else
1230     {
1231         if (iDims > m_iDims)
1232         {
1233             for (int i = m_iDims; i < iDims; i++)
1234             {
1235                 if (piMaxDim[i] > 1)
1236                 {
1237                     delete[] piMaxDim;
1238                     delete[] piCountDim;
1239                     //free pArg content
1240                     cleanIndexesArguments(_pArgs, &pArg);
1241                     return NULL;
1242                 }
1243             }
1244         }
1245
1246         //check MaxDim
1247         for (int i = 0; i < m_iDims; i++)
1248         {
1249             if (piMaxDim[i] > m_piDims[i])
1250             {
1251                 delete[] piMaxDim;
1252                 delete[] piCountDim;
1253                 //free pArg content
1254                 cleanIndexesArguments(_pArgs, &pArg);
1255                 //exrtact must be in dimension limits
1256                 return NULL;
1257             }
1258         }
1259     }
1260
1261     //remove last dimension if are == 1
1262     for (int i = (iDims - 1); i >= 2; i--)
1263     {
1264         if (piCountDim[i] == 1)
1265         {
1266             (iDims)--;
1267         }
1268         else
1269         {
1270             break;
1271         }
1272     }
1273
1274     //vector
1275     if (iDims == 1)
1276     {
1277         if (piCountDim[0] == 0)
1278         {
1279             delete[] piMaxDim;
1280             delete[] piCountDim;
1281             //free pArg content
1282             cleanIndexesArguments(_pArgs, &pArg);
1283             return createEmpty();
1284         }
1285         else
1286         {
1287             //two cases, depends of original matrix/vector
1288             if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[1] != 1 && m_piDims[0] == 1)
1289             {
1290                 //special case for row vector
1291                 int piRealDim[2] = {1, piCountDim[0]};
1292                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1293             }
1294             else
1295             {
1296                 if (getSize() == 1)
1297                 {
1298                     //for extraction on scalar
1299                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), pArg[0]->getAs<GenericType>()->getDimsArray(), m_pImgData != NULL);
1300                 }
1301                 else
1302                 {
1303                     int piRealDim[2] = {piCountDim[0], 1};
1304                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1305                 }
1306             }
1307         }
1308     }
1309     else
1310     {
1311         //matrix
1312         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1313     }
1314
1315     int* piIndex = new int[_pArgs->size()];
1316     int* piCoord = new int[_pArgs->size()];
1317     int* piViewDims = new int[iDims];
1318     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1319
1320     for (int i = 0; i < iDims; i++)
1321     {
1322         piViewDims[i] = getVarMaxDim(i, iDims);
1323     }
1324
1325     for (int i = 0; i < iSeqCount; i++)
1326     {
1327         //increment last dimension
1328         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1329
1330         //std::cout << "[";
1331         for (int j = 0; j < (int)_pArgs->size(); j++)
1332         {
1333             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1334             //InternalType* pVar = pArg[i];
1335             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1336             //std::cout << piCoord[j] << " ";
1337
1338             // try to access somewhere wrong.
1339             if (piCoord[j] < 0)
1340             {
1341                 delete[] piIndex;
1342                 delete[] piCoord;
1343                 delete[] piViewDims;
1344                 delete[] piMaxDim;
1345                 delete[] piCountDim;
1346
1347                 //free pArg content
1348                 cleanIndexesArguments(_pArgs, &pArg);
1349                 return NULL;
1350             }
1351         }
1352
1353         //std::cout << "]" << std::endl;
1354
1355         int iPos = 0;
1356         //put vlaue in the new matrix
1357         if ((int)_pArgs->size() < m_iDims)
1358         {
1359             //compute index based on viewed matrix
1360             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1361         }
1362         else
1363         {
1364             //compute vector index
1365             iPos = getIndex(piCoord);
1366         }
1367
1368         //convert flat dimension to 0
1369         for (int j = 0; j < iDims; j++)
1370         {
1371             if (piCountDim[j] == 1)
1372             {
1373                 piCoord[j] = 0;
1374             }
1375         }
1376
1377         pOut->set(i, get(iPos));
1378         if (m_pImgData != NULL)
1379         {
1380             pOut->setImg(i, getImg(iPos));
1381         }
1382
1383
1384         piIndex[0]++;
1385     }
1386
1387     //free pArg content
1388     cleanIndexesArguments(_pArgs, &pArg);
1389
1390     delete[] piIndex;
1391     delete[] piCoord;
1392     delete[] piViewDims;
1393     delete[] piMaxDim;
1394     delete[] piCountDim;
1395
1396     return pOut;
1397 }
1398
1399 template <typename T>
1400 ArrayOf<T>* ArrayOf<T>::reshape(int* _piDims, int _iDims)
1401 {
1402     typedef ArrayOf<T>* (ArrayOf<T>::*reshape_t)(int*, int);
1403     ArrayOf<T>* pIT = checkRef(this, (reshape_t)&ArrayOf<T>::reshape, _piDims, _iDims);
1404     if (pIT != this)
1405     {
1406         return pIT;
1407     }
1408
1409     int iNewSize = get_max_size(_piDims, _iDims);
1410     if (iNewSize != m_iSize)
1411     {
1412         return NULL;
1413     }
1414
1415     for (int i = 0 ; i < _iDims ; i++)
1416     {
1417         m_piDims[i] = _piDims[i];
1418     }
1419
1420     if (_iDims == 1)
1421     {
1422         m_piDims[1] = 1;
1423         _iDims++;
1424     }
1425
1426     int iDims = _iDims;
1427     for (int i = iDims - 1; i >= 2; --i)
1428     {
1429         if (m_piDims[i] == 1)
1430         {
1431             _iDims--;
1432         }
1433         else
1434         {
1435             break;
1436         }
1437     }
1438
1439     m_iRows = m_piDims[0];
1440     m_iCols = m_piDims[1];
1441     m_iSize = iNewSize;
1442     m_iDims = _iDims;
1443
1444     return this;
1445 }
1446
1447 template <typename T>
1448 ArrayOf<T>* ArrayOf<T>::resize(int* _piDims, int _iDims)
1449 {
1450     typedef ArrayOf<T>* (ArrayOf<T>::*resize_t)(int*, int);
1451     ArrayOf<T>* pIT = checkRef(this, (resize_t)&ArrayOf::resize, _piDims, _iDims);
1452     if (pIT != this)
1453     {
1454         return pIT;
1455     }
1456
1457     if (_iDims == m_iDims)
1458     {
1459         bool bChange = false;
1460         for (int i = 0; i < _iDims; i++)
1461         {
1462             if (m_piDims[i] != _piDims[i])
1463             {
1464                 bChange = true;
1465                 break;
1466             }
1467         }
1468
1469         if (bChange == false)
1470         {
1471             //nothing to do
1472             return this;
1473         }
1474     }
1475
1476     //alloc new data array
1477     T* pRealData = NULL;
1478     T* pImgData = NULL;
1479
1480     int iNewSize = 0;
1481     if (m_pImgData != NULL)
1482     {
1483         iNewSize = get_max_size(_piDims, _iDims);
1484         if (m_iSizeMax < iNewSize)
1485         {
1486             //alloc 10% bigger than asked to prevent future resize
1487             int iOldSizeMax = m_iSizeMax;
1488             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1489             pRealData = allocData(m_iSizeMax);
1490             pImgData = allocData(m_iSizeMax);
1491
1492             //copy values into new one
1493             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1494             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1495             for (int i = 0; i < _iDims; i++)
1496             {
1497                 piIndexes[i] = 0;
1498             }
1499
1500             int iPreviousNewIdx = 0;
1501             for (int i = 0; i < m_iSize; i++)
1502             {
1503                 getIndexes(i, piIndexes);
1504                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1505                 pRealData[iNewIdx] = m_pRealData[i];
1506                 pImgData[iNewIdx] = m_pImgData[i];
1507                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1508                 {
1509                     T pTemp = getNullValue();
1510                     pRealData[j] = copyValue(pTemp);
1511                     pImgData[j] = copyValue(pTemp);
1512                     if (pTemp != pRealData[j])
1513                     {
1514                         deleteData(pTemp);
1515                     }
1516                 }
1517
1518                 iPreviousNewIdx = iNewIdx + 1;
1519             }
1520
1521             // if it's not the first resize,
1522             // fill new data with element of last allocation
1523             if (iPreviousNewIdx < iOldSizeMax)
1524             {
1525                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1526                 {
1527                     pRealData[i] = m_pRealData[i];
1528                     pImgData[i] = m_pImgData[i];
1529                 }
1530             }
1531             else
1532             {
1533                 // first resize, iOldSizeMax don't contain the 10%
1534                 iOldSizeMax = iPreviousNewIdx;
1535             }
1536
1537             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1538             {
1539                 T pTemp = getNullValue();
1540                 pRealData[i] = copyValue(pTemp);
1541                 pImgData[i] = copyValue(pTemp);
1542                 if (pTemp != pRealData[i])
1543                 {
1544                     deleteData(pTemp);
1545                 }
1546             }
1547
1548             delete[] piIndexes;
1549             //delete all array
1550             delete[] m_pRealData;
1551             delete[] m_pImgData;
1552             //replace old array by new one
1553             m_pRealData = pRealData;
1554             m_pImgData = pImgData;
1555         }
1556         else
1557         {
1558             //check if only the last dims change
1559             bool bNonLastDimChange = false;
1560             for (int i = 0; i < (m_iDims - 1); i++)
1561             {
1562                 if (m_piDims[i] != _piDims[i])
1563                 {
1564                     bNonLastDimChange = true;
1565                     break;
1566                 }
1567             }
1568
1569             //if vector or if row dimension not change, we don't need to shift data
1570             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1571             {
1572                 //copy values into new one
1573                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1574                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1575                 for (int i = m_iSize - 1; i >= 0; i--)
1576                 {
1577                     getIndexes(i, piIndexes);
1578                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1579                     if (iNewIdx != i)
1580                     {
1581                         T pTemp = m_pRealData[iNewIdx];
1582                         m_pRealData[iNewIdx] = m_pRealData[i];
1583                         m_pRealData[i] = pTemp;
1584
1585                         pTemp = m_pImgData[iNewIdx];
1586                         m_pImgData[iNewIdx] = m_pImgData[i];
1587                         m_pImgData[i] = pTemp;
1588                     }
1589                 }
1590                 delete[] piIndexes;
1591             }
1592         }
1593     }
1594     else
1595     {
1596         iNewSize = get_max_size(_piDims, _iDims);
1597         if (iNewSize > m_iSizeMax)
1598         {
1599             //alloc 10% bigger than asked to prevent future resize
1600             int iOldSizeMax = m_iSizeMax;
1601             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1602             pRealData = allocData(m_iSizeMax);
1603
1604             //copy values into new one
1605             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1606             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1607             for (int i = 0; i < _iDims; i++)
1608             {
1609                 piIndexes[i] = 0;
1610             }
1611
1612             int iPreviousNewIdx = 0;
1613             for (int i = 0; i < m_iSize; i++)
1614             {
1615                 getIndexes(i, piIndexes);
1616                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1617                 pRealData[iNewIdx] = m_pRealData[i];
1618                 m_pRealData[i] = NULL;
1619
1620                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1621                 {
1622                     T pTemp = getNullValue();
1623                     T pTemp2 = copyValue(pTemp);
1624                     pRealData[j] = pTemp2;
1625                     if (pTemp != pTemp2)
1626                     {
1627                         deleteData(pTemp);
1628                     }
1629                 }
1630
1631                 iPreviousNewIdx = iNewIdx + 1;
1632             }
1633
1634             //clean section between m_iSize and iOldSizeMax
1635             for (int i = m_iSize; i < iOldSizeMax; ++i)
1636             {
1637                 deleteData(m_pRealData[i]);
1638                 m_pRealData[i] = NULL;
1639             }
1640
1641             //if (iPreviousNewIdx < iOldSizeMax)
1642             //{
1643             //    for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1644             //    {
1645             //        pRealData[i] = m_pRealData[i];
1646             //        m_pRealData[i] = NULL;
1647             //    }
1648             //}
1649             //else
1650             //{
1651             //    iOldSizeMax = iPreviousNewIdx;
1652             //}
1653
1654             //fill exceeded with NullValue
1655             for (int i = iPreviousNewIdx; i < m_iSizeMax; ++i)
1656             {
1657                 T pTemp = getNullValue();
1658                 T pTemp2 = copyValue(pTemp);
1659                 pRealData[i] = pTemp2;
1660                 if (pTemp != pTemp2)
1661                 {
1662                     deleteData(pTemp);
1663                 }
1664             }
1665
1666             delete[] piIndexes;
1667             //delete all array
1668             delete[] m_pRealData;
1669             //replace old array by new one
1670             m_pRealData = pRealData;
1671         }
1672         else
1673         {
1674             //check if only the last dims change
1675             bool bNonLastDimChange = false;
1676             for (int i = 0; i < (m_iDims - 1); i++)
1677             {
1678                 if (m_piDims[i] != _piDims[i])
1679                 {
1680                     bNonLastDimChange = true;
1681                     break;
1682                 }
1683             }
1684
1685             //if vector or if row dimension not change, we don't need to shift data
1686             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1687             {
1688                 //copy values into new one
1689                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1690                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1691                 for (int i = m_iSize - 1; i >= 0; i--)
1692                 {
1693                     getIndexes(i, piIndexes);
1694                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1695                     if (iNewIdx != i)
1696                     {
1697                         T pTemp = m_pRealData[iNewIdx];
1698                         m_pRealData[iNewIdx] = m_pRealData[i];
1699                         m_pRealData[i] = pTemp;
1700                     }
1701                 }
1702                 delete[] piIndexes;
1703             }
1704         }
1705     }
1706
1707     if (_iDims != m_iDims)
1708     {
1709         //int* piDims = new int[_iDims];
1710         for (int i = 0; i < _iDims; i++)
1711         {
1712             m_piDims[i] = _piDims[i];
1713         }
1714         //delete[] m_piDims;
1715         //m_piDims = piDims;
1716         m_iDims = _iDims;
1717     }
1718     else
1719     {
1720         for (int i = 0; i < m_iDims; i++)
1721         {
1722             m_piDims[i] = _piDims[i];
1723         }
1724     }
1725     m_iRows = m_piDims[0];
1726     m_iCols = m_piDims[1];
1727     m_iSize = iNewSize;
1728     return this;
1729 }
1730
1731 template <typename T>
1732 bool ArrayOf<T>::isTrue()
1733 {
1734     return type_traits::isTrue<T>(m_iSize, m_pRealData);
1735 }
1736
1737 template<typename T>
1738 bool ArrayOf<T>::neg(InternalType *& out)
1739 {
1740     out = new Bool(this->m_iDims, this->m_piDims);
1741     type_traits::neg<T, int>(this->m_iSize, this->m_pRealData, static_cast<Bool *>(out)->get());
1742
1743     return true;
1744 }
1745
1746 template<typename T>
1747 bool ArrayOf<T>::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
1748 {
1749     if (in.size() == 0)
1750     {
1751         out.push_back(this);
1752     }
1753     else
1754     {
1755         InternalType * _out = extract(&in);
1756         if (!_out)
1757         {
1758             std::wostringstream os;
1759             os << _W("Invalid index.\n");
1760             throw ast::InternalError(os.str(), 999, e.getLocation());
1761         }
1762         out.push_back(_out);
1763     }
1764
1765     return true;
1766 }
1767
1768 template<typename T>
1769 bool ArrayOf<T>::isInvokable() const
1770 {
1771     return true;
1772 }
1773
1774 template<typename T>
1775 bool ArrayOf<T>::hasInvokeOption() const
1776 {
1777     return false;
1778 }
1779
1780 template<typename T>
1781 int ArrayOf<T>::getInvokeNbIn()
1782 {
1783     return -1;
1784 }
1785
1786 template<typename T>
1787 int ArrayOf<T>::getInvokeNbOut()
1788 {
1789     return 1;
1790 }
1791
1792
1793 // used to allow definition of ArrayOf methode in this cpp file.
1794 template class EXTERN_AST ArrayOf < char >;
1795 template class EXTERN_AST ArrayOf < unsigned char >;
1796 template class EXTERN_AST ArrayOf < short >;
1797 template class EXTERN_AST ArrayOf < unsigned short >;
1798 template class EXTERN_AST ArrayOf < int >;
1799 template class EXTERN_AST ArrayOf < unsigned int >;
1800 template class EXTERN_AST ArrayOf < long long >;
1801 template class EXTERN_AST ArrayOf < unsigned long long >;
1802 template class EXTERN_AST ArrayOf < double >;
1803 template class EXTERN_AST ArrayOf < wchar_t* >;
1804 template class EXTERN_AST ArrayOf < SinglePoly* >;
1805 template class EXTERN_AST ArrayOf < SingleStruct* >;
1806 template class EXTERN_AST ArrayOf < InternalType* >; // Cell
1807 }