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