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