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