commit 636e38fcc17ca0730c0a177e700e0b9484e3acb9
parent 1a581c10dd613dbe4b312c34e81dbb46f79d5e69
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 2 Aug 2026 22:12:21 +0200
faster path if int128 is available, not high-bit limit and warn if it is hit
Diffstat:
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/util/amount_quantity.c b/src/util/amount_quantity.c
@@ -109,6 +109,20 @@ div128_64 (uint64_t n_hi,
{
uint64_t remainder;
+#if defined(__SIZEOF_INT128__)
+ {
+ /* Use native 128-bit division where the compiler supports it.
+ This also avoids the overflow of the bit-by-bit fallback below
+ when d > 2^63 (there 'remainder <<= 1' would drop the top bit). */
+ __uint128_t n = (((__uint128_t) n_hi) << 64) | (__uint128_t) n_lo;
+
+ *q_hi = (uint64_t) ((n / d) >> 64);
+ *q_lo = (uint64_t) (n / d);
+ *r = (uint64_t) (n % d);
+ return;
+ }
+#endif
+
if (0 == n_hi)
{
*q_hi = 0;
@@ -116,12 +130,13 @@ div128_64 (uint64_t n_hi,
*r = n_lo % d;
return;
}
-
+ GNUNET_break (d < INT64_MAX); /* theoretical algo limit... */
/* Note: very slow method, could be done faster, but
in practice we expect the above short-cut to apply
- in virtually all cases, so we keep it simple here;
- also, if it mattered, we should use __uint128_t on
- systems that support it. */
+ in virtually all cases, so we keep it simple here.
+ WARNING: this fallback is only correct for d <= 2^63;
+ for larger divisors 'remainder <<= 1' overflows. All
+ platforms with __uint128_t take the fast path above. */
remainder = 0;
*q_hi = 0;
*q_lo = 0;