877b6e72bb5755e89ff2b01d36d6efc573f7c0d4
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #ifndef __ARRAYOF_HXX__
17 #define __ARRAYOF_HXX__
18
19 #ifdef _MSC_VER
20 #define NOMINMAX
21 #endif
22
23 #include <sstream>
24 #include <cstdio>
25 #include "types.hxx"
26 #include "scilabexception.hxx"
27 #include "inspector.hxx"
28
29 extern "C"
30 {
31 #include "core_math.h"
32 #include "localization.h"
33 #include "os_string.h"
34 }
35
36 namespace types
37 {
38
39 static int get_max_size(int* _piDims, int _iDims);
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     T*                      m_pRealData;
53     T*                      m_pImgData;
54
55
56     ArrayOf() : GenericType(), m_pRealData(NULL), m_pImgData(NULL) {}
57
58     virtual                 ~ArrayOf()
59     {
60         //delete[] m_piDims;
61     }
62
63
64     /*internal constructor*/
65     void create(const int* _piDims, int _iDims, T** _pRealData, T** _pImgData)
66     {
67         m_iSize     = 1;
68         m_iDims     = _iDims;
69
70         //reduce dims if it's possible
71         for (int i = _iDims - 1 ; i > 1 ; i--)
72         {
73             if (_piDims[i] == 1)
74             {
75                 //remove dimension equal to 1
76                 m_iDims--;
77             }
78             else
79             {
80                 break;
81             }
82         }
83
84         //m_piDims    = new int[m_iDims];
85
86         //eye detection ^^
87         if (m_iDims == 2 && _piDims[0] == -1 && _piDims[1] == -1)
88         {
89             m_iDims = 2;
90             m_piDims[0] = -1;
91             m_piDims[1] = -1;
92             m_iSize = 1;
93         }
94         else
95         {
96             for (int i = 0 ; i < m_iDims ; i++)
97             {
98                 // if one of dim is null, create an empty matrix
99                 if (_piDims[i] <= 0)
100                 {
101                     m_iDims = 2;
102                     m_piDims[0] = 0;
103                     m_piDims[1] = 0;
104                     m_iSize = 0;
105                     break;
106                 }
107
108                 m_piDims[i] = _piDims[i];
109
110                 /*
111                 ** Manage overflow on size
112                 ** a = b * c is in overflow if a / b != c
113                 ** check b is not 0 (empty matrix case)
114                 */
115                 int iTmpSize = m_iSize * m_piDims[i];
116                 if (m_iSize != 0 && iTmpSize / m_iSize != m_piDims[i])
117                 {
118                     char message[bsiz];
119                     os_sprintf(message, _("Can not allocate %.2f MB memory.\n"),  (double) ((double) m_iSize * (double) m_piDims[i] * sizeof(T)) / 1.e6);
120                     throw ast::InternalError(message);
121                 }
122
123                 m_iSize = iTmpSize;
124             }
125
126             if (m_iSize < 0)
127             {
128                 m_pRealData = NULL;
129                 m_pImgData = NULL;
130                 char message[bsiz];
131                 os_sprintf(message, _("Can not allocate negative size (%d).\n"), m_iSize);
132                 throw ast::InternalError(message);
133             }
134
135         }
136
137         try
138         {
139
140             if (_pRealData)
141             {
142                 m_pRealData = allocData(m_iSize);
143                 *_pRealData = m_pRealData;
144             }
145             else
146             {
147                 m_pRealData = NULL;
148             }
149
150             if (_pImgData)
151             {
152                 m_pImgData = allocData(m_iSize);
153                 *_pImgData = m_pImgData;
154             }
155             else
156             {
157                 m_pImgData = NULL;
158             }
159         }
160         catch (std::bad_alloc & /*e*/)
161         {
162             char message[bsiz];
163             os_sprintf(message, _("Can not allocate %.2f MB memory.\n"), (double)(m_iSize * sizeof(T)) / 1.e6);
164             throw ast::InternalError(message);
165         }
166
167         m_iSizeMax = m_iSize;
168         m_iRows = m_piDims[0];
169         m_iCols = m_piDims[1];
170     }
171
172     virtual T               getNullValue() = 0;
173     virtual ArrayOf<T>*     createEmpty(int _iDims, int* _piDims, bool _bComplex = false) = 0;
174     virtual GenericType*    createEmpty();
175
176     virtual T               copyValue(T _data) = 0;
177     virtual T*              allocData(int _iSize) = 0;
178     virtual void            deleteAll() = 0;
179     virtual void            deleteImg() = 0;
180 public :
181
182     bool isArrayOf()
183     {
184         return true;
185     }
186
187     bool isTrue();
188
189     // The function is not write here because we needs to create a Bool which inherits from ArrayOf<int>
190     // so it will create a cyclic dependency... so the body of the function is in bool.hxx after the Bool definition.
191     virtual bool neg(InternalType *& out);
192
193     virtual bool isVector() //only one dim must be != 1
194     {
195         bool bFirstChance = false;
196
197         for (int i = 0 ; i < m_iDims ; i++)
198         {
199             if (m_piDims[i] != 1)
200             {
201                 if (bFirstChance == true)
202                 {
203                     return false;
204                 }
205                 else
206                 {
207                     bFirstChance = true;
208                 }
209             }
210         }
211         return true;
212     }
213
214     virtual bool isComplex()
215     {
216         return m_pImgData != NULL;
217     }
218
219     virtual ArrayOf<T>* setComplex(bool _bComplex)
220     {
221         typedef ArrayOf<T>* (ArrayOf<T>::*setcplx_t)(bool);
222         ArrayOf<T>* pIT = checkRef(this, (setcplx_t)&ArrayOf<T>::setComplex, _bComplex);
223         if (pIT != this)
224         {
225             return pIT;
226         }
227
228         if (_bComplex == false)
229         {
230             if (m_pImgData != NULL)
231             {
232                 deleteImg();
233             }
234         }
235         else // _bComplex == true
236         {
237             if (m_pImgData == NULL)
238             {
239                 m_pImgData = allocData(m_iSize);
240                 memset(m_pImgData, 0x00, sizeof(T) * m_iSize);
241             }
242         }
243
244         return this;
245     }
246
247     virtual ArrayOf<T>* set(int _iPos, T _data)
248     {
249         if (m_pRealData == NULL || _iPos >= m_iSize)
250         {
251             return NULL;
252         }
253
254         typedef ArrayOf<T>* (ArrayOf<T>::*set_t)(int, T);
255         ArrayOf<T>* pIT = checkRef(this, (set_t)&ArrayOf<T>::set, _iPos, _data);
256         if (pIT != this)
257         {
258             return pIT;
259         }
260
261         deleteData(m_pRealData[_iPos]);
262         m_pRealData[_iPos] = copyValue(_data);
263         return this;
264     }
265
266     virtual ArrayOf<T>* set(int _iRows, int _iCols, T _data)
267     {
268         //            int piIndexes[2];
269         //            piIndexes[0] = _iRows;
270         //            piIndexes[1] = _iCols;
271         //            return set(getIndex(piIndexes), _data);
272         return set(_iCols * getRows() + _iRows, _data);
273     }
274
275     virtual ArrayOf<T>* set(T* _pdata)
276     {
277         if (m_pRealData == NULL)
278         {
279             return NULL;
280         }
281
282         typedef ArrayOf<T>* (ArrayOf<T>::*set_t)(T*);
283         ArrayOf<T>* pIT = checkRef(this, (set_t)&ArrayOf<T>::set, _pdata);
284         if (pIT != this)
285         {
286             return pIT;
287         }
288
289         for (int i = 0 ; i < m_iSize ; i++)
290         {
291             deleteData(m_pRealData[i]);
292             m_pRealData[i] = copyValue(_pdata[i]);
293         }
294         return this;
295     }
296
297     virtual ArrayOf<T>* set(const T* _pdata)
298     {
299         if (m_pRealData == NULL)
300         {
301             return NULL;
302         }
303
304         typedef ArrayOf<T>* (ArrayOf<T>::*set_t)(const T*);
305         ArrayOf<T>* pIT = checkRef(this, (set_t)&ArrayOf<T>::set, _pdata);
306         if (pIT != this)
307         {
308             return pIT;
309         }
310
311         for (int i = 0 ; i < m_iSize ; i++)
312         {
313             deleteData(m_pRealData[i]);
314             m_pRealData[i] = copyValue(_pdata[i]);
315         }
316
317         return this;
318     }
319
320     inline T* get() const
321     {
322         return m_pRealData;
323     }
324
325     inline T get(int _iPos)
326     {
327         if (m_pRealData)
328         {
329             return m_pRealData[_iPos];
330         }
331         return T();
332     }
333
334     inline T get(int _iRows, int _iCols)
335     {
336         int piIndexes[2] = {_iRows, _iCols};
337         return get(getIndex(piIndexes));
338     }
339
340     /*internal function to manage img part*/
341     ArrayOf<T>* setImg(int _iPos, T _data)
342     {
343         if (m_pImgData == NULL || _iPos >= m_iSize)
344         {
345             return NULL;
346         }
347
348         typedef ArrayOf<T>* (ArrayOf<T>::*setimg_t)(int, T);
349         ArrayOf<T>* pIT = checkRef(this, (setimg_t)&ArrayOf<T>::setImg, _iPos, _data);
350         if (pIT != this)
351         {
352             return pIT;
353         }
354
355         m_pImgData[_iPos] = copyValue(_data);
356         return this;
357     }
358
359
360     ArrayOf<T>* setImg(int _iRows, int _iCols, T _data)
361     {
362         int piIndexes[2] = {_iRows, _iCols};
363         return setImg(getIndex(piIndexes), copyValue(_data));
364     }
365
366     ArrayOf<T>* setImg(T* _pdata)
367     {
368         if (m_pImgData == NULL)
369         {
370             return NULL;
371         }
372
373         typedef ArrayOf<T>* (ArrayOf<T>::*setimg_t)(T*);
374         ArrayOf<T>* pIT = checkRef(this, (setimg_t)&ArrayOf<T>::setImg, _pdata);
375         if (pIT != this)
376         {
377             return pIT;
378         }
379
380         for (int i = 0 ; i < m_iSize ; i++)
381         {
382             m_pImgData[i] = copyValue(_pdata[i]);
383         }
384
385         return this;
386     }
387
388
389     ArrayOf<T>* setImg(const T* _pdata)
390     {
391         if (m_pImgData == NULL)
392         {
393             return NULL;
394         }
395
396         typedef ArrayOf<T>* (ArrayOf<T>::*setimg_t)(const T*);
397         ArrayOf<T>* pIT = checkRef(this, (setimg_t)&ArrayOf<T>::setImg, _pdata);
398         if (pIT != this)
399         {
400             return pIT;
401         }
402
403         for (int i = 0 ; i < m_iSize ; i++)
404         {
405             m_pImgData[i] = copyValue(_pdata[i]);
406         }
407
408         return this;
409     }
410
411     inline T* getImg() const
412     {
413         return m_pImgData;
414     }
415
416     inline T getImg(int _iPos)
417     {
418         if (m_pImgData)
419         {
420             return m_pImgData[_iPos];
421         }
422         return T();
423     }
424
425     inline T getImg(int _iRows, int _iCols)
426     {
427         int piIndexes[2] = {_iRows, _iCols};
428         return getImg(getIndex(piIndexes));
429     }
430
431     virtual ArrayOf<T>* insert(typed_list* _pArgs, InternalType* _pSource);
432     virtual ArrayOf<T>* append(int _iRows, int _iCols, InternalType* _poSource);
433     virtual ArrayOf<T>* resize(int* _piDims, int _iDims);
434
435     // return a GenericType because of [] wich is a types::Double (can't be a ArrayOf<char>)
436     virtual GenericType* remove(typed_list* _pArgs);
437     virtual GenericType* extract(typed_list* _pArgs);
438     virtual GenericType* insertNew(typed_list* _pArgs);
439
440     virtual bool invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e) override;
441     virtual bool isInvokable() const;
442     virtual bool hasInvokeOption() const;
443     virtual int getInvokeNbIn();
444     virtual int getInvokeNbOut();
445
446     virtual ArrayOf<T>* reshape(int _iNewRows, int _iNewCols)
447     {
448         int piDims[2] = {_iNewRows, _iNewCols};
449         return reshape(piDims, 2);
450     }
451
452     virtual ArrayOf<T>* reshape(int* _piDims, int _iDims);
453
454
455     virtual ArrayOf<T>* resize(int _iNewRows, int _iNewCols)
456     {
457         int piDims[2] = {_iNewRows, _iNewCols};
458         return resize(piDims, 2);
459     }
460
461     virtual void deleteData(T /*data*/)
462     {
463     }
464
465     /*dimensions functions*/
466     int getIndex(const int* _piIndexes)
467     {
468         int idx = 0;
469         int iMult = 1;
470         for (int i = 0 ; i < m_iDims ; i++)
471         {
472             idx += _piIndexes[i] * iMult;
473             iMult *= m_piDims[i];
474         }
475         return idx;
476     }
477
478     void getIndexes(int _iIndex, int* _piIndexes);
479
480     ArrayOf<T>* getColumnValues(int _iPos)
481     {
482         ArrayOf<T>* pOut = NULL;
483         if (_iPos < m_iCols)
484         {
485             int piDims[2] = {m_iRows, 1};
486             pOut = createEmpty(2, piDims, m_pImgData != NULL);
487             T* pReal    = pOut->get();
488             T* pImg     = pOut->getImg();
489             for (int i = 0 ; i < m_iRows ; i++)
490             {
491                 pReal[i] = copyValue(get(i, _iPos));
492             }
493
494             if (m_pImgData != NULL)
495             {
496                 for (int i = 0 ; i < m_iRows ; i++)
497                 {
498                     pImg[i] = copyValue(getImg(i, _iPos));
499                 }
500             }
501         }
502         return pOut;
503     }
504
505     virtual bool toString(std::wostringstream& ostr)
506     {
507         int* piDims = new int[m_iDims];
508         bool bFinish = parseSubMatrix(ostr, piDims, m_iDims, m_iDims - 1);
509         delete[] piDims;
510         return bFinish;
511     }
512
513     bool parseSubMatrix(std::wostringstream& ostr, int* _piDims, int _iDims, int _iDim)
514     {
515         bool bFinish = false;
516         if (_iDim == 1)
517         {
518             //we have reach 2-dim matrix
519
520             if (m_iDims > 2 && m_bPrintFromStart)
521             {
522                 //only print for dims > 2
523                 ostr << L"(:,:";
524                 for (int i = 2 ; i < _iDims ; i++)
525                 {
526                     ostr << L"," << (_piDims[i] + 1);
527                 }
528                 ostr << L")" << std::endl << std::endl;
529             }
530
531             //reset flag to print dims on next call
532             m_bPrintFromStart = true;
533
534             bFinish = subMatrixToString(ostr, _piDims, _iDims);
535             if (bFinish == false)
536             {
537                 //save print status
538                 m_bPrintFromStart = false;
539                 return false;
540             }
541         }
542         else
543         {
544             //draw, continue to dig
545             for (int i = m_iSavePrintState ; i < m_piDims[_iDim] ; i++)
546             {
547                 _piDims[_iDim] = i;
548                 bFinish = parseSubMatrix(ostr, _piDims, _iDims, _iDim - 1);
549                 if (bFinish == false)
550                 {
551                     //save print status
552                     m_iSavePrintState = i;
553                     return false;
554                 }
555             }
556
557             //reset state to print from state
558             m_iSavePrintState = 0;
559             m_iRows1PrintState = 0;
560             m_iCols1PrintState = 0;
561             m_iRows2PrintState = 0;
562             m_iCols2PrintState = 0;
563         }
564
565         return true;
566     }
567
568     virtual bool subMatrixToString(std::wostringstream& ostr, int* _piDims, int _iDims) = 0;
569
570     virtual std::wstring toStringInLine()
571     {
572         std::wostringstream ostr;
573         ostr << L"[";
574
575         for (int i = 0 ; i < m_iDims ; i++)
576         {
577             if (i > 0)
578             {
579                 ostr << L"x";
580             }
581
582             ostr << m_piDims[i];
583         }
584
585         ostr << L" " << getTypeStr() << L"]";
586         return ostr.str();
587     }
588 };
589
590 static int get_max_size(int* _piDims, int _iDims)
591 {
592     if (_iDims == 0)
593     {
594         return 0;
595     }
596
597     int iMax = 1;
598     for (int i = 0 ; i < _iDims ; i++)
599     {
600         iMax *= _piDims[i];
601     }
602     return iMax;
603 }
604 }
605
606 #endif /* !__ARRAYOF_HXX__ */