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