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