| ... | @@ -242,15 +242,24 @@ pub const Timer = struct { | ... | @@ -242,15 +242,24 @@ pub const Timer = struct { |
| 242 | | 242 | |
| 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 | }; |
| 253 | | 253 | |
| | 254 | // Calculate (a * b) / c without risk of overflowing too early because of the |
| | 255 | // multiplication. |
| | 256 | fn 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 | |
| 254 | test "sleep" { | 263 | test "sleep" { |
| 255 | sleep(1); | 264 | sleep(1); |
| 256 | } | 265 | } |