Skip to content

Commit 83185ab

Browse files
committed
Add mult_frac() to handle fractional multiplication safely
Introduce a new inline function mult_frac() to compute "x * n / d" with enhanced precision and safety. This function addresses the common issues of overflow and loss of precision that can occur with straightforward approaches to this calculation. Directly computing "x * n / d" can lead to problems: - Performing the division first can result in loss of precision due to integer truncation. - Performing multiplication before division can risk overflow. The mult_frac() function mitigates these issues by: 1. Calculating the quotient and remainder of 'x' divided by 'd'. 2. Using these intermediate results to perform the final calculation, thus avoiding intermediate overflow and preserving precision. This approach is based on the Linux kernel's mult_frac() macro [1], which follows a similar method to handle these calculations robustly. Link: https://elixir.bootlin.com/linux/v6.10.7/source/include/linux/math.h#L121 [1]
1 parent 1023b4c commit 83185ab

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

utils.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@
1919
#endif
2020
#endif
2121

22+
/* Calculate "x * n / d" without unnecessary overflow or loss of precision.
23+
*
24+
* Reference:
25+
* https://elixir.bootlin.com/linux/v6.10.7/source/include/linux/math.h#L121
26+
*/
27+
static inline uint64_t mult_frac(uint64_t x, uint64_t n, uint64_t d)
28+
{
29+
const uint64_t q = x / d;
30+
const uint64_t r = x % d;
31+
32+
return q * n + r * n / d;
33+
}
34+
2235
void semu_timer_init(semu_timer_t *timer, uint64_t freq)
2336
{
2437
timer->freq = freq;

0 commit comments

Comments
 (0)