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