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