Allow explicit conversion from rational to fixed if it fits value range.

This commit is contained in:
chriseth 2021-07-28 11:30:10 +02:00
parent 1e816332f3
commit 28e8f5571b
2 changed files with 34 additions and 6 deletions

View File

@ -756,19 +756,31 @@ string FixedPointType::toString(bool) const
bigint FixedPointType::maxIntegerValue() const bigint FixedPointType::maxIntegerValue() const
{ {
bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1; rational max = maxValue();
return maxValue / boost::multiprecision::pow(bigint(10), m_fractionalDigits); return max.numerator() / max.denominator();
} }
bigint FixedPointType::minIntegerValue() const bigint FixedPointType::minIntegerValue() const
{
rational min = minValue();
return min.numerator() / min.denominator();
}
rational FixedPointType::maxValue() const
{
bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1;
return rational(maxValue) / boost::multiprecision::pow(bigint(10), m_fractionalDigits);
}
rational FixedPointType::minValue() const
{ {
if (isSigned()) if (isSigned())
{ {
bigint minValue = -(bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))); bigint minValue = -(bigint(1) << (m_totalBits - 1));
return minValue / boost::multiprecision::pow(bigint(10), m_fractionalDigits); return rational(minValue) / boost::multiprecision::pow(bigint(10), m_fractionalDigits);
} }
else else
return bigint(0); return rational{0};
} }
TypeResult FixedPointType::binaryOperatorResult(Token _operator, Type const* _other) const TypeResult FixedPointType::binaryOperatorResult(Token _operator, Type const* _other) const
@ -985,11 +997,24 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
else if (category == Category::Integer) else if (category == Category::Integer)
return false; return false;
else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo)) else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo))
{
if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers()) if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers())
return false; return false;
}
else if (auto fixedPointType = dynamic_cast<FixedPointType const*>(&_convertTo))
{
if (value() < fixedPointType->minValue())
return BoolResult::err("Value is too small.");
else if (value() > fixedPointType->maxValue())
return BoolResult::err("Value is too large.");
else
return true;
}
Type const* mobType = mobileType(); Type const* mobType = mobileType();
return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)); if (!mobType)
return false;
return mobType->isExplicitlyConvertibleTo(_convertTo);
} }

View File

@ -529,6 +529,9 @@ public:
/// smallest value in general. /// smallest value in general.
bigint minIntegerValue() const; bigint minIntegerValue() const;
rational maxValue() const;
rational minValue() const;
/// @returns the smallest integer type that can hold this type with fractional parts shifted to integers. /// @returns the smallest integer type that can hold this type with fractional parts shifted to integers.
IntegerType const* asIntegerType() const; IntegerType const* asIntegerType() const;