Commit 445d808bae

LemonBoy <thatlemon@gmail.com>
2020-10-30 19:30:02
std: Fix early overflow in time calculation
Closes #6867
1 parent 2e1cef7
Changed files (1)
lib
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);
 }