Skip to content

Instantly share code, notes, and snippets.

@jspohr
Last active September 1, 2024 21:55
Show Gist options
  • Save jspohr/3dc4f00033d79ec5bdaf67bc46c813e3 to your computer and use it in GitHub Desktop.
Save jspohr/3dc4f00033d79ec5bdaf67bc46c813e3 to your computer and use it in GitHub Desktop.
Avoid overflow when converting time to microseconds
// Taken from the Rust code base: https://github.com/rust-lang/rust/blob/3809bbf47c8557bd149b3e52ceb47434ca8378d5/src/libstd/sys_common/mod.rs#L124
// Computes (value*numer)/denom without overflow, as long as both
// (numer*denom) and the overall result fit into i64 (which is the case
// for our time conversions).
int64_t int64MulDiv(int64_t value, int64_t numer, int64_t denom) {
int64_t q = value / denom;
int64_t r = value % denom;
// Decompose value as (value/denom*denom + value%denom),
// substitute into (value*numer)/denom and simplify.
// r < denom, so (denom*numer) is the upper bound of (r*numer)
return q * numer + r * numer / denom;
}
int64_t timeInMicros() {
// Get time and frequency
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
// Convert to microseconds
const int64_t microsPerSecond = 1000000LL;
int64_t micros = int64MulDiv(time.QuadPart, microsPerSecond, frequency.QuadPart);
return micros;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment