Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / ast / includes / analysis / gvn / SymbolicDimension.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
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 __SYMBOLIC_DIMENSION_HXX__
17 #define __SYMBOLIC_DIMENSION_HXX__
18
19 #include <iostream>
20
21 #include "GVN.hxx"
22 #include "tools.hxx"
23
24 namespace analysis
25 {
26
27 /**
28  * \class SymbolicDimension
29  * \brief Manage a symbolic dimension
30  */
31 class SymbolicDimension
32 {
33     GVN * gvn;
34     GVN::Value * value;
35
36 public:
37
38     /**
39      * \brief default constructor
40      */
41     SymbolicDimension() : gvn(nullptr), value(nullptr) { }
42
43     /**
44      * \brief constructor
45      * \param _gvn the GVN associated with this dimension
46      */
47     SymbolicDimension(GVN & _gvn) : gvn(&_gvn), value(_gvn.getValue()) { }
48
49     /**
50      * \brief constructor
51      * \param _gvn the GVN associated with this dimension
52      * \param _value the value of this dimension
53      */
54     SymbolicDimension(GVN * _gvn, GVN::Value * _value) : gvn(_gvn), value(_value) { }
55
56     /**
57      * \brief constructor
58      * \param _gvn the GVN associated with this dimension
59      * \param _value the value of this dimension
60      */
61     SymbolicDimension(GVN & _gvn, GVN::Value * _value) : gvn(&_gvn), value(_value) { }
62
63     /**
64      * \brief constructor
65      * \param _gvn the GVN associated with this dimension
66      * \param dim the value of this dimension
67      */
68     SymbolicDimension(GVN & _gvn, int64_t dim) : gvn(&_gvn), value(dim == -1 ? _gvn.getValue() : _gvn.getValue((double)dim)) { }
69
70     /**
71      * \brief Get the associated GVN
72      * \return the GVN
73      */
74     inline GVN * getGVN()
75     {
76         return gvn;
77     }
78
79     /**
80      * \brief Check if this dimension is empty
81      * \return true if empty
82      */
83     inline bool empty() const
84     {
85         return gvn == nullptr || value == nullptr;
86     }
87
88     /**
89      * \brief Check if this dimension is valid
90      * \return true if valid
91      */
92     inline bool isValid() const
93     {
94         return gvn != nullptr;
95     }
96
97     /**
98      * \brief Check if this dimension is constant (i.e. the associated polynomial is constant)
99      * \return true if constant
100      */
101     inline bool isConstant() const
102     {
103         return value->poly->isConstant();
104     }
105
106     /**
107      * \brief Get the constant part of the associated polynomial
108      * \return the constant
109      */
110     inline int64_t getConstant() const
111     {
112         return value->poly->constant;
113     }
114
115     /**
116      * \brief Get the associated polynomial
117      * \return a polynomial
118      */
119     inline const MultivariatePolynomial * getPoly() const
120     {
121         return value->poly;
122     }
123
124     /**
125      * \brief Get the associated Value
126      * \return a Value
127      */
128     inline const GVN::Value * getValue() const
129     {
130         return value;
131     }
132
133     /**
134      * \brief Get the associated Value
135      * \return a Value
136      */
137     inline GVN::Value * getValue()
138     {
139         return value;
140     }
141
142     /**
143      * \brief Set the associated Value
144      * \param _value a Value
145      */
146     inline void setValue(GVN::Value * _value)
147     {
148         value = _value;
149     }
150
151     /**
152      * \brief Set the associated Value
153      * \param _value a Value
154      */
155     inline void setValue(const int64_t _value)
156     {
157         value = gvn->getValue((double)_value);
158     }
159
160     /**
161      * \brief Set the associated GVN
162      * \param _gvn a GVN
163      */
164     inline void setGVN(GVN * _gvn)
165     {
166         gvn = _gvn;
167     }
168
169     /**
170      * \brief merge two dimensions considered as a max (cf Info::maxIndex)
171      * \param dim a dim
172      */
173     inline void mergeAsMax(const SymbolicDimension & dim)
174     {
175         bool mustInvalidate = true;
176         if (isValid() && dim.isValid())
177         {
178             if (value->poly && dim.value->poly)
179             {
180                 MultivariatePolynomial mp = *value->poly - *dim.value->poly;
181                 if (mp.isCoeffPositive())
182                 {
183                     value = dim.value;
184                     mustInvalidate = false;
185                 }
186                 else if (mp.isCoeffNegative())
187                 {
188                     mustInvalidate = false;
189                 }
190             }
191         }
192         if (mustInvalidate && gvn)
193         {
194             gvn = nullptr;
195             value = nullptr;
196         }
197     }
198
199     /**
200      * \brief Overload of the + operator
201      */
202     inline SymbolicDimension operator+(const SymbolicDimension & R) const
203     {
204         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::PLUS, *value, *R.value));
205     }
206
207     /**
208      * \brief Overload of the + operator
209      */
210     inline SymbolicDimension operator+(const int64_t R) const
211     {
212         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::PLUS, *value, *gvn->getValue((double)R)));
213     }
214
215     /**
216      * \brief Overload of the - operator
217      */
218     inline SymbolicDimension operator-(const SymbolicDimension & R) const
219     {
220         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::MINUS, *value, *R.value));
221     }
222
223     /**
224      * \brief Overload of the - operator
225      */
226     inline SymbolicDimension operator-(const int64_t R) const
227     {
228         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::MINUS, *value, *gvn->getValue((double)R)));
229     }
230
231     /**
232      * \brief Overload of the * operator
233      */
234     inline SymbolicDimension operator*(const SymbolicDimension & R) const
235     {
236         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::TIMES, *value, *R.value));
237     }
238
239     /**
240      * \brief Overload of the * operator
241      */
242     inline SymbolicDimension operator*(const int64_t R) const
243     {
244         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::TIMES, *value, *gvn->getValue((double)R)));
245     }
246
247     /**
248      * \brief Overload of the *= operator
249      */
250     inline SymbolicDimension & operator*=(const SymbolicDimension & R)
251     {
252         if (R != 1)
253         {
254             if (*this != 1)
255             {
256                 value = gvn->getValue(OpValue::Kind::TIMES, *value, *R.value);
257             }
258             else
259             {
260                 value = R.value;
261             }
262         }
263
264         return *this;
265     }
266
267     /**
268      * \brief Overload of the / operator
269      */
270     inline SymbolicDimension operator/(const SymbolicDimension & R) const
271     {
272         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::RDIV, *value, *R.value));
273     }
274
275     /**
276      * \brief Overload of the / operator
277      */
278     inline SymbolicDimension operator/(const int64_t R) const
279     {
280         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::RDIV, *value, *gvn->getValue((double)R)));
281     }
282
283     /**
284      * \brief Overload of the ^ operator
285      */
286     inline SymbolicDimension operator^(const SymbolicDimension & R) const
287     {
288         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::POWER, *value, *R.value));
289     }
290
291     /**
292      * \brief Overload of the ^ operator
293      */
294     inline SymbolicDimension operator^(const int64_t R) const
295     {
296         return SymbolicDimension(gvn, gvn->getValue(OpValue::Kind::POWER, *value, *gvn->getValue((double)R)));
297     }
298
299     /**
300      * \brief Overload of the == operator
301      */
302     inline bool operator==(const SymbolicDimension & R) const
303     {
304         return value->value == R.value->value;
305     }
306
307     /**
308      * \brief Overload of the == operator
309      */
310     inline bool operator==(const int64_t R) const
311     {
312         return value->poly->isConstant(R);
313     }
314
315     /**
316      * \brief Overload of the != operator
317      */
318     inline bool operator!=(const SymbolicDimension & R) const
319     {
320         return value->value != R.value->value;
321     }
322
323     /**
324      * \brief Overload of the != operator
325      */
326     inline bool operator!=(const int64_t R) const
327     {
328         return !value->poly->isConstant(R);
329     }
330
331     /**
332      * \brief Overload of the + operator
333      */
334     inline friend SymbolicDimension operator+(const int64_t L, const SymbolicDimension & R)
335     {
336         return R + L;
337     }
338
339     /**
340      * \brief Overload of the - operator
341      */
342     inline friend SymbolicDimension operator-(const int64_t L, const SymbolicDimension & R)
343     {
344         return SymbolicDimension(R.gvn, R.gvn->getValue(OpValue::Kind::MINUS, *R.gvn->getValue((double)L), *R.value));
345     }
346
347     /**
348      * \brief Overload of the * operator
349      */
350     inline friend SymbolicDimension operator*(const int64_t L, const SymbolicDimension & R)
351     {
352         return R * L;
353     }
354
355     /**
356      * \brief Overload of the / operator
357      */
358     inline friend SymbolicDimension operator/(const int64_t L, const SymbolicDimension & R)
359     {
360         return SymbolicDimension(R.gvn, R.gvn->getValue(OpValue::Kind::RDIV, *R.gvn->getValue((double)L), *R.value));
361     }
362
363     /**
364      * \brief Overload of the ^ operator
365      */
366     inline friend SymbolicDimension operator^(const int64_t L, const SymbolicDimension & R)
367     {
368         return SymbolicDimension(R.gvn, R.gvn->getValue(OpValue::Kind::POWER, *R.gvn->getValue((double)L), *R.value));
369     }
370
371     /**
372      * \brief Overload of the == operator
373      */
374     inline friend bool operator==(const int64_t L, const SymbolicDimension & R)
375     {
376         return R == L;
377     }
378
379     /**
380      * \brief Overload of the != operator
381      */
382     inline friend bool operator!=(const int64_t L, const SymbolicDimension & R)
383     {
384         return R != L;
385     }
386
387     /**
388      * \brief Overload of the << operator
389      */
390     friend inline std::ostream & operator<<(std::ostream & out, const SymbolicDimension & d)
391     {
392         out << *d.value->poly;
393
394         return out;
395     }
396 };
397
398 } // namespace analysis
399
400 #endif // __SYMBOLIC_DIMENSION_HXX__