Keep in mind that most of the examples in the article use the float type in the context of game dev, which is typically single-precision floating-point IEEE754 (32-bit float). Swanstation uses double which is typically double-precision IEEE754 (64-bit float), so things are not as extreme as in the examples there.
The article also suggests using double as a possible fix, however, that isn't good enough for swanstation. For instance, it appears CLOCK_MONOTONIC is implemented as the time since boot at least on NetBSD and OpenBSD. I can't seem to find the relevant code on FreeBSD or Linux, but they should be similar. Considering every integer between -(2^53) and 2^53 can be stored without rounding in a 64-bit IEEE754 float, the time is acquired via CLOCK_MONOTONIC on Unix, and the unit is nanoseconds:
https://github.com/libretro/swanstation/blob/7a27436548128c00e70b08dde63c52118e2a6228/src/common/timer.cpp#L59-L60
It takes 2^53 / 1000000000 seconds or 104 days of uptime for any conversion of Common::Timer to double to lose precision to rounding.
The separate Windows and Unix code can be mostly unified too, only GetValue() needs to be different.
The timer API in swanstation correctly stores time as an integer: https://github.com/libretro/swanstation/blob/7a27436548128c00e70b08dde63c52118e2a6228/src/common/timer.h#L9 But then provides APIs to convert it to and from floating-point: https://github.com/libretro/swanstation/blob/7a27436548128c00e70b08dde63c52118e2a6228/src/common/timer.h#L14-L17 The floating-point API is used in the code, here's one example: https://github.com/libretro/swanstation/blob/7a27436548128c00e70b08dde63c52118e2a6228/src/core/gpu_backend.cpp#L213-L214
This article has a mostly good writeup on why storing time in floating-point is bad: https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/
Keep in mind that most of the examples in the article use the
float
type in the context of game dev, which is typically single-precision floating-point IEEE754 (32-bit float). Swanstation usesdouble
which is typically double-precision IEEE754 (64-bit float), so things are not as extreme as in the examples there.The article also suggests using
double
as a possible fix, however, that isn't good enough for swanstation. For instance, it appears CLOCK_MONOTONIC is implemented as the time since boot at least on NetBSD and OpenBSD. I can't seem to find the relevant code on FreeBSD or Linux, but they should be similar. Considering every integer between-(2^53)
and2^53
can be stored without rounding in a 64-bit IEEE754 float, the time is acquired via CLOCK_MONOTONIC on Unix, and the unit is nanoseconds: https://github.com/libretro/swanstation/blob/7a27436548128c00e70b08dde63c52118e2a6228/src/common/timer.cpp#L59-L60 It takes2^53 / 1000000000
seconds or 104 days of uptime for any conversion ofCommon::Timer
todouble
to lose precision to rounding.The separate Windows and Unix code can be mostly unified too, only
GetValue()
needs to be different.