You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
4.1 KiB
68 lines
4.1 KiB
#pragma once
|
|
|
|
#include "storm/utility/constants.h"
|
|
#include "storm/utility/macros.h"
|
|
|
|
#include "storm/exceptions/PrecisionExceededException.h"
|
|
|
|
namespace storm {
|
|
namespace utility{
|
|
namespace kwek_mehlhorn {
|
|
|
|
template<typename IntegerType>
|
|
std::pair<IntegerType, IntegerType> findRational(IntegerType const& alpha, IntegerType const& beta, IntegerType const& gamma, IntegerType const& delta) {
|
|
IntegerType alphaDivBetaFloor = alpha / beta;
|
|
IntegerType gammaDivDeltaFloor = gamma / delta;
|
|
IntegerType alphaModBeta = storm::utility::mod(alpha, beta);
|
|
|
|
if (alphaDivBetaFloor == gammaDivDeltaFloor && !storm::utility::isZero(alphaModBeta)) {
|
|
std::pair<IntegerType, IntegerType> subresult = findRational(delta, storm::utility::mod(gamma, delta), beta, alphaModBeta);
|
|
auto result = std::make_pair(alphaDivBetaFloor * subresult.first + subresult.second, subresult.first);
|
|
|
|
return result;
|
|
} else {
|
|
auto result = std::make_pair(storm::utility::isZero(alphaModBeta) ? alphaDivBetaFloor : alphaDivBetaFloor + storm::utility::one<IntegerType>(), storm::utility::one<IntegerType>());
|
|
return result;
|
|
}
|
|
}
|
|
|
|
template<typename RationalType, typename ImpreciseType>
|
|
std::pair<typename NumberTraits<RationalType>::IntegerType, typename NumberTraits<RationalType>::IntegerType> truncateToRational(ImpreciseType const& value, uint64_t precision) {
|
|
typedef typename NumberTraits<RationalType>::IntegerType IntegerType;
|
|
|
|
IntegerType powerOfTen = storm::utility::pow(storm::utility::convertNumber<IntegerType>(10ull), precision);
|
|
IntegerType truncated = storm::utility::trunc<RationalType>(value * powerOfTen);
|
|
return std::make_pair(truncated, powerOfTen);
|
|
}
|
|
|
|
template<typename RationalType>
|
|
std::pair<typename NumberTraits<RationalType>::IntegerType, typename NumberTraits<RationalType>::IntegerType> truncateToRational(double const& value, uint64_t precision) {
|
|
STORM_LOG_THROW(precision < 17, storm::exceptions::PrecisionExceededException, "Exceeded precision of double, consider switching to rational numbers.");
|
|
double powerOfTen = std::pow(10, precision);
|
|
double truncated = storm::utility::trunc<double>(value * powerOfTen);
|
|
return std::make_pair(truncated, powerOfTen);
|
|
}
|
|
|
|
template<typename RationalType, typename ImpreciseType>
|
|
RationalType findRational(uint64_t precision, ImpreciseType const& value) {
|
|
typedef typename NumberTraits<RationalType>::IntegerType IntegerType;
|
|
|
|
std::pair<IntegerType, IntegerType> truncatedFraction = truncateToRational<RationalType>(value, precision);
|
|
std::pair<IntegerType, IntegerType> result = findRational<IntegerType>(truncatedFraction.first, truncatedFraction.second, truncatedFraction.first + storm::utility::one<IntegerType>(), truncatedFraction.second);
|
|
|
|
// Convert one of the arguments to a rational type to not get integer division.
|
|
return storm::utility::convertNumber<RationalType>(result.first) / result.second;
|
|
}
|
|
|
|
template<typename RationalType, typename ImpreciseType>
|
|
void sharpen(uint64_t precision, std::vector<ImpreciseType> const& input, std::vector<RationalType>& output) {
|
|
for (uint64_t index = 0; index < input.size(); ++index) {
|
|
ImpreciseType integer = storm::utility::floor(input[index]);
|
|
ImpreciseType fraction = input[index] - integer;
|
|
output[index] = storm::utility::convertNumber<RationalType>(integer) + findRational<RationalType>(precision, fraction);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|