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