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