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