* Bug 14487 fixed: matrix indexing is now coherent with MATLAB
[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, false);
1085         pOut->set(0, get(index));
1086         bool c = isNativeType() ? getImg(index) != 0 : isComplexElement(index);
1087         if (isComplex() && c)
1088         {
1089             pOut->setComplex(true);
1090             pOut->setImg(0, getImg(index));
1091         }
1092         else
1093         {
1094             pOut->setComplex(false);
1095         }
1096
1097         
1098
1099         return pOut;
1100     }
1101
1102     std::vector<double> il;
1103     if (getScalarImplicitIndex(this, _pArgs, il))
1104     {
1105         double start = il[0];
1106         double step = il[1];
1107         double end = il[2];
1108         //index are ":"
1109         bool isForceColVector = il.size() == 4;
1110
1111         //std::cout << start << ":" << step << ":" << end << std::endl;
1112         int size = static_cast<int>((end - start) / step + 1);
1113
1114         if (size <= 0 || m_iSize == 0)
1115         {
1116             return createEmpty();
1117         }
1118
1119         //check bounds
1120         if (step > 0 && ((size - 1) * step + start > m_iSize || start < 1) ||
1121                 (step < 0 && (start > m_iSize || end < 1)))
1122         {
1123             return NULL;
1124         }
1125
1126         bool isRowVector = m_iRows == 1;
1127         isRowVector = isRowVector && !isForceColVector;
1128         int dims[2] = {isRowVector ? 1 : size, isRowVector ? size : 1};
1129         pOut = createEmpty(2, dims, isComplex());
1130         double idx = start;
1131
1132         if (isComplex())
1133         {
1134             bool bIsComplex = false;
1135             for (int i = 0; i < size; ++i)
1136             {
1137                 int index = static_cast<int>(idx) - 1;
1138                 T iValue = getImg(index);
1139                 pOut->set(i, get(index));
1140                 pOut->setImg(i, iValue);
1141                 if (isNativeType())
1142                 {
1143                     bIsComplex |= (iValue != 0);
1144                 }
1145                 else
1146                 {
1147                     bIsComplex |= (isComplexElement(index) != 0);
1148                 }
1149                 idx += step;
1150             }
1151
1152             pOut->setComplex(bIsComplex);
1153         }
1154         else
1155         {
1156             for (int i = 0; i < size; ++i)
1157             {
1158                 pOut->set(i, get(static_cast<int>(idx) - 1));
1159                 idx += step;
1160             }
1161         }
1162         return pOut;
1163     }
1164
1165     std::vector<int> indexes;
1166     std::vector<int> dims;
1167     if (getImplicitIndex(this, _pArgs, indexes, dims))
1168     {
1169         if (indexes.size() == 0)
1170         {
1171             return createEmpty();
1172         }
1173
1174         if (dims.size() == 1)
1175         {
1176             int d[2] = {1, dims[0]};
1177             pOut = createEmpty(2, d, isComplex());
1178         }
1179         else
1180         {
1181             pOut = createEmpty(static_cast<int>(dims.size()), dims.data(), isComplex());
1182         }
1183
1184         int size = getSize();
1185         if (isComplex())
1186         {
1187             bool bIsComplex = false;
1188             int idx = 0;
1189             for (int & i : indexes)
1190             {
1191                 if (i < 0 || i >= size)
1192                 {
1193                     pOut->killMe();
1194                     return NULL;
1195                 }
1196
1197                 T iValue = getImg(i);
1198                 pOut->set(idx, get(i));
1199                 pOut->setImg(idx, iValue);
1200                 if (isNativeType())
1201                 {
1202                     bIsComplex |= (iValue != 0);
1203                 }
1204                 else
1205                 {
1206                     bIsComplex |= (isComplexElement(i) != 0);
1207                 }
1208
1209                 ++idx;
1210             }
1211             pOut->setComplex(bIsComplex);
1212         }
1213         else
1214         {
1215             int idx = 0;
1216             for (int & i : indexes)
1217             {
1218                 pOut->set(idx, get(i));
1219                 ++idx;
1220             }
1221         }
1222
1223         return pOut;
1224     }
1225
1226
1227     int* piMaxDim = new int[iDims];
1228     int* piCountDim = new int[iDims];
1229
1230     //evaluate each argument and replace by appropriate value and compute the count of combinations
1231     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1232     if (iSeqCount == 0)
1233     {
1234         delete[] piMaxDim;
1235         delete[] piCountDim;
1236         //free pArg content
1237         cleanIndexesArguments(_pArgs, &pArg);
1238         return createEmpty();
1239     }
1240
1241     if (iSeqCount < 0)
1242     {
1243         delete[] piMaxDim;
1244         delete[] piCountDim;
1245         //free pArg content
1246         cleanIndexesArguments(_pArgs, &pArg);
1247         return NULL;
1248     }
1249
1250     //a = {};a(1:2, 1:2) -> {}
1251     if (getSize() == 0)
1252     {
1253         delete[] piMaxDim;
1254         delete[] piCountDim;
1255         //free pArg content
1256         cleanIndexesArguments(_pArgs, &pArg);
1257         return createEmpty();
1258     }
1259
1260     if (iDims < m_iDims)
1261     {
1262         for (int i = 0; i < iDims; i++)
1263         {
1264             int iDimToCheck = 0;
1265             if (i == (iDims - 1))
1266             {
1267                 iDimToCheck = getVarMaxDim(i, iDims);
1268             }
1269             else
1270             {
1271                 iDimToCheck = m_piDims[i];
1272             }
1273
1274             if (piMaxDim[i] > iDimToCheck)
1275             {
1276                 delete[] piMaxDim;
1277                 delete[] piCountDim;
1278                 //free pArg content
1279                 cleanIndexesArguments(_pArgs, &pArg);
1280                 return NULL;
1281             }
1282         }
1283     }
1284     else
1285     {
1286         if (iDims > m_iDims)
1287         {
1288             for (int i = m_iDims; i < iDims; i++)
1289             {
1290                 if (piMaxDim[i] > 1)
1291                 {
1292                     delete[] piMaxDim;
1293                     delete[] piCountDim;
1294                     //free pArg content
1295                     cleanIndexesArguments(_pArgs, &pArg);
1296                     return NULL;
1297                 }
1298             }
1299         }
1300
1301         //check MaxDim
1302         for (int i = 0; i < m_iDims; i++)
1303         {
1304             if (piMaxDim[i] > m_piDims[i])
1305             {
1306                 delete[] piMaxDim;
1307                 delete[] piCountDim;
1308                 //free pArg content
1309                 cleanIndexesArguments(_pArgs, &pArg);
1310                 //exrtact must be in dimension limits
1311                 return NULL;
1312             }
1313         }
1314     }
1315
1316     //remove last dimension if are == 1
1317     for (int i = (iDims - 1); i >= 2; i--)
1318     {
1319         if (piCountDim[i] == 1)
1320         {
1321             (iDims)--;
1322         }
1323         else
1324         {
1325             break;
1326         }
1327     }
1328
1329     //linear indexing (one subscript)
1330     if (iDims == 1)
1331     {
1332         if (piCountDim[0] == 0)
1333         {
1334             delete[] piMaxDim;
1335             delete[] piCountDim;
1336             //free pArg content
1337             cleanIndexesArguments(_pArgs, &pArg);
1338             return createEmpty();
1339         }
1340         else
1341         {
1342             int *i_piDims = pArg[0]->getAs<GenericType>()->getDimsArray();
1343             if (!isScalar() && isVector() && (i_piDims[0] == 1 || i_piDims[1] == 1))
1344             {
1345                 //vector with vector subscript
1346                 int piRealDim[2] = { 1, 1 };
1347                 piRealDim[(int)(m_piDims[0] == 1)] = piCountDim[0];
1348                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1349             }
1350             else
1351             {
1352                 if ((*_pArgs)[0]->isBool())
1353                 {
1354                     //boolean extraction must return a column vector
1355                     int piRealDim[2] = { piCountDim[0], 1 };
1356                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1357                 }
1358                 else
1359                 {
1360                     //other cases
1361                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), i_piDims, m_pImgData != NULL);
1362                 }
1363             }
1364         }
1365     }
1366     else
1367     {
1368         //indexing with more than one subscript
1369         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1370     }
1371
1372     int* piIndex = new int[_pArgs->size()];
1373     int* piCoord = new int[_pArgs->size()];
1374     int* piViewDims = new int[iDims];
1375     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1376
1377     for (int i = 0; i < iDims; i++)
1378     {
1379         piViewDims[i] = getVarMaxDim(i, iDims);
1380     }
1381
1382     bool bIsComplex = false;
1383     for (int i = 0; i < iSeqCount; i++)
1384     {
1385         //increment last dimension
1386         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1387
1388         //std::cout << "[";
1389         for (int j = 0; j < (int)_pArgs->size(); j++)
1390         {
1391             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1392             //InternalType* pVar = pArg[i];
1393             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1394             //std::cout << piCoord[j] << " ";
1395
1396             // try to access somewhere wrong.
1397             if (piCoord[j] < 0)
1398             {
1399                 delete[] piIndex;
1400                 delete[] piCoord;
1401                 delete[] piViewDims;
1402                 delete[] piMaxDim;
1403                 delete[] piCountDim;
1404
1405                 //free pArg content
1406                 cleanIndexesArguments(_pArgs, &pArg);
1407                 return NULL;
1408             }
1409         }
1410
1411         //std::cout << "]" << std::endl;
1412
1413         int iPos = 0;
1414         //put vlaue in the new matrix
1415         if ((int)_pArgs->size() < m_iDims)
1416         {
1417             //compute index based on viewed matrix
1418             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1419         }
1420         else
1421         {
1422             //compute vector index
1423             iPos = getIndex(piCoord);
1424         }
1425
1426         //convert flat dimension to 0
1427         for (int j = 0; j < iDims; j++)
1428         {
1429             if (piCountDim[j] == 1)
1430             {
1431                 piCoord[j] = 0;
1432             }
1433         }
1434
1435         pOut->set(i, get(iPos));
1436         if (isComplex())
1437         {
1438             T iValue = getImg(iPos);
1439             pOut->setImg(i, iValue);
1440             if (isNativeType())
1441             {
1442                 bIsComplex |= (iValue != 0);
1443             }
1444             else
1445             {
1446                 bIsComplex |= (isComplexElement(iPos) != 0);
1447             }
1448         }
1449
1450         piIndex[0]++;
1451     }
1452     
1453     pOut->setComplex(bIsComplex);
1454
1455     //free pArg content
1456     cleanIndexesArguments(_pArgs, &pArg);
1457
1458     delete[] piIndex;
1459     delete[] piCoord;
1460     delete[] piViewDims;
1461     delete[] piMaxDim;
1462     delete[] piCountDim;
1463
1464     return pOut;
1465 }
1466
1467 template <typename T>
1468 ArrayOf<T>* ArrayOf<T>::reshape(int* _piDims, int _iDims)
1469 {
1470     typedef ArrayOf<T>* (ArrayOf<T>::*reshape_t)(int*, int);
1471     ArrayOf<T>* pIT = checkRef(this, (reshape_t)&ArrayOf<T>::reshape, _piDims, _iDims);
1472     if (pIT != this)
1473     {
1474         return pIT;
1475     }
1476
1477     int iNewSize = get_max_size(_piDims, _iDims);
1478     if (iNewSize != m_iSize)
1479     {
1480         return NULL;
1481     }
1482
1483     for (int i = 0 ; i < _iDims ; i++)
1484     {
1485         m_piDims[i] = _piDims[i];
1486     }
1487
1488     if (_iDims == 1)
1489     {
1490         m_piDims[1] = 1;
1491         _iDims++;
1492     }
1493
1494     int iDims = _iDims;
1495     for (int i = iDims - 1; i >= 2; --i)
1496     {
1497         if (m_piDims[i] == 1)
1498         {
1499             _iDims--;
1500         }
1501         else
1502         {
1503             break;
1504         }
1505     }
1506
1507     m_iRows = m_piDims[0];
1508     m_iCols = m_piDims[1];
1509     m_iSize = iNewSize;
1510     m_iDims = _iDims;
1511
1512     return this;
1513 }
1514
1515 template <typename T>
1516 ArrayOf<T>* ArrayOf<T>::resize(int* _piDims, int _iDims)
1517 {
1518     typedef ArrayOf<T>* (ArrayOf<T>::*resize_t)(int*, int);
1519     ArrayOf<T>* pIT = checkRef(this, (resize_t)&ArrayOf::resize, _piDims, _iDims);
1520     if (pIT != this)
1521     {
1522         return pIT;
1523     }
1524
1525     if (_iDims == m_iDims)
1526     {
1527         bool bChange = false;
1528         for (int i = 0; i < _iDims; i++)
1529         {
1530             if (m_piDims[i] != _piDims[i])
1531             {
1532                 bChange = true;
1533                 break;
1534             }
1535         }
1536
1537         if (bChange == false)
1538         {
1539             //nothing to do
1540             return this;
1541         }
1542     }
1543
1544     //alloc new data array
1545     T* pRealData = NULL;
1546     T* pImgData = NULL;
1547
1548     int iNewSize = 0;
1549     if (m_pImgData != NULL)
1550     {
1551         iNewSize = get_max_size(_piDims, _iDims);
1552         if (m_iSizeMax < iNewSize)
1553         {
1554             //alloc 10% bigger than asked to prevent future resize
1555             int iOldSizeMax = m_iSizeMax;
1556             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1557             pRealData = allocData(m_iSizeMax);
1558             pImgData = allocData(m_iSizeMax);
1559
1560             //copy values into new one
1561             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1562             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1563             for (int i = 0; i < _iDims; i++)
1564             {
1565                 piIndexes[i] = 0;
1566             }
1567
1568             int iPreviousNewIdx = 0;
1569             for (int i = 0; i < m_iSize; i++)
1570             {
1571                 getIndexes(i, piIndexes);
1572                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1573                 pRealData[iNewIdx] = m_pRealData[i];
1574                 pImgData[iNewIdx] = m_pImgData[i];
1575                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1576                 {
1577                     T pTemp = getNullValue();
1578                     pRealData[j] = copyValue(pTemp);
1579                     pImgData[j] = copyValue(pTemp);
1580                     if (pTemp != pRealData[j])
1581                     {
1582                         deleteData(pTemp);
1583                     }
1584                 }
1585
1586                 iPreviousNewIdx = iNewIdx + 1;
1587             }
1588
1589             // if it's not the first resize,
1590             // fill new data with element of last allocation
1591             if (iPreviousNewIdx < iOldSizeMax)
1592             {
1593                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1594                 {
1595                     pRealData[i] = m_pRealData[i];
1596                     pImgData[i] = m_pImgData[i];
1597                 }
1598             }
1599             else
1600             {
1601                 // first resize, iOldSizeMax don't contain the 10%
1602                 iOldSizeMax = iPreviousNewIdx;
1603             }
1604
1605             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1606             {
1607                 T pTemp = getNullValue();
1608                 pRealData[i] = copyValue(pTemp);
1609                 pImgData[i] = copyValue(pTemp);
1610                 if (pTemp != pRealData[i])
1611                 {
1612                     deleteData(pTemp);
1613                 }
1614             }
1615
1616             delete[] piIndexes;
1617             //delete all array
1618             delete[] m_pRealData;
1619             delete[] m_pImgData;
1620             //replace old array by new one
1621             m_pRealData = pRealData;
1622             m_pImgData = pImgData;
1623         }
1624         else
1625         {
1626             //check if only the last dims change
1627             bool bNonLastDimChange = false;
1628             for (int i = 0; i < (m_iDims - 1); i++)
1629             {
1630                 if (m_piDims[i] != _piDims[i])
1631                 {
1632                     bNonLastDimChange = true;
1633                     break;
1634                 }
1635             }
1636
1637             //if vector or if row dimension not change, we don't need to shift data
1638             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1639             {
1640                 //copy values into new one
1641                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1642                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1643                 for (int i = m_iSize - 1; i >= 0; i--)
1644                 {
1645                     getIndexes(i, piIndexes);
1646                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1647                     if (iNewIdx != i)
1648                     {
1649                         T pTemp = m_pRealData[iNewIdx];
1650                         m_pRealData[iNewIdx] = m_pRealData[i];
1651                         m_pRealData[i] = pTemp;
1652
1653                         pTemp = m_pImgData[iNewIdx];
1654                         m_pImgData[iNewIdx] = m_pImgData[i];
1655                         m_pImgData[i] = pTemp;
1656                     }
1657                 }
1658                 delete[] piIndexes;
1659             }
1660         }
1661     }
1662     else
1663     {
1664         iNewSize = get_max_size(_piDims, _iDims);
1665         if (iNewSize > m_iSizeMax)
1666         {
1667             //alloc 10% bigger than asked to prevent future resize
1668             int iOldSizeMax = m_iSizeMax;
1669             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1670             pRealData = allocData(m_iSizeMax);
1671
1672             //copy values into new one
1673             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1674             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1675             for (int i = 0; i < _iDims; i++)
1676             {
1677                 piIndexes[i] = 0;
1678             }
1679
1680             int iPreviousNewIdx = 0;
1681             for (int i = 0; i < m_iSize; i++)
1682             {
1683                 getIndexes(i, piIndexes);
1684                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1685                 pRealData[iNewIdx] = m_pRealData[i];
1686                 m_pRealData[i] = T();
1687
1688                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1689                 {
1690                     T pTemp = getNullValue();
1691                     T pTemp2 = copyValue(pTemp);
1692                     pRealData[j] = pTemp2;
1693                     if (pTemp != pTemp2)
1694                     {
1695                         deleteData(pTemp);
1696                     }
1697                 }
1698
1699                 iPreviousNewIdx = iNewIdx + 1;
1700             }
1701
1702             //clean section between m_iSize and iOldSizeMax
1703             for (int i = m_iSize; i < iOldSizeMax; ++i)
1704             {
1705                 deleteData(m_pRealData[i]);
1706                 m_pRealData[i] = T();
1707             }
1708
1709             //if (iPreviousNewIdx < iOldSizeMax)
1710             //{
1711             //    for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1712             //    {
1713             //        pRealData[i] = m_pRealData[i];
1714             //        m_pRealData[i] = T();
1715             //    }
1716             //}
1717             //else
1718             //{
1719             //    iOldSizeMax = iPreviousNewIdx;
1720             //}
1721
1722             //fill exceeded with NullValue
1723             for (int i = iPreviousNewIdx; i < m_iSizeMax; ++i)
1724             {
1725                 T pTemp = getNullValue();
1726                 T pTemp2 = copyValue(pTemp);
1727                 pRealData[i] = pTemp2;
1728                 if (pTemp != pTemp2)
1729                 {
1730                     deleteData(pTemp);
1731                 }
1732             }
1733
1734             delete[] piIndexes;
1735             //delete all array
1736             delete[] m_pRealData;
1737             //replace old array by new one
1738             m_pRealData = pRealData;
1739         }
1740         else
1741         {
1742             //check if only the last dims change
1743             bool bNonLastDimChange = false;
1744             for (int i = 0; i < (m_iDims - 1); i++)
1745             {
1746                 if (m_piDims[i] != _piDims[i])
1747                 {
1748                     bNonLastDimChange = true;
1749                     break;
1750                 }
1751             }
1752
1753             //if vector or if row dimension not change, we don't need to shift data
1754             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1755             {
1756                 //copy values into new one
1757                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1758                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1759                 for (int i = m_iSize - 1; i >= 0; i--)
1760                 {
1761                     getIndexes(i, piIndexes);
1762                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1763                     if (iNewIdx != i)
1764                     {
1765                         T pTemp = m_pRealData[iNewIdx];
1766                         m_pRealData[iNewIdx] = m_pRealData[i];
1767                         m_pRealData[i] = pTemp;
1768                     }
1769                 }
1770                 delete[] piIndexes;
1771             }
1772         }
1773     }
1774
1775     if (_iDims != m_iDims)
1776     {
1777         //int* piDims = new int[_iDims];
1778         for (int i = 0; i < _iDims; i++)
1779         {
1780             m_piDims[i] = _piDims[i];
1781         }
1782         //delete[] m_piDims;
1783         //m_piDims = piDims;
1784         m_iDims = _iDims;
1785     }
1786     else
1787     {
1788         for (int i = 0; i < m_iDims; i++)
1789         {
1790             m_piDims[i] = _piDims[i];
1791         }
1792     }
1793     m_iRows = m_piDims[0];
1794     m_iCols = m_piDims[1];
1795     m_iSize = iNewSize;
1796     return this;
1797 }
1798
1799 template <typename T>
1800 bool ArrayOf<T>::isTrue()
1801 {
1802     return type_traits::isTrue<T>(m_iSize, m_pRealData);
1803 }
1804
1805 template<typename T>
1806 bool ArrayOf<T>::neg(InternalType *& out)
1807 {
1808     out = new Bool(this->m_iDims, this->m_piDims);
1809     type_traits::neg<T, int>(this->m_iSize, this->m_pRealData, static_cast<Bool *>(out)->get());
1810
1811     return true;
1812 }
1813
1814 template<typename T>
1815 bool ArrayOf<T>::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
1816 {
1817     if (in.size() == 0)
1818     {
1819         out.push_back(this);
1820     }
1821     else
1822     {
1823         InternalType * _out = extract(&in);
1824         if (!_out)
1825         {
1826             std::wostringstream os;
1827             os << _W("Invalid index.\n");
1828             throw ast::InternalError(os.str(), 999, e.getLocation());
1829         }
1830         out.push_back(_out);
1831     }
1832
1833     return true;
1834 }
1835
1836 template<typename T>
1837 bool ArrayOf<T>::isInvokable() const
1838 {
1839     return true;
1840 }
1841
1842 template<typename T>
1843 bool ArrayOf<T>::hasInvokeOption() const
1844 {
1845     return false;
1846 }
1847
1848 template<typename T>
1849 int ArrayOf<T>::getInvokeNbIn()
1850 {
1851     return -1;
1852 }
1853
1854 template<typename T>
1855 int ArrayOf<T>::getInvokeNbOut()
1856 {
1857     return 1;
1858 }
1859
1860
1861 // used to allow definition of ArrayOf methode in this cpp file.
1862 template class EXTERN_AST ArrayOf < char >;
1863 template class EXTERN_AST ArrayOf < unsigned char >;
1864 template class EXTERN_AST ArrayOf < short >;
1865 template class EXTERN_AST ArrayOf < unsigned short >;
1866 template class EXTERN_AST ArrayOf < int >;
1867 template class EXTERN_AST ArrayOf < unsigned int >;
1868 template class EXTERN_AST ArrayOf < long long >;
1869 template class EXTERN_AST ArrayOf < unsigned long long >;
1870 template class EXTERN_AST ArrayOf < double >;
1871 template class EXTERN_AST ArrayOf < wchar_t* >;
1872 template class EXTERN_AST ArrayOf < SinglePoly* >;
1873 template class EXTERN_AST ArrayOf < SingleStruct* >;
1874 template class EXTERN_AST ArrayOf < InternalType* >; // Cell
1875 }