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