From f17758e7f9de050317d651bb2069b92103f0639c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 20 Dec 2017 21:03:24 -0500 Subject: [PATCH] Attempts better to deal with large numbers. --- Storage/TimedEventLoop.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Storage/TimedEventLoop.cpp b/Storage/TimedEventLoop.cpp index 2e187197a..bd9bea643 100644 --- a/Storage/TimedEventLoop.cpp +++ b/Storage/TimedEventLoop.cpp @@ -65,18 +65,29 @@ void TimedEventLoop::jump_to_next_event() { void TimedEventLoop::set_next_event_time_interval(Time interval) { // Calculate [interval]*[input clock rate] + [subcycles until this event]. - int64_t denominator = (int64_t)interval.clock_rate * (int64_t)subcycles_until_event_.clock_rate; + int64_t denominator = static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.clock_rate); int64_t numerator = - (int64_t)subcycles_until_event_.clock_rate * (int64_t)input_clock_rate_ * (int64_t)interval.length + - (int64_t)interval.clock_rate * (int64_t)subcycles_until_event_.length; + static_cast(subcycles_until_event_.clock_rate) * static_cast(input_clock_rate_) * static_cast(interval.length) + + static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.length); - // Simplify if necessary. - if(denominator > std::numeric_limits::max()) { + // Simplify if necessary: try just simplifying the interval and recalculating; if that doesn't + // work then try simplifying the whole thing. + if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { + interval.simplify(); + denominator = static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.clock_rate); + numerator = + static_cast(subcycles_until_event_.clock_rate) * static_cast(input_clock_rate_) * static_cast(interval.length) + + static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.length); + } + + if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { int64_t common_divisor = NumberTheory::greatest_common_divisor(numerator % denominator, denominator); denominator /= common_divisor; numerator /= common_divisor; } + // TODO: if that doesn't work then reduce precision. + // So this event will fire in the integral number of cycles from now, putting us at the remainder // number of subcycles assert(cycles_until_event_ == 0);