aboutsummaryrefslogtreecommitdiff
path: root/base/runtime
diff options
context:
space:
mode:
authorLaytan <laytanlaats@hotmail.com>2024-08-20 19:00:49 +0200
committerLaytan <laytanlaats@hotmail.com>2024-08-20 19:01:09 +0200
commit8f2d3dc955f1135c64a03236e57ddd97186a18aa (patch)
tree8e5d89cacd14d9136e1106ffd03bb99415fd151a /base/runtime
parentdaa0779c019738ffe775e80e8c1a4f76cd4b1e0f (diff)
fix i128 division?
Diffstat (limited to 'base/runtime')
-rw-r--r--base/runtime/internal.odin26
1 files changed, 22 insertions, 4 deletions
diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin
index 1f85fb569..ff60cf547 100644
--- a/base/runtime/internal.odin
+++ b/base/runtime/internal.odin
@@ -1014,14 +1014,32 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
- u := udivmod128(u128(a), u128(b), (^u128)(rem))
- return i128(u)
+ s_a := a >> (128 - 1) // -1 if negative or 0
+ s_b := b >> (128 - 1)
+ an := (a ~ s_a) - s_a // absolute
+ bn := (b ~ s_b) - s_b
+
+ s_b ~= s_a // quotient sign
+ u_s_b := u128(s_b)
+ u_s_a := u128(s_a)
+
+ r: u128 = ---
+ u := i128((udivmodti4(u128(an), u128(bn), &r) ~ u_s_b) - u_s_b) // negate if negative
+ rem^ = i128((r ~ u_s_a) - u_s_a)
+ return u
}
@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divti3 :: proc "c" (a, b: i128) -> i128 {
- u := udivmodti4(u128(a), u128(b), nil)
- return i128(u)
+ s_a := a >> (128 - 1) // -1 if negative or 0
+ s_b := b >> (128 - 1)
+ an := (a ~ s_a) - s_a // absolute
+ bn := (b ~ s_b) - s_b
+
+ s_a ~= s_b // quotient sign
+ u_s_a := u128(s_a)
+
+ return i128((udivmodti4(u128(an), u128(bn), nil) ~ u_s_a) - u_s_a) // negate if negative
}