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