authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-30 19:30:02+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-01 17:06:14-05:00
log445d808bae4b9a2ff1c7a56a4ebff64ae848f46c
tree62ad307aaf5772c2066aed44a3bfe54f479afbb7
parent2e1cef75086a0b606fd8f1f7a0cda4ab2f0b7a49

std: Fix early overflow in time calculation

Closes #6867

1 files changed, 11 insertions(+), 2 deletions(-)

lib/std/time.zig+11-2
...@@ -242,15 +242,24 @@ pub const Timer = struct {...@@ -242,15 +242,24 @@ pub const Timer = struct {
242242
243 fn nativeDurationToNanos(self: Timer, duration: u64) u64 {243 fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
244 if (is_windows) {244 if (is_windows) {
245 return @divFloor(duration * ns_per_s, self.frequency);245 return safeMulDiv(duration, ns_per_s, self.frequency);
246 }246 }
247 if (comptime std.Target.current.isDarwin()) {247 if (comptime std.Target.current.isDarwin()) {
248 return @divFloor(duration * self.frequency.numer, self.frequency.denom);248 return safeMulDiv(duration, self.frequency.numer, self.frequency.denom);
249 }249 }
250 return duration;250 return duration;
251 }251 }
252};252};
253253
254// Calculate (a * b) / c without risk of overflowing too early because of the
255// multiplication.
256fn safeMulDiv(a: u64, b: u64, c: u64) u64 {
257 const q = a / c;
258 const r = a % c;
259 // (a * b) / c == (a / c) * b + ((a % c) * b) / c
260 return (q * b) + (r * b) / c;
261}
262
254test "sleep" {263test "sleep" {
255 sleep(1);264 sleep(1);
256}265}