mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-10 05:11:37 -07:00
70 lines
1.3 KiB
Odin
70 lines
1.3 KiB
Odin
#shared_global_scope;
|
|
|
|
__u128_mod :: proc(a, b: u128) -> u128 #cc_odin #link_name "__umodti3" {
|
|
r: u128;
|
|
__u128_quo_mod(a, b, &r);
|
|
return r;
|
|
}
|
|
|
|
__u128_quo :: proc(a, b: u128) -> u128 #cc_odin #link_name "__udivti3" {
|
|
return __u128_quo_mod(a, b, nil);
|
|
}
|
|
|
|
__i128_mod :: proc(a, b: i128) -> i128 #cc_odin #link_name "__modti3" {
|
|
r: i128;
|
|
__i128_quo_mod(a, b, &r);
|
|
return r;
|
|
}
|
|
|
|
__i128_quo :: proc(a, b: i128) -> i128 #cc_odin #link_name "__divti3" {
|
|
return __i128_quo_mod(a, b, nil);
|
|
}
|
|
|
|
__i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_name "__divmodti4" {
|
|
s: i128;
|
|
s = b >> 127;
|
|
b = (b~s) - s;
|
|
s = a >> 127;
|
|
b = (a~s) - s;
|
|
|
|
urem: u128;
|
|
uquo := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &urem);
|
|
iquo := transmute(i128, uquo);
|
|
irem := transmute(i128, urem);
|
|
|
|
iquo = (iquo~s) - s;
|
|
irem = (irem~s) - s;
|
|
if rem != nil { rem^ = irem; }
|
|
return iquo;
|
|
}
|
|
|
|
|
|
__u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_name "__udivmodti4" {
|
|
alo, ahi := u64(a), u64(a>>64);
|
|
blo, bhi := u64(b), u64(b>>64);
|
|
if b == 0 {
|
|
if rem != nil { rem^ = 0; }
|
|
return u128(alo/blo);
|
|
}
|
|
|
|
r, d, x, q: u128 = a, b, 1, 0;
|
|
|
|
for r >= d && (d>>127)&1 == 0 {
|
|
x <<= 1;
|
|
d <<= 1;
|
|
}
|
|
|
|
for x != 0 {
|
|
if r >= d {
|
|
r -= d;
|
|
q |= x;
|
|
}
|
|
x >>= 1;
|
|
d >>= 1;
|
|
}
|
|
|
|
if rem != nil { rem^ = r; }
|
|
return q;
|
|
}
|
|
|