commit 445d808bae4b9a2ff1c7a56a4ebff64ae848f46c (tree)
parent 2e1cef75086a0b606fd8f1f7a0cda4ab2f0b7a49
Author: LemonBoy <thatlemon@gmail.com>
Date: Fri, 30 Oct 2020 19:30:02 +0100
std: Fix early overflow in time calculation
Closes #6867
Diffstat:
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/lib/std/time.zig b/lib/std/time.zig
@@ -242,15 +242,24 @@ pub const Timer = struct {
fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
if (is_windows) {
- return @divFloor(duration * ns_per_s, self.frequency);
+ return safeMulDiv(duration, ns_per_s, self.frequency);
}
if (comptime std.Target.current.isDarwin()) {
- return @divFloor(duration * self.frequency.numer, self.frequency.denom);
+ return safeMulDiv(duration, self.frequency.numer, self.frequency.denom);
}
return duration;
}
};
+// Calculate (a * b) / c without risk of overflowing too early because of the
+// multiplication.
+fn safeMulDiv(a: u64, b: u64, c: u64) u64 {
+ const q = a / c;
+ const r = a % c;
+ // (a * b) / c == (a / c) * b + ((a % c) * b) / c
+ return (q * b) + (r * b) / c;
+}
+
test "sleep" {
sleep(1);
}