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