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