#include "src/storage/expressions/ToRationalNumberVisitor.h" #include "src/utility/macros.h" #include "src/utility/constants.h" #include "src/exceptions/InvalidArgumentException.h" #include "src/exceptions/NotSupportedException.h" namespace storm { namespace expressions { template ToRationalNumberVisitor::ToRationalNumberVisitor() : ExpressionVisitor() { // Intentionally left empty. } template RationalNumberType ToRationalNumberVisitor::toRationalNumber(Expression const& expression) { return boost::any_cast(expression.accept(*this, boost::none)); } template boost::any ToRationalNumberVisitor::visit(IfThenElseExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) { RationalNumberType firstOperandAsRationalNumber = boost::any_cast(expression.getFirstOperand()->accept(*this, data)); RationalNumberType secondOperandAsRationalNumber = boost::any_cast(expression.getSecondOperand()->accept(*this, data)); switch(expression.getOperatorType()) { case BinaryNumericalFunctionExpression::OperatorType::Plus: return firstOperandAsRationalNumber + secondOperandAsRationalNumber; break; case BinaryNumericalFunctionExpression::OperatorType::Minus: return firstOperandAsRationalNumber - secondOperandAsRationalNumber; break; case BinaryNumericalFunctionExpression::OperatorType::Times: return firstOperandAsRationalNumber * secondOperandAsRationalNumber; break; case BinaryNumericalFunctionExpression::OperatorType::Divide: return firstOperandAsRationalNumber / secondOperandAsRationalNumber; break; case BinaryNumericalFunctionExpression::OperatorType::Min: return std::min(firstOperandAsRationalNumber, secondOperandAsRationalNumber); break; case BinaryNumericalFunctionExpression::OperatorType::Max: return std::max(firstOperandAsRationalNumber, secondOperandAsRationalNumber); break; case BinaryNumericalFunctionExpression::OperatorType::Power: STORM_LOG_THROW(storm::utility::isInteger(secondOperandAsRationalNumber), storm::exceptions::InvalidArgumentException, "Exponent of power operator must be a positive integer."); uint_fast64_t exponentAsInteger = storm::utility::convertNumber(secondOperandAsRationalNumber); return storm::utility::pow(firstOperandAsRationalNumber, exponentAsInteger); break; } // Return a dummy. This point must, however, never be reached. STORM_LOG_ASSERT(false, "Illegal operator type."); return boost::any(); } template boost::any ToRationalNumberVisitor::visit(BinaryRelationExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(VariableExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Cannot transform expressions containing variables to a rational number."); } template boost::any ToRationalNumberVisitor::visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(BooleanLiteralExpression const& expression, boost::any const& data) { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Expression cannot be translated into a rational number."); } template boost::any ToRationalNumberVisitor::visit(IntegerLiteralExpression const& expression, boost::any const& data) { #ifdef STORM_HAVE_CARL return RationalNumberType(carl::rationalize(static_cast(expression.getValue()))); #else STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Rational numbers are not supported in this build."); #endif } template boost::any ToRationalNumberVisitor::visit(RationalLiteralExpression const& expression, boost::any const& data) { #ifdef STORM_HAVE_CARL return expression.getValue(); #else STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Rational numbers are not supported in this build."); #endif } #ifdef STORM_HAVE_CARL template class ToRationalNumberVisitor; #endif } }