32727e4144f149efb3521ab266d8107eb877690b
[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 (piCountDim[i] == piSourceDims[iSource] && (piCountDim[i] > 1 || iNbColon < iSourceDims))
693             {
694                 ++iSource;
695             }
696         }
697         delete[] piSourceDims;
698     }
699
700     //remove last dimension at size 1
701     //remove last dimension if are == 1
702     for (int i = (iDims - 1); i >= 2; i--)
703     {
704         if (piMaxDim[i] == 1)
705         {
706             iDims--;
707             pArg.back()->killMe();
708             pArg.pop_back();
709         }
710         else
711         {
712             break;
713         }
714     }
715
716     if (checkArgValidity(pArg) == false)
717     {
718         delete[] piMaxDim;
719         delete[] piCountDim;
720         //free pArg content
721         cleanIndexesArguments(_pArgs, &pArg);
722         //contain bad index, like <= 0, ...
723         return NULL;
724     }
725
726     if (iDims == 1)
727     {
728         if (getCols() == 1)
729         {
730             int piRealDim[2] = {piMaxDim[0], 1};
731             pOut = createEmpty(2, piRealDim, bComplex);
732         }
733         else
734         {
735             //rows == 1
736             int piRealDim[2] = {1, piMaxDim[0]};
737             pOut = createEmpty(2, piRealDim, bComplex);
738         }
739     }
740     else
741     {
742         pOut = createEmpty(iDims, piMaxDim, bComplex);
743     }
744
745
746     //fill with null item
747     ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
748     pArrayOut->fillDefaultValues();
749     //T* pRealData = pArrayOut->get();
750     //if (bComplex)
751     //{
752     //    int size = pArrayOut->getSize();
753     //    T* pImgData = pArrayOut->getImg();
754
755     //    if (isNativeType())
756     //    {
757     //        T val = getNullValue();
758     //        for (int i = 0; i < size; i++)
759     //        {
760     //            pRealData[i] = val;
761     //            pImgData[i] = val;
762     //        }
763     //    }
764     //    else
765     //    {
766     //        for (int i = 0; i < size; i++)
767     //        {
768     //            pArrayOut->deleteData(pRealData[i]);
769     //            pRealData[i] = getNullValue();
770     //            pArrayOut->deleteData(pImgData[i]);
771     //            pImgData[i] = getNullValue();
772     //        }
773     //    }
774     //}
775     //else
776     //{
777     //    int size = pArrayOut->getSize();
778     //    if (isNativeType())
779     //    {
780     //        T val = getNullValue();
781     //        for (int i = 0; i < size; i++)
782     //        {
783     //            pRealData[i] = val;
784     //        }
785     //    }
786     //    else
787     //    {
788     //        for (int i = 0; i < size; i++)
789     //        {
790     //            pArrayOut->deleteData(pRealData[i]);
791     //            pRealData[i] = getNullValue();
792     //        }
793     //    }
794     //}
795
796     //insert values in new matrix
797     ArrayOf* pOut2 = pArrayOut->insert(&pArg, this);
798     if (pOut != pOut2)
799     {
800         delete pOut;
801     }
802
803     delete[] piMaxDim;
804     delete[] piCountDim;
805     //free pArg content
806     cleanIndexesArguments(_pArgs, &pArg);
807
808     return pOut2;
809 }
810
811 template <typename T>
812 ArrayOf<T>* ArrayOf<T>::append(int _iRows, int _iCols, InternalType* _poSource)
813 {
814     ArrayOf<T>* pIT = checkRef(this, &ArrayOf::append, _iRows, _iCols, _poSource);
815     if (pIT != this)
816     {
817         return pIT;
818     }
819
820     _poSource->IncreaseRef();
821     ArrayOf * pGT = _poSource->getAs<ArrayOf>();
822     int iRows = pGT->getRows();
823     int iCols = pGT->getCols();
824
825     //insert without resize
826     if (iRows + _iRows > m_iRows || iCols + _iCols > m_iCols)
827     {
828         return NULL;
829     }
830
831     //Update complexity if necessary
832     if (pGT->isComplex())
833     {
834         setComplex(true);
835     }
836     else if (isComplex())
837     {
838         pGT = pGT->setComplex(true);
839     }
840
841     if (pGT->isComplex())
842     {
843         for (int i = 0; i < iRows; i++)
844         {
845             for (int j = 0; j < iCols; j++)
846             {
847                 set(_iRows + i, _iCols + j, pGT->get(i, j));
848                 setImg(_iRows + i, _iCols + j, pGT->getImg(i, j));
849             }
850         }
851     }
852     else
853     {
854         for (int i = 0; i < iRows; i++)
855         {
856             for (int j = 0; j < iCols; j++)
857             {
858                 set(_iRows + i, _iCols + j, pGT->get(i, j));
859             }
860         }
861     }
862
863     pGT->killMe();
864     _poSource->DecreaseRef();
865
866     return this;
867 }
868
869 template <typename T>
870 GenericType* ArrayOf<T>::remove(typed_list* _pArgs)
871 {
872     ArrayOf<T>* pOut = NULL;
873     int iDims = (int)_pArgs->size();
874     typed_list pArg;
875
876     int* piMaxDim = new int[iDims];
877     int* piCountDim = new int[iDims];
878
879     //evaluate each argument and replace by appropriate value and compute the count of combinations
880     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
881     delete[] piMaxDim;
882     delete[] piCountDim;
883     if (iSeqCount == 0)
884     {
885         //free pArg content
886         cleanIndexesArguments(_pArgs, &pArg);
887         //no Seq, no change but no error.
888         return this;
889     }
890
891     int iToDelIndex = -1;
892     std::vector<int> toDelIndexVect;
893
894     // dimensions not subject to deletion must be indexed with colon or equivalent
895     for (int i = 0; i < iDims; i++)
896     {
897         int iDimToCheck = getVarMaxDim(i, iDims);
898         int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
899         if ((*_pArgs)[i]->isColon() == false)
900         {
901             //if equivalent to colon, should be 1:iDimToCheck after sorting and removing duplicates
902             double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
903             std::vector<int> pIndexesVect(pIndexes, pIndexes + iIndexSize);
904             std::sort(pIndexesVect.begin(), pIndexesVect.end());
905             pIndexesVect.erase(unique(pIndexesVect.begin(), pIndexesVect.end()), pIndexesVect.end());
906             //remove index > iDimToCheck to allow a[10, 10](1, 1:100) = [] and a[10, 10]([1 5 20], :) = []
907             auto lastUnique = std::find_if(pIndexesVect.begin(), pIndexesVect.end(),
908                                            [&iDimToCheck](int idx) { return idx > iDimToCheck; });
909             pIndexesVect.erase(lastUnique, pIndexesVect.end());
910
911             if (pIndexesVect.size() != iDimToCheck)
912             {
913                 // index is not equivalent to colon -> index to delete
914                 if (iToDelIndex < 0)
915                 {
916                     iToDelIndex = i;
917                     toDelIndexVect = pIndexesVect;
918                 }
919                 else
920                 {
921                     //cannot delete indexes on more than one dimension
922                     //free pArg content
923                     cleanIndexesArguments(_pArgs, &pArg);
924                     return NULL;
925                 }
926             }
927         }
928     }
929
930     if (iToDelIndex < 0)
931     {
932         // overall removal x(:,...,:) = []
933         cleanIndexesArguments(_pArgs, &pArg);
934         return createEmpty();
935     }
936
937     if (toDelIndexVect.size() == 0)
938     {
939         // no removal because of too large indexes
940         cleanIndexesArguments(_pArgs, &pArg);
941         return this;
942     }
943
944     int iNewDimSize = getVarMaxDim(iToDelIndex, iDims) - toDelIndexVect.size();
945
946     int* piNewDims = new int[iDims];
947     for (int i = 0; i < iDims; i++)
948     {
949         piNewDims[i] = getVarMaxDim(i, iDims);
950     }
951     piNewDims[iToDelIndex] = iNewDimSize;
952
953     //remove last dimension if are == 1
954     int iOrigDims = iDims;
955     for (int i = (iDims - 1); i >= 2; i--)
956     {
957         if (piNewDims[i] == 1)
958         {
959             iDims--;
960         }
961         else
962         {
963             break;
964         }
965     }
966
967     if (iDims == 1)
968     {
969         //two cases, depends of original matrix/vector
970         if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
971         {
972             //special case for row vector
973             int piRealDim[2] = {1, iNewDimSize};
974             //in this case we have to care of 2nd dimension
975             //iToDelIndex = 1;
976             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
977         }
978         else
979         {
980             int piRealDim[2] = {iNewDimSize, 1};
981             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
982         }
983     }
984     else
985     {
986         pOut = createEmpty(iDims, piNewDims, m_pImgData != NULL);
987     }
988
989     // find a way to copy existing data to new variable ...
990     int* piViewDims = new int[iOrigDims];
991     int* piOffset = new int[iOrigDims+1];
992
993     // offsets
994     piOffset[0] = 1;
995     for (int i = 0; i < iOrigDims; i++)
996     {
997         piViewDims[i] = getVarMaxDim(i, iOrigDims);
998         piOffset[i+1] = piViewDims[i]*piOffset[i];
999     }
1000
1001     // indexes to remove -> [ 0, toDelIndexVect, piViewDims[iToDelIndex]+1 ] to facilitate loop
1002     toDelIndexVect.insert(toDelIndexVect.begin(),0);
1003     toDelIndexVect.push_back(piViewDims[iToDelIndex]+1);
1004
1005     int iStart;
1006     int iSize;
1007     int iOffset1 = piOffset[iToDelIndex];
1008     int iOffset2 = piOffset[iToDelIndex+1];
1009     int iNbChunks = getSize()/iOffset2;
1010
1011     // fast algorithm (allowing in place removal if necessary)
1012     for (int k = 0, iDest = 0; k < iNbChunks; k++)
1013     {
1014         iStart = k*iOffset2;
1015         // loop on indexes to remove
1016         for (int j = 0; j < toDelIndexVect.size()-1; j++)
1017         {
1018             iSize =  (toDelIndexVect[j+1]-toDelIndexVect[j]-1)*iOffset1;
1019             if (isNativeType())
1020             {
1021                 memcpy(pOut->m_pRealData + iDest, m_pRealData + iStart, iSize*sizeof(T));
1022                 if (m_pImgData != NULL)
1023                 {
1024                     memcpy(pOut->m_pImgData + iDest, m_pImgData + iStart, iSize*sizeof(T));
1025                 }
1026                 iDest += iSize;
1027             }
1028             else
1029             {
1030                 for (int i = iStart; i < iStart+iSize; i++, iDest++)
1031                 {
1032                     pOut->set(iDest, get(i));
1033                     if (m_pImgData != NULL)
1034                     {
1035                         pOut->setImg(iDest, getImg(i));
1036                     }
1037                 }
1038             }
1039             iStart += iSize + iOffset1;
1040         }
1041     }
1042
1043     delete[] piViewDims;
1044     delete[] piOffset;
1045     delete[] piNewDims;
1046
1047     //free pArg content
1048     cleanIndexesArguments(_pArgs, &pArg);
1049
1050     return pOut;
1051 }
1052
1053 template <typename T>
1054 GenericType* ArrayOf<T>::extract(typed_list* _pArgs)
1055 {
1056     ArrayOf<T>* pOut = NULL;
1057     int iDims = (int)_pArgs->size();
1058     typed_list pArg;
1059
1060     int index;
1061     if (getScalarIndex(this, _pArgs, &index))
1062     {
1063         if (index < 0)
1064         {
1065             return NULL;
1066         }
1067
1068         if (getSize() == 0)
1069         {
1070             return createEmpty();
1071         }
1072
1073         if (index >= getSize())
1074         {
1075             return NULL;
1076         }
1077
1078         int dims[2] = {1, 1};
1079         pOut = createEmpty(2, dims, isComplex());;
1080         pOut->set(0, get(index));
1081         if (isComplex())
1082         {
1083             pOut->setImg(0, getImg(index));
1084         }
1085
1086         return pOut;
1087     }
1088
1089     std::vector<double> il;
1090     if (getScalarImplicitIndex(this, _pArgs, il))
1091     {
1092         double start = il[0];
1093         double step = il[1];
1094         double end = il[2];
1095         //index are ":"
1096         bool isForceColVector = il.size() == 4;
1097
1098         //std::cout << start << ":" << step << ":" << end << std::endl;
1099         int size = static_cast<int>((end - start) / step + 1);
1100
1101         if (size <= 0 || m_iSize == 0)
1102         {
1103             return createEmpty();
1104         }
1105
1106         //check bounds
1107         if (step > 0 && ((size - 1) * step + start > m_iSize || start < 1) ||
1108                 (step < 0 && (start > m_iSize || end < 1)))
1109         {
1110             return NULL;
1111         }
1112
1113         bool isRowVector = m_iRows == 1;
1114         isRowVector = isRowVector && !isForceColVector;
1115         int dims[2] = {isRowVector ? 1 : size, isRowVector ? size : 1};
1116         pOut = createEmpty(2, dims, isComplex());
1117         double idx = start;
1118
1119         if (isComplex())
1120         {
1121             for (int i = 0; i < size; ++i)
1122             {
1123                 int index = static_cast<int>(idx) - 1;
1124                 pOut->set(i, get(index));
1125                 pOut->setImg(i, getImg(index));
1126                 idx += step;
1127             }
1128         }
1129         else
1130         {
1131             for (int i = 0; i < size; ++i)
1132             {
1133                 pOut->set(i, get(static_cast<int>(idx) - 1));
1134                 idx += step;
1135             }
1136         }
1137         return pOut;
1138     }
1139
1140     std::vector<int> indexes;
1141     std::vector<int> dims;
1142     if (getImplicitIndex(this, _pArgs, indexes, dims))
1143     {
1144         if (indexes.size() == 0)
1145         {
1146             return createEmpty();
1147         }
1148
1149         if (dims.size() == 1)
1150         {
1151             int d[2] = {1, dims[0]};
1152             pOut = createEmpty(2, d, isComplex());
1153         }
1154         else
1155         {
1156             pOut = createEmpty(static_cast<int>(dims.size()), dims.data(), isComplex());
1157         }
1158
1159         int size = getSize();
1160         if (isComplex())
1161         {
1162             int idx = 0;
1163             for (int & i : indexes)
1164             {
1165                 if (i < 0 || i >= size)
1166                 {
1167                     pOut->killMe();
1168                     return NULL;
1169                 }
1170
1171                 pOut->set(idx, get(i));
1172                 pOut->setImg(idx, getImg(i));
1173                 ++idx;
1174             }
1175         }
1176         else
1177         {
1178             int idx = 0;
1179             for (int & i : indexes)
1180             {
1181                 pOut->set(idx, get(i));
1182                 ++idx;
1183             }
1184         }
1185
1186         return pOut;
1187     }
1188
1189
1190     int* piMaxDim = new int[iDims];
1191     int* piCountDim = new int[iDims];
1192
1193     //evaluate each argument and replace by appropriate value and compute the count of combinations
1194     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1195     if (iSeqCount == 0)
1196     {
1197         delete[] piMaxDim;
1198         delete[] piCountDim;
1199         //free pArg content
1200         cleanIndexesArguments(_pArgs, &pArg);
1201         return createEmpty();
1202     }
1203
1204     if (iSeqCount < 0)
1205     {
1206         delete[] piMaxDim;
1207         delete[] piCountDim;
1208         //free pArg content
1209         cleanIndexesArguments(_pArgs, &pArg);
1210         return NULL;
1211     }
1212
1213     //a = {};a(1:2, 1:2) -> {}
1214     if (getSize() == 0)
1215     {
1216         delete[] piMaxDim;
1217         delete[] piCountDim;
1218         //free pArg content
1219         cleanIndexesArguments(_pArgs, &pArg);
1220         return createEmpty();
1221     }
1222
1223     if (iDims < m_iDims)
1224     {
1225         for (int i = 0; i < iDims; i++)
1226         {
1227             int iDimToCheck = 0;
1228             if (i == (iDims - 1))
1229             {
1230                 iDimToCheck = getVarMaxDim(i, iDims);
1231             }
1232             else
1233             {
1234                 iDimToCheck = m_piDims[i];
1235             }
1236
1237             if (piMaxDim[i] > iDimToCheck)
1238             {
1239                 delete[] piMaxDim;
1240                 delete[] piCountDim;
1241                 //free pArg content
1242                 cleanIndexesArguments(_pArgs, &pArg);
1243                 return NULL;
1244             }
1245         }
1246     }
1247     else
1248     {
1249         if (iDims > m_iDims)
1250         {
1251             for (int i = m_iDims; i < iDims; i++)
1252             {
1253                 if (piMaxDim[i] > 1)
1254                 {
1255                     delete[] piMaxDim;
1256                     delete[] piCountDim;
1257                     //free pArg content
1258                     cleanIndexesArguments(_pArgs, &pArg);
1259                     return NULL;
1260                 }
1261             }
1262         }
1263
1264         //check MaxDim
1265         for (int i = 0; i < m_iDims; i++)
1266         {
1267             if (piMaxDim[i] > m_piDims[i])
1268             {
1269                 delete[] piMaxDim;
1270                 delete[] piCountDim;
1271                 //free pArg content
1272                 cleanIndexesArguments(_pArgs, &pArg);
1273                 //exrtact must be in dimension limits
1274                 return NULL;
1275             }
1276         }
1277     }
1278
1279     //remove last dimension if are == 1
1280     for (int i = (iDims - 1); i >= 2; i--)
1281     {
1282         if (piCountDim[i] == 1)
1283         {
1284             (iDims)--;
1285         }
1286         else
1287         {
1288             break;
1289         }
1290     }
1291
1292     //vector
1293     if (iDims == 1)
1294     {
1295         if (piCountDim[0] == 0)
1296         {
1297             delete[] piMaxDim;
1298             delete[] piCountDim;
1299             //free pArg content
1300             cleanIndexesArguments(_pArgs, &pArg);
1301             return createEmpty();
1302         }
1303         else
1304         {
1305             //two cases, depends of original matrix/vector
1306             if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[1] != 1 && m_piDims[0] == 1)
1307             {
1308                 //special case for row vector
1309                 int piRealDim[2] = {1, piCountDim[0]};
1310                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1311             }
1312             else
1313             {
1314                 if (getSize() == 1)
1315                 {
1316                     //for extraction on scalar
1317                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), pArg[0]->getAs<GenericType>()->getDimsArray(), m_pImgData != NULL);
1318                 }
1319                 else
1320                 {
1321                     int piRealDim[2] = {piCountDim[0], 1};
1322                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1323                 }
1324             }
1325         }
1326     }
1327     else
1328     {
1329         //matrix
1330         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1331     }
1332
1333     int* piIndex = new int[_pArgs->size()];
1334     int* piCoord = new int[_pArgs->size()];
1335     int* piViewDims = new int[iDims];
1336     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1337
1338     for (int i = 0; i < iDims; i++)
1339     {
1340         piViewDims[i] = getVarMaxDim(i, iDims);
1341     }
1342
1343     for (int i = 0; i < iSeqCount; i++)
1344     {
1345         //increment last dimension
1346         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1347
1348         //std::cout << "[";
1349         for (int j = 0; j < (int)_pArgs->size(); j++)
1350         {
1351             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1352             //InternalType* pVar = pArg[i];
1353             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1354             //std::cout << piCoord[j] << " ";
1355
1356             // try to access somewhere wrong.
1357             if (piCoord[j] < 0)
1358             {
1359                 delete[] piIndex;
1360                 delete[] piCoord;
1361                 delete[] piViewDims;
1362                 delete[] piMaxDim;
1363                 delete[] piCountDim;
1364
1365                 //free pArg content
1366                 cleanIndexesArguments(_pArgs, &pArg);
1367                 return NULL;
1368             }
1369         }
1370
1371         //std::cout << "]" << std::endl;
1372
1373         int iPos = 0;
1374         //put vlaue in the new matrix
1375         if ((int)_pArgs->size() < m_iDims)
1376         {
1377             //compute index based on viewed matrix
1378             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1379         }
1380         else
1381         {
1382             //compute vector index
1383             iPos = getIndex(piCoord);
1384         }
1385
1386         //convert flat dimension to 0
1387         for (int j = 0; j < iDims; j++)
1388         {
1389             if (piCountDim[j] == 1)
1390             {
1391                 piCoord[j] = 0;
1392             }
1393         }
1394
1395         pOut->set(i, get(iPos));
1396         if (m_pImgData != NULL)
1397         {
1398             pOut->setImg(i, getImg(iPos));
1399         }
1400
1401
1402         piIndex[0]++;
1403     }
1404
1405     //free pArg content
1406     cleanIndexesArguments(_pArgs, &pArg);
1407
1408     delete[] piIndex;
1409     delete[] piCoord;
1410     delete[] piViewDims;
1411     delete[] piMaxDim;
1412     delete[] piCountDim;
1413
1414     return pOut;
1415 }
1416
1417 template <typename T>
1418 ArrayOf<T>* ArrayOf<T>::reshape(int* _piDims, int _iDims)
1419 {
1420     typedef ArrayOf<T>* (ArrayOf<T>::*reshape_t)(int*, int);
1421     ArrayOf<T>* pIT = checkRef(this, (reshape_t)&ArrayOf<T>::reshape, _piDims, _iDims);
1422     if (pIT != this)
1423     {
1424         return pIT;
1425     }
1426
1427     int iNewSize = get_max_size(_piDims, _iDims);
1428     if (iNewSize != m_iSize)
1429     {
1430         return NULL;
1431     }
1432
1433     for (int i = 0 ; i < _iDims ; i++)
1434     {
1435         m_piDims[i] = _piDims[i];
1436     }
1437
1438     if (_iDims == 1)
1439     {
1440         m_piDims[1] = 1;
1441         _iDims++;
1442     }
1443
1444     int iDims = _iDims;
1445     for (int i = iDims - 1; i >= 2; --i)
1446     {
1447         if (m_piDims[i] == 1)
1448         {
1449             _iDims--;
1450         }
1451         else
1452         {
1453             break;
1454         }
1455     }
1456
1457     m_iRows = m_piDims[0];
1458     m_iCols = m_piDims[1];
1459     m_iSize = iNewSize;
1460     m_iDims = _iDims;
1461
1462     return this;
1463 }
1464
1465 template <typename T>
1466 ArrayOf<T>* ArrayOf<T>::resize(int* _piDims, int _iDims)
1467 {
1468     typedef ArrayOf<T>* (ArrayOf<T>::*resize_t)(int*, int);
1469     ArrayOf<T>* pIT = checkRef(this, (resize_t)&ArrayOf::resize, _piDims, _iDims);
1470     if (pIT != this)
1471     {
1472         return pIT;
1473     }
1474
1475     if (_iDims == m_iDims)
1476     {
1477         bool bChange = false;
1478         for (int i = 0; i < _iDims; i++)
1479         {
1480             if (m_piDims[i] != _piDims[i])
1481             {
1482                 bChange = true;
1483                 break;
1484             }
1485         }
1486
1487         if (bChange == false)
1488         {
1489             //nothing to do
1490             return this;
1491         }
1492     }
1493
1494     //alloc new data array
1495     T* pRealData = NULL;
1496     T* pImgData = NULL;
1497
1498     int iNewSize = 0;
1499     if (m_pImgData != NULL)
1500     {
1501         iNewSize = get_max_size(_piDims, _iDims);
1502         if (m_iSizeMax < iNewSize)
1503         {
1504             //alloc 10% bigger than asked to prevent future resize
1505             int iOldSizeMax = m_iSizeMax;
1506             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1507             pRealData = allocData(m_iSizeMax);
1508             pImgData = allocData(m_iSizeMax);
1509
1510             //copy values into new one
1511             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1512             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1513             for (int i = 0; i < _iDims; i++)
1514             {
1515                 piIndexes[i] = 0;
1516             }
1517
1518             int iPreviousNewIdx = 0;
1519             for (int i = 0; i < m_iSize; i++)
1520             {
1521                 getIndexes(i, piIndexes);
1522                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1523                 pRealData[iNewIdx] = m_pRealData[i];
1524                 pImgData[iNewIdx] = m_pImgData[i];
1525                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1526                 {
1527                     T pTemp = getNullValue();
1528                     pRealData[j] = copyValue(pTemp);
1529                     pImgData[j] = copyValue(pTemp);
1530                     if (pTemp != pRealData[j])
1531                     {
1532                         deleteData(pTemp);
1533                     }
1534                 }
1535
1536                 iPreviousNewIdx = iNewIdx + 1;
1537             }
1538
1539             // if it's not the first resize,
1540             // fill new data with element of last allocation
1541             if (iPreviousNewIdx < iOldSizeMax)
1542             {
1543                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1544                 {
1545                     pRealData[i] = m_pRealData[i];
1546                     pImgData[i] = m_pImgData[i];
1547                 }
1548             }
1549             else
1550             {
1551                 // first resize, iOldSizeMax don't contain the 10%
1552                 iOldSizeMax = iPreviousNewIdx;
1553             }
1554
1555             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1556             {
1557                 T pTemp = getNullValue();
1558                 pRealData[i] = copyValue(pTemp);
1559                 pImgData[i] = copyValue(pTemp);
1560                 if (pTemp != pRealData[i])
1561                 {
1562                     deleteData(pTemp);
1563                 }
1564             }
1565
1566             delete[] piIndexes;
1567             //delete all array
1568             delete[] m_pRealData;
1569             delete[] m_pImgData;
1570             //replace old array by new one
1571             m_pRealData = pRealData;
1572             m_pImgData = pImgData;
1573         }
1574         else
1575         {
1576             //check if only the last dims change
1577             bool bNonLastDimChange = false;
1578             for (int i = 0; i < (m_iDims - 1); i++)
1579             {
1580                 if (m_piDims[i] != _piDims[i])
1581                 {
1582                     bNonLastDimChange = true;
1583                     break;
1584                 }
1585             }
1586
1587             //if vector or if row dimension not change, we don't need to shift data
1588             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1589             {
1590                 //copy values into new one
1591                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1592                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1593                 for (int i = m_iSize - 1; i >= 0; i--)
1594                 {
1595                     getIndexes(i, piIndexes);
1596                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1597                     if (iNewIdx != i)
1598                     {
1599                         T pTemp = m_pRealData[iNewIdx];
1600                         m_pRealData[iNewIdx] = m_pRealData[i];
1601                         m_pRealData[i] = pTemp;
1602
1603                         pTemp = m_pImgData[iNewIdx];
1604                         m_pImgData[iNewIdx] = m_pImgData[i];
1605                         m_pImgData[i] = pTemp;
1606                     }
1607                 }
1608                 delete[] piIndexes;
1609             }
1610         }
1611     }
1612     else
1613     {
1614         iNewSize = get_max_size(_piDims, _iDims);
1615         if (iNewSize > m_iSizeMax)
1616         {
1617             //alloc 10% bigger than asked to prevent future resize
1618             int iOldSizeMax = m_iSizeMax;
1619             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1620             pRealData = allocData(m_iSizeMax);
1621
1622             //copy values into new one
1623             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1624             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1625             for (int i = 0; i < _iDims; i++)
1626             {
1627                 piIndexes[i] = 0;
1628             }
1629
1630             int iPreviousNewIdx = 0;
1631             for (int i = 0; i < m_iSize; i++)
1632             {
1633                 getIndexes(i, piIndexes);
1634                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1635                 pRealData[iNewIdx] = m_pRealData[i];
1636                 m_pRealData[i] = NULL;
1637
1638                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1639                 {
1640                     T pTemp = getNullValue();
1641                     T pTemp2 = copyValue(pTemp);
1642                     pRealData[j] = pTemp2;
1643                     if (pTemp != pTemp2)
1644                     {
1645                         deleteData(pTemp);
1646                     }
1647                 }
1648
1649                 iPreviousNewIdx = iNewIdx + 1;
1650             }
1651
1652             //clean section between m_iSize and iOldSizeMax
1653             for (int i = m_iSize; i < iOldSizeMax; ++i)
1654             {
1655                 deleteData(m_pRealData[i]);
1656                 m_pRealData[i] = NULL;
1657             }
1658
1659             //if (iPreviousNewIdx < iOldSizeMax)
1660             //{
1661             //    for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1662             //    {
1663             //        pRealData[i] = m_pRealData[i];
1664             //        m_pRealData[i] = NULL;
1665             //    }
1666             //}
1667             //else
1668             //{
1669             //    iOldSizeMax = iPreviousNewIdx;
1670             //}
1671
1672             //fill exceeded with NullValue
1673             for (int i = iPreviousNewIdx; i < m_iSizeMax; ++i)
1674             {
1675                 T pTemp = getNullValue();
1676                 T pTemp2 = copyValue(pTemp);
1677                 pRealData[i] = pTemp2;
1678                 if (pTemp != pTemp2)
1679                 {
1680                     deleteData(pTemp);
1681                 }
1682             }
1683
1684             delete[] piIndexes;
1685             //delete all array
1686             delete[] m_pRealData;
1687             //replace old array by new one
1688             m_pRealData = pRealData;
1689         }
1690         else
1691         {
1692             //check if only the last dims change
1693             bool bNonLastDimChange = false;
1694             for (int i = 0; i < (m_iDims - 1); i++)
1695             {
1696                 if (m_piDims[i] != _piDims[i])
1697                 {
1698                     bNonLastDimChange = true;
1699                     break;
1700                 }
1701             }
1702
1703             //if vector or if row dimension not change, we don't need to shift data
1704             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1705             {
1706                 //copy values into new one
1707                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1708                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1709                 for (int i = m_iSize - 1; i >= 0; i--)
1710                 {
1711                     getIndexes(i, piIndexes);
1712                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1713                     if (iNewIdx != i)
1714                     {
1715                         T pTemp = m_pRealData[iNewIdx];
1716                         m_pRealData[iNewIdx] = m_pRealData[i];
1717                         m_pRealData[i] = pTemp;
1718                     }
1719                 }
1720                 delete[] piIndexes;
1721             }
1722         }
1723     }
1724
1725     if (_iDims != m_iDims)
1726     {
1727         //int* piDims = new int[_iDims];
1728         for (int i = 0; i < _iDims; i++)
1729         {
1730             m_piDims[i] = _piDims[i];
1731         }
1732         //delete[] m_piDims;
1733         //m_piDims = piDims;
1734         m_iDims = _iDims;
1735     }
1736     else
1737     {
1738         for (int i = 0; i < m_iDims; i++)
1739         {
1740             m_piDims[i] = _piDims[i];
1741         }
1742     }
1743     m_iRows = m_piDims[0];
1744     m_iCols = m_piDims[1];
1745     m_iSize = iNewSize;
1746     return this;
1747 }
1748
1749 template <typename T>
1750 bool ArrayOf<T>::isTrue()
1751 {
1752     return type_traits::isTrue<T>(m_iSize, m_pRealData);
1753 }
1754
1755 template<typename T>
1756 bool ArrayOf<T>::neg(InternalType *& out)
1757 {
1758     out = new Bool(this->m_iDims, this->m_piDims);
1759     type_traits::neg<T, int>(this->m_iSize, this->m_pRealData, static_cast<Bool *>(out)->get());
1760
1761     return true;
1762 }
1763
1764 template<typename T>
1765 bool ArrayOf<T>::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
1766 {
1767     if (in.size() == 0)
1768     {
1769         out.push_back(this);
1770     }
1771     else
1772     {
1773         InternalType * _out = extract(&in);
1774         if (!_out)
1775         {
1776             std::wostringstream os;
1777             os << _W("Invalid index.\n");
1778             throw ast::InternalError(os.str(), 999, e.getLocation());
1779         }
1780         out.push_back(_out);
1781     }
1782
1783     return true;
1784 }
1785
1786 template<typename T>
1787 bool ArrayOf<T>::isInvokable() const
1788 {
1789     return true;
1790 }
1791
1792 template<typename T>
1793 bool ArrayOf<T>::hasInvokeOption() const
1794 {
1795     return false;
1796 }
1797
1798 template<typename T>
1799 int ArrayOf<T>::getInvokeNbIn()
1800 {
1801     return -1;
1802 }
1803
1804 template<typename T>
1805 int ArrayOf<T>::getInvokeNbOut()
1806 {
1807     return 1;
1808 }
1809
1810
1811 // used to allow definition of ArrayOf methode in this cpp file.
1812 template class EXTERN_AST ArrayOf < char >;
1813 template class EXTERN_AST ArrayOf < unsigned char >;
1814 template class EXTERN_AST ArrayOf < short >;
1815 template class EXTERN_AST ArrayOf < unsigned short >;
1816 template class EXTERN_AST ArrayOf < int >;
1817 template class EXTERN_AST ArrayOf < unsigned int >;
1818 template class EXTERN_AST ArrayOf < long long >;
1819 template class EXTERN_AST ArrayOf < unsigned long long >;
1820 template class EXTERN_AST ArrayOf < double >;
1821 template class EXTERN_AST ArrayOf < wchar_t* >;
1822 template class EXTERN_AST ArrayOf < SinglePoly* >;
1823 template class EXTERN_AST ArrayOf < SingleStruct* >;
1824 template class EXTERN_AST ArrayOf < InternalType* >; // Cell
1825 }