cosmopolitan/third_party/compiler_rt/divmodti4.c

65 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to division, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "third_party/compiler_rt/int_lib.h"
/**
* Divides 128-bit signed integers w/ remainder.
*
* @param a is numerator
* @param b is denominator
* @param opt_out_rem receives euclidean division remainder if not null
* @return quotient or result of division
* @note rounds towards zero
*/
COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, tu_int *opt_out_rem) {
int k;
tu_int r;
ti_int sa, sb, sq, sr, x, y, q;
k = sizeof(ti_int) * CHAR_BIT - 1;
if (b == -1 && a == ((ti_int)1 << k)) {
volatile int x = 0;
x = 1 / x; // raise(SIGFPE)
}
sa = a >> k; // sa = a < 0 ? -1 : 0
sb = b >> k; // sb = b < 0 ? -1 : 0
x = (a ^ sa) - sa; // negate if sa == -1
y = (b ^ sb) - sb; // negate if sb == -1
sq = sa ^ sb; // sign of quotient
sr = sa; // sign of remainder
q = __udivmodti4(x, y, &r); // unsigned divide
q = (q ^ sq) - sq; // fix quotient sign
r = (r ^ sr) - sr; // fix remainder sign
if (opt_out_rem) *opt_out_rem = r;
return q;
}
/*
Intel Kabylake i9-9900 @ 3.10GHz Client Grade
idiv32 l: 27𝑐 9𝑛𝑠
idiv64 l: 27𝑐 9𝑛𝑠
divmodti4 small / small l: 42𝑐 14𝑛𝑠
divmodti4 small / large l: 14𝑐 5𝑛𝑠
divmodti4 large / small l: 92𝑐 30𝑛𝑠
divmodti4 large / large l: 209𝑐 68𝑛𝑠
Intel Kabylake i3-8100 @ 3.60GHz Client Grade
idiv32 l: 51𝑐 14𝑛𝑠
idiv64 l: 51𝑐 14𝑛𝑠
divmodti4 small / small l: 83𝑐 23𝑛𝑠
divmodti4 small / large l: 26𝑐 7𝑛𝑠
divmodti4 large / small l: 175𝑐 48𝑛𝑠
divmodti4 large / large l: 389𝑐 107𝑛𝑠
*/