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