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