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 __OPVALUE_HXX__
17 #define __OPVALUE_HXX__
18 
19 #include <iostream>
20 
21 #include "tools.hxx"
22 
23 namespace analysis
24 {
25 
26 /**
27  * \struct OpValue
28  * \brief OpValue represents an operation between one or two operands
29  *
30  * This is struct is mainly used by the GVN.
31  */
32 struct OpValue
33 {
34     enum Kind : uint8_t
35     {
36         UNARYMINUS = 0, UNARYNEG, PLUS, MINUS, TIMES, DOTTIMES, RDIV, DOTRDIV, POWER, DOTPOWER
37     };
38     const Kind kind;
39     uint64_t lnum : 60;
40     uint64_t rnum : 60;
41 
42     /**
43      * \brief constructor for unary operation
44      * \param _kind the operation kind
45      * \param _lnum the value of the operand
46      */
OpValueanalysis::OpValue47     OpValue(Kind _kind, uint64_t _lnum) : kind(_kind), lnum(_lnum), rnum(0) { }
48 
49     /**
50      * \brief constructor for binary operation
51      * \param _kind the operation kind
52      * \param _lnum the value of the left operand
53      * \param _rnum the value of the right operand
54      */
OpValueanalysis::OpValue55     OpValue(Kind _kind, uint64_t _lnum, uint64_t _rnum) : kind(_kind), lnum(_lnum), rnum(_rnum)
56     {
57         if (isCommutative() && lnum > rnum)
58         {
59             const uint64_t x = lnum;
60             lnum = rnum;
61             rnum = x;
62         }
63     }
64 
65     /**
66      * \brief Check if the operation is commutative
67      * \return true if the operation is commutative
68      */
isCommutativeanalysis::OpValue69     inline bool isCommutative() const
70     {
71         return kind == PLUS || kind == TIMES || kind == DOTTIMES;
72     }
73 
74     /**
75      * \brief Check if the operation is unary
76      * \return true if the operation is unary
77      */
isUnaryanalysis::OpValue78     inline bool isUnary() const
79     {
80         return kind == UNARYMINUS || kind == UNARYNEG;
81     }
82 
83     /**
84      * \brief Compute the hash
85      * \return the hash
86      */
hashanalysis::OpValue87     inline std::size_t hash() const
88     {
89         return tools::hash_combine(kind, lnum, rnum);
90     }
91 
92     /**
93      * \brief Overload of the operator ==
94      */
operator ==analysis::OpValue95     inline bool operator==(const OpValue & R) const
96     {
97         if (kind == R.kind)
98         {
99             if (isUnary())
100             {
101                 return lnum == R.lnum;
102             }
103             else
104             {
105                 return lnum == R.lnum && rnum == R.rnum;
106             }
107         }
108         return false;
109     }
110 
111     /**
112      * \brief Overload of the operator <<
113      */
114     friend std::wostream & operator<<(std::wostream & out, const OpValue & ov);
115 
116     /**
117      * \struct Hash
118      * \brief Helper struct to be used in unordered_map
119      */
120     struct Hash
121     {
operator ()analysis::OpValue::Hash122         inline std::size_t operator()(const OpValue & ov) const
123         {
124             return ov.hash();
125         }
126     };
127 
128     /**
129      * \struct Eq
130      * \brief Helper struct to be used in unordered_map
131      */
132     struct Eq
133     {
operator ()analysis::OpValue::Eq134         inline bool operator()(const OpValue & L, const OpValue & R) const
135         {
136             return L == R;
137         }
138     };
139 };
140 
141 } // namespace analysis
142 
143 #endif // __OPVALUE_HXX__
144