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