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