mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move computation of constants out of types.cpp
This commit is contained in:
parent
d56a7bb89e
commit
49bde69afa
@ -32,6 +32,201 @@ using namespace solidity;
|
|||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Check whether (_base ** _exp) fits into 4096 bits.
|
||||||
|
bool fitsPrecisionExp(bigint const& _base, bigint const& _exp)
|
||||||
|
{
|
||||||
|
if (_base == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
solAssert(_base > 0, "");
|
||||||
|
|
||||||
|
size_t const bitsMax = 4096;
|
||||||
|
|
||||||
|
unsigned mostSignificantBaseBit = boost::multiprecision::msb(_base);
|
||||||
|
if (mostSignificantBaseBit == 0) // _base == 1
|
||||||
|
return true;
|
||||||
|
if (mostSignificantBaseBit > bitsMax) // _base >= 2 ^ 4096
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bigint bitsNeeded = _exp * (mostSignificantBaseBit + 1);
|
||||||
|
|
||||||
|
return bitsNeeded <= bitsMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks whether _mantissa * (2 ** _expBase10) fits into 4096 bits.
|
||||||
|
bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
|
||||||
|
{
|
||||||
|
return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right)
|
||||||
|
{
|
||||||
|
bool fractional = _left.denominator() != 1 || _right.denominator() != 1;
|
||||||
|
switch (_operator)
|
||||||
|
{
|
||||||
|
//bit operations will only be enabled for integers and fixed types that resemble integers
|
||||||
|
case Token::BitOr:
|
||||||
|
if (fractional)
|
||||||
|
return nullopt;
|
||||||
|
else
|
||||||
|
return _left.numerator() | _right.numerator();
|
||||||
|
case Token::BitXor:
|
||||||
|
if (fractional)
|
||||||
|
return nullopt;
|
||||||
|
else
|
||||||
|
return _left.numerator() ^ _right.numerator();
|
||||||
|
case Token::BitAnd:
|
||||||
|
if (fractional)
|
||||||
|
return nullopt;
|
||||||
|
else
|
||||||
|
return _left.numerator() & _right.numerator();
|
||||||
|
case Token::Add: return _left + _right;
|
||||||
|
case Token::Sub: return _left - _right;
|
||||||
|
case Token::Mul: return _left * _right;
|
||||||
|
case Token::Div:
|
||||||
|
if (_right == rational(0))
|
||||||
|
return nullopt;
|
||||||
|
else
|
||||||
|
return _left / _right;
|
||||||
|
case Token::Mod:
|
||||||
|
if (_right == rational(0))
|
||||||
|
return nullopt;
|
||||||
|
else if (fractional)
|
||||||
|
{
|
||||||
|
rational tempValue = _left / _right;
|
||||||
|
return _left - (tempValue.numerator() / tempValue.denominator()) * _right;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return _left.numerator() % _right.numerator();
|
||||||
|
break;
|
||||||
|
case Token::Exp:
|
||||||
|
{
|
||||||
|
if (_right.denominator() != 1)
|
||||||
|
return nullopt;
|
||||||
|
bigint const& exp = _right.numerator();
|
||||||
|
|
||||||
|
// x ** 0 = 1
|
||||||
|
// for 0, 1 and -1 the size of the exponent doesn't have to be restricted
|
||||||
|
if (exp == 0)
|
||||||
|
return 1;
|
||||||
|
else if (_left == 0 || _left == 1)
|
||||||
|
return _left;
|
||||||
|
else if (_left == -1)
|
||||||
|
{
|
||||||
|
bigint isOdd = abs(exp) & bigint(1);
|
||||||
|
return 1 - 2 * isOdd.convert_to<int>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (abs(exp) > numeric_limits<uint32_t>::max())
|
||||||
|
return nullopt; // This will need too much memory to represent.
|
||||||
|
|
||||||
|
uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>();
|
||||||
|
|
||||||
|
if (!fitsPrecisionExp(abs(_left.numerator()), absExp) || !fitsPrecisionExp(abs(_left.denominator()), absExp))
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint {
|
||||||
|
if (_base == 1)
|
||||||
|
return 1;
|
||||||
|
else if (_base == -1)
|
||||||
|
return 1 - 2 * static_cast<int>(_exponent & 1);
|
||||||
|
else
|
||||||
|
return boost::multiprecision::pow(_base, _exponent);
|
||||||
|
};
|
||||||
|
|
||||||
|
bigint numerator = optimizedPow(_left.numerator(), absExp);
|
||||||
|
bigint denominator = optimizedPow(_left.denominator(), absExp);
|
||||||
|
|
||||||
|
if (exp >= 0)
|
||||||
|
return makeRational(numerator, denominator);
|
||||||
|
else
|
||||||
|
// invert
|
||||||
|
return makeRational(denominator, numerator);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Token::SHL:
|
||||||
|
{
|
||||||
|
if (fractional)
|
||||||
|
return nullopt;
|
||||||
|
else if (_right < 0)
|
||||||
|
return nullopt;
|
||||||
|
else if (_right > numeric_limits<uint32_t>::max())
|
||||||
|
return nullopt;
|
||||||
|
if (_left.numerator() == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t exponent = _right.numerator().convert_to<uint32_t>();
|
||||||
|
if (!fitsPrecisionBase2(abs(_left.numerator()), exponent))
|
||||||
|
return nullopt;
|
||||||
|
return _left.numerator() * boost::multiprecision::pow(bigint(2), exponent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// NOTE: we're using >> (SAR) to denote right shifting. The type of the LValue
|
||||||
|
// determines the resulting type and the type of shift (SAR or SHR).
|
||||||
|
case Token::SAR:
|
||||||
|
{
|
||||||
|
if (fractional)
|
||||||
|
return nullopt;
|
||||||
|
else if (_right < 0)
|
||||||
|
return nullopt;
|
||||||
|
else if (_right > numeric_limits<uint32_t>::max())
|
||||||
|
return nullopt;
|
||||||
|
if (_left.numerator() == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t exponent = _right.numerator().convert_to<uint32_t>();
|
||||||
|
if (exponent > boost::multiprecision::msb(boost::multiprecision::abs(_left.numerator())))
|
||||||
|
return _left.numerator() < 0 ? -1 : 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_left.numerator() < 0)
|
||||||
|
// Add 1 to the negative value before dividing to get a result that is strictly too large,
|
||||||
|
// then subtract 1 afterwards to round towards negative infinity.
|
||||||
|
// This is the same algorithm as used in ExpressionCompiler::appendShiftOperatorCode(...).
|
||||||
|
// To see this note that for negative x, xor(x,all_ones) = (-x-1) and
|
||||||
|
// therefore xor(div(xor(x,all_ones), exp(2, shift_amount)), all_ones) is
|
||||||
|
// -(-x - 1) / 2^shift_amount - 1, which is the same as
|
||||||
|
// (x + 1) / 2^shift_amount - 1.
|
||||||
|
return rational((_left.numerator() + 1) / boost::multiprecision::pow(bigint(2), exponent) - bigint(1), 1);
|
||||||
|
else
|
||||||
|
return rational(_left.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator, rational const& _input)
|
||||||
|
{
|
||||||
|
switch (_operator)
|
||||||
|
{
|
||||||
|
case Token::BitNot:
|
||||||
|
if (_input.denominator() != 1)
|
||||||
|
return nullopt;
|
||||||
|
else
|
||||||
|
return ~_input.numerator();
|
||||||
|
case Token::Add:
|
||||||
|
return +_input;
|
||||||
|
case Token::Sub:
|
||||||
|
return -_input;
|
||||||
|
default:
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||||
{
|
{
|
||||||
auto sub = type(_operation.subExpression());
|
auto sub = type(_operation.subExpression());
|
||||||
|
@ -56,6 +56,14 @@ public:
|
|||||||
|
|
||||||
TypePointer evaluate(Expression const& _expr);
|
TypePointer evaluate(Expression const& _expr);
|
||||||
|
|
||||||
|
/// Performs arbitrary-precision evaluation of a binary operator. Returns nullopt on cases like
|
||||||
|
/// division by zero or e.g. bit operators applied to fractional values.
|
||||||
|
static std::optional<rational> evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right);
|
||||||
|
|
||||||
|
/// Performs arbitrary-precision evaluation of a unary operator. Returns nullopt on cases like
|
||||||
|
/// bit operators applied to fractional values.
|
||||||
|
static std::optional<rational> evaluateUnaryOperator(Token _operator, rational const& _input);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void endVisit(BinaryOperation const& _operation) override;
|
void endVisit(BinaryOperation const& _operation) override;
|
||||||
void endVisit(UnaryOperation const& _operation) override;
|
void endVisit(UnaryOperation const& _operation) override;
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include <libsolidity/ast/AST.h>
|
#include <libsolidity/ast/AST.h>
|
||||||
#include <libsolidity/ast/TypeProvider.h>
|
#include <libsolidity/ast/TypeProvider.h>
|
||||||
|
|
||||||
|
#include <libsolidity/analysis/ConstantEvaluator.h>
|
||||||
|
|
||||||
#include <libsolutil/Algorithms.h>
|
#include <libsolutil/Algorithms.h>
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
@ -56,50 +58,6 @@ using namespace solidity::frontend;
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Check whether (_base ** _exp) fits into 4096 bits.
|
|
||||||
bool fitsPrecisionExp(bigint const& _base, bigint const& _exp)
|
|
||||||
{
|
|
||||||
if (_base == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
solAssert(_base > 0, "");
|
|
||||||
|
|
||||||
size_t const bitsMax = 4096;
|
|
||||||
|
|
||||||
unsigned mostSignificantBaseBit = boost::multiprecision::msb(_base);
|
|
||||||
if (mostSignificantBaseBit == 0) // _base == 1
|
|
||||||
return true;
|
|
||||||
if (mostSignificantBaseBit > bitsMax) // _base >= 2 ^ 4096
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bigint bitsNeeded = _exp * (mostSignificantBaseBit + 1);
|
|
||||||
|
|
||||||
return bitsNeeded <= bitsMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether _mantissa * (X ** _exp) fits into 4096 bits,
|
|
||||||
/// where X is given indirectly via _log2OfBase = log2(X).
|
|
||||||
bool fitsPrecisionBaseX(
|
|
||||||
bigint const& _mantissa,
|
|
||||||
double _log2OfBase,
|
|
||||||
uint32_t _exp
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (_mantissa == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
solAssert(_mantissa > 0, "");
|
|
||||||
|
|
||||||
size_t const bitsMax = 4096;
|
|
||||||
|
|
||||||
unsigned mostSignificantMantissaBit = boost::multiprecision::msb(_mantissa);
|
|
||||||
if (mostSignificantMantissaBit > bitsMax) // _mantissa >= 2 ^ 4096
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bigint bitsNeeded = mostSignificantMantissaBit + bigint(floor(double(_exp) * _log2OfBase)) + 1;
|
|
||||||
return bitsNeeded <= bitsMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether _mantissa * (10 ** _expBase10) fits into 4096 bits.
|
/// Checks whether _mantissa * (10 ** _expBase10) fits into 4096 bits.
|
||||||
bool fitsPrecisionBase10(bigint const& _mantissa, uint32_t _expBase10)
|
bool fitsPrecisionBase10(bigint const& _mantissa, uint32_t _expBase10)
|
||||||
{
|
{
|
||||||
@ -107,12 +65,6 @@ bool fitsPrecisionBase10(bigint const& _mantissa, uint32_t _expBase10)
|
|||||||
return fitsPrecisionBaseX(_mantissa, log2Of10AwayFromZero, _expBase10);
|
return fitsPrecisionBaseX(_mantissa, log2Of10AwayFromZero, _expBase10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether _mantissa * (2 ** _expBase10) fits into 4096 bits.
|
|
||||||
bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
|
|
||||||
{
|
|
||||||
return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether _value fits into IntegerType _type.
|
/// Checks whether _value fits into IntegerType _type.
|
||||||
BoolResult fitsIntegerType(bigint const& _value, IntegerType const& _type)
|
BoolResult fitsIntegerType(bigint const& _value, IntegerType const& _type)
|
||||||
{
|
{
|
||||||
@ -1000,26 +952,10 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
|
|||||||
|
|
||||||
TypeResult RationalNumberType::unaryOperatorResult(Token _operator) const
|
TypeResult RationalNumberType::unaryOperatorResult(Token _operator) const
|
||||||
{
|
{
|
||||||
rational value;
|
if (optional<rational> value = ConstantEvaluator::evaluateUnaryOperator(_operator, m_value))
|
||||||
switch (_operator)
|
return TypeResult{TypeProvider::rationalNumber(*value)};
|
||||||
{
|
else
|
||||||
case Token::BitNot:
|
|
||||||
if (isFractional())
|
|
||||||
return nullptr;
|
|
||||||
value = ~m_value.numerator();
|
|
||||||
break;
|
|
||||||
case Token::Add:
|
|
||||||
value = +(m_value);
|
|
||||||
break;
|
|
||||||
case Token::Sub:
|
|
||||||
value = -(m_value);
|
|
||||||
break;
|
|
||||||
case Token::After:
|
|
||||||
return this;
|
|
||||||
default:
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
return TypeResult{TypeProvider::rationalNumber(value)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const* _other) const
|
TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const* _other) const
|
||||||
@ -1074,165 +1010,16 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
return thisMobile->binaryOperatorResult(_operator, otherMobile);
|
return thisMobile->binaryOperatorResult(_operator, otherMobile);
|
||||||
}
|
}
|
||||||
else
|
else if (optional<rational> value = ConstantEvaluator::evaluateBinaryOperator(_operator, m_value, other.m_value))
|
||||||
{
|
{
|
||||||
rational value;
|
|
||||||
bool fractional = isFractional() || other.isFractional();
|
|
||||||
switch (_operator)
|
|
||||||
{
|
|
||||||
//bit operations will only be enabled for integers and fixed types that resemble integers
|
|
||||||
case Token::BitOr:
|
|
||||||
if (fractional)
|
|
||||||
return nullptr;
|
|
||||||
value = m_value.numerator() | other.m_value.numerator();
|
|
||||||
break;
|
|
||||||
case Token::BitXor:
|
|
||||||
if (fractional)
|
|
||||||
return nullptr;
|
|
||||||
value = m_value.numerator() ^ other.m_value.numerator();
|
|
||||||
break;
|
|
||||||
case Token::BitAnd:
|
|
||||||
if (fractional)
|
|
||||||
return nullptr;
|
|
||||||
value = m_value.numerator() & other.m_value.numerator();
|
|
||||||
break;
|
|
||||||
case Token::Add:
|
|
||||||
value = m_value + other.m_value;
|
|
||||||
break;
|
|
||||||
case Token::Sub:
|
|
||||||
value = m_value - other.m_value;
|
|
||||||
break;
|
|
||||||
case Token::Mul:
|
|
||||||
value = m_value * other.m_value;
|
|
||||||
break;
|
|
||||||
case Token::Div:
|
|
||||||
if (other.m_value == rational(0))
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
value = m_value / other.m_value;
|
|
||||||
break;
|
|
||||||
case Token::Mod:
|
|
||||||
if (other.m_value == rational(0))
|
|
||||||
return nullptr;
|
|
||||||
else if (fractional)
|
|
||||||
{
|
|
||||||
rational tempValue = m_value / other.m_value;
|
|
||||||
value = m_value - (tempValue.numerator() / tempValue.denominator()) * other.m_value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
value = m_value.numerator() % other.m_value.numerator();
|
|
||||||
break;
|
|
||||||
case Token::Exp:
|
|
||||||
{
|
|
||||||
if (other.isFractional())
|
|
||||||
return nullptr;
|
|
||||||
solAssert(other.m_value.denominator() == 1, "");
|
|
||||||
bigint const& exp = other.m_value.numerator();
|
|
||||||
|
|
||||||
// x ** 0 = 1
|
|
||||||
// for 0, 1 and -1 the size of the exponent doesn't have to be restricted
|
|
||||||
if (exp == 0)
|
|
||||||
value = 1;
|
|
||||||
else if (m_value.numerator() == 0 || m_value == 1)
|
|
||||||
value = m_value;
|
|
||||||
else if (m_value == -1)
|
|
||||||
{
|
|
||||||
bigint isOdd = abs(exp) & bigint(1);
|
|
||||||
value = 1 - 2 * isOdd.convert_to<int>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (abs(exp) > numeric_limits<uint32_t>::max())
|
|
||||||
return nullptr; // This will need too much memory to represent.
|
|
||||||
|
|
||||||
uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>();
|
|
||||||
|
|
||||||
if (!fitsPrecisionExp(abs(m_value.numerator()), absExp) || !fitsPrecisionExp(abs(m_value.denominator()), absExp))
|
|
||||||
return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
|
|
||||||
|
|
||||||
static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint {
|
|
||||||
if (_base == 1)
|
|
||||||
return 1;
|
|
||||||
else if (_base == -1)
|
|
||||||
return 1 - 2 * static_cast<int>(_exponent & 1);
|
|
||||||
else
|
|
||||||
return boost::multiprecision::pow(_base, _exponent);
|
|
||||||
};
|
|
||||||
|
|
||||||
bigint numerator = optimizedPow(m_value.numerator(), absExp);
|
|
||||||
bigint denominator = optimizedPow(m_value.denominator(), absExp);
|
|
||||||
|
|
||||||
if (exp >= 0)
|
|
||||||
value = makeRational(numerator, denominator);
|
|
||||||
else
|
|
||||||
// invert
|
|
||||||
value = makeRational(denominator, numerator);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::SHL:
|
|
||||||
{
|
|
||||||
if (fractional)
|
|
||||||
return nullptr;
|
|
||||||
else if (other.m_value < 0)
|
|
||||||
return nullptr;
|
|
||||||
else if (other.m_value > numeric_limits<uint32_t>::max())
|
|
||||||
return nullptr;
|
|
||||||
if (m_value.numerator() == 0)
|
|
||||||
value = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>();
|
|
||||||
if (!fitsPrecisionBase2(abs(m_value.numerator()), exponent))
|
|
||||||
return nullptr;
|
|
||||||
value = m_value.numerator() * boost::multiprecision::pow(bigint(2), exponent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// NOTE: we're using >> (SAR) to denote right shifting. The type of the LValue
|
|
||||||
// determines the resulting type and the type of shift (SAR or SHR).
|
|
||||||
case Token::SAR:
|
|
||||||
{
|
|
||||||
if (fractional)
|
|
||||||
return nullptr;
|
|
||||||
else if (other.m_value < 0)
|
|
||||||
return nullptr;
|
|
||||||
else if (other.m_value > numeric_limits<uint32_t>::max())
|
|
||||||
return nullptr;
|
|
||||||
if (m_value.numerator() == 0)
|
|
||||||
value = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>();
|
|
||||||
if (exponent > boost::multiprecision::msb(boost::multiprecision::abs(m_value.numerator())))
|
|
||||||
value = m_value.numerator() < 0 ? -1 : 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_value.numerator() < 0)
|
|
||||||
// Add 1 to the negative value before dividing to get a result that is strictly too large,
|
|
||||||
// then subtract 1 afterwards to round towards negative infinity.
|
|
||||||
// This is the same algorithm as used in ExpressionCompiler::appendShiftOperatorCode(...).
|
|
||||||
// To see this note that for negative x, xor(x,all_ones) = (-x-1) and
|
|
||||||
// therefore xor(div(xor(x,all_ones), exp(2, shift_amount)), all_ones) is
|
|
||||||
// -(-x - 1) / 2^shift_amount - 1, which is the same as
|
|
||||||
// (x + 1) / 2^shift_amount - 1.
|
|
||||||
value = rational((m_value.numerator() + 1) / boost::multiprecision::pow(bigint(2), exponent) - bigint(1), 1);
|
|
||||||
else
|
|
||||||
value = rational(m_value.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify that numerator and denominator fit into 4096 bit after every operation
|
// verify that numerator and denominator fit into 4096 bit after every operation
|
||||||
if (value.numerator() != 0 && max(boost::multiprecision::msb(abs(value.numerator())), boost::multiprecision::msb(abs(value.denominator()))) > 4096)
|
if (value->numerator() != 0 && max(boost::multiprecision::msb(abs(value->numerator())), boost::multiprecision::msb(abs(value->denominator()))) > 4096)
|
||||||
return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
|
return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
|
||||||
|
|
||||||
return TypeResult{TypeProvider::rationalNumber(value)};
|
return TypeResult{TypeProvider::rationalNumber(*value)};
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string RationalNumberType::richIdentifier() const
|
string RationalNumberType::richIdentifier() const
|
||||||
|
@ -3,6 +3,7 @@ set(sources
|
|||||||
AnsiColorized.h
|
AnsiColorized.h
|
||||||
Assertions.h
|
Assertions.h
|
||||||
Common.h
|
Common.h
|
||||||
|
Common.cpp
|
||||||
CommonData.cpp
|
CommonData.cpp
|
||||||
CommonData.h
|
CommonData.h
|
||||||
CommonIO.cpp
|
CommonIO.cpp
|
||||||
|
40
libsolutil/Common.cpp
Normal file
40
libsolutil/Common.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <libsolutil/Common.h>
|
||||||
|
|
||||||
|
#include <liblangutil/Exceptions.h>
|
||||||
|
|
||||||
|
using namespace solidity;
|
||||||
|
|
||||||
|
bool solidity::fitsPrecisionBaseX(bigint const& _mantissa, double _log2OfBase, uint32_t _exp)
|
||||||
|
{
|
||||||
|
if (_mantissa == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
solAssert(_mantissa > 0, "");
|
||||||
|
|
||||||
|
size_t const bitsMax = 4096;
|
||||||
|
|
||||||
|
unsigned mostSignificantMantissaBit = boost::multiprecision::msb(_mantissa);
|
||||||
|
if (mostSignificantMantissaBit > bitsMax) // _mantissa >= 2 ^ 4096
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bigint bitsNeeded = mostSignificantMantissaBit + bigint(floor(double(_exp) * _log2OfBase)) + 1;
|
||||||
|
return bitsNeeded <= bitsMax;
|
||||||
|
}
|
@ -107,6 +107,10 @@ inline u256 exp256(u256 _base, u256 _exponent)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether _mantissa * (X ** _exp) fits into 4096 bits,
|
||||||
|
/// where X is given indirectly via _log2OfBase = log2(X).
|
||||||
|
bool fitsPrecisionBaseX(bigint const& _mantissa, double _log2OfBase, uint32_t _exp);
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, bytes const& _bytes)
|
inline std::ostream& operator<<(std::ostream& os, bytes const& _bytes)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
|
@ -19,7 +19,7 @@ contract c {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError 2271: (71-112): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits.
|
// TypeError 2271: (71-112): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4
|
||||||
// TypeError 7407: (71-112): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (71-112): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
// TypeError 2271: (135-151): Operator ** not compatible with types int_const 4 and int_const 1157...(70 digits omitted)...9936
|
// TypeError 2271: (135-151): Operator ** not compatible with types int_const 4 and int_const 1157...(70 digits omitted)...9936
|
||||||
// TypeError 7407: (126-169): Type int_const 1340...(147 digits omitted)...4096 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (126-169): Type int_const 1340...(147 digits omitted)...4096 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
@ -29,13 +29,13 @@ contract c {
|
|||||||
// TypeError 2271: (258-270): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000
|
// TypeError 2271: (258-270): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000
|
||||||
// TypeError 2271: (284-296): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000
|
// TypeError 2271: (284-296): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000
|
||||||
// TypeError 2271: (310-323): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000
|
// TypeError 2271: (310-323): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000
|
||||||
// TypeError 2271: (337-348): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits.
|
// TypeError 2271: (337-348): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2
|
||||||
// TypeError 7407: (337-348): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (337-348): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
// TypeError 2271: (362-374): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits.
|
// TypeError 2271: (362-374): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2
|
||||||
// TypeError 7407: (362-374): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (362-374): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
// TypeError 2271: (388-400): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits.
|
// TypeError 2271: (388-400): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2
|
||||||
// TypeError 7407: (388-400): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (388-400): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
// TypeError 2271: (414-427): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits.
|
// TypeError 2271: (414-427): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2
|
||||||
// TypeError 7407: (414-427): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (414-427): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
// TypeError 2271: (441-457): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000
|
// TypeError 2271: (441-457): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000
|
||||||
// TypeError 7407: (441-457): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
// TypeError 7407: (441-457): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.
|
||||||
|
Loading…
Reference in New Issue
Block a user