mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-01 18:44:41 +00:00
159 lines
3.4 KiB
Odin
159 lines
3.4 KiB
Odin
#shared_global_scope;
|
|
|
|
|
|
// import "fmt.odin";
|
|
|
|
// proc __u128_mod(a, b: u128) -> u128 #link_name "__umodti3" {
|
|
// var _, r := __u128_quo_mod(a, b)
|
|
// return r
|
|
// }
|
|
|
|
// proc __u128_quo(a, b: u128) -> u128 #link_name "__udivti3" {
|
|
// var n, _ := __u128_quo_mod(a, b)
|
|
// return n
|
|
// }
|
|
|
|
// proc __i128_mod(a, b: i128) -> i128 #link_name "__modti3" {
|
|
// var _, r := __i128_quo_mod(a, b)
|
|
// return r
|
|
// }
|
|
|
|
// proc __i128_quo(a, b: i128) -> i128 #link_name "__divti3" {
|
|
// var n, _ := __i128_quo_mod(a, b)
|
|
// return n
|
|
// }
|
|
|
|
// proc __i128_quo_mod(a, b: i128) -> (i128, i128) #link_name "__divmodti4" {
|
|
// var s := b >> 127
|
|
// b = (b ~ s) - s
|
|
// s = a >> 127
|
|
// a = (a ~ s) - s
|
|
|
|
// var n, r := __u128_quo_mod(a as u128, b as u128)
|
|
// return (n as i128 ~ s) - s, (r as i128 ~ s) - s
|
|
// }
|
|
|
|
|
|
// proc __u128_quo_mod(a, b: u128) -> (u128, u128) #link_name "__udivmodti4" {
|
|
// proc clz(x: u64) -> u64 {
|
|
// proc clz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64"
|
|
// return clz_u64(x, false)
|
|
// }
|
|
// proc ctz(x: u64) -> u64 {
|
|
// proc ctz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64"
|
|
// return ctz_u64(x, false)
|
|
// }
|
|
|
|
|
|
// u128_lo_hi :: raw_union {
|
|
// all: u128
|
|
// using _lohi: struct {lo, hi: u64;}
|
|
// }
|
|
|
|
// n, d, q, r: u128_lo_hi
|
|
// sr: u64
|
|
|
|
// n.all = a
|
|
// d.all = b
|
|
|
|
// if n.hi == 0 {
|
|
// if d.hi == 0 {
|
|
// return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128
|
|
// }
|
|
// return 0, n.lo as u128
|
|
// }
|
|
// if d.lo == 0 {
|
|
// if d.hi == 0 {
|
|
// return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128
|
|
// }
|
|
// if n.lo == 0 {
|
|
// r.hi = n.hi % d.hi
|
|
// r.lo = 0
|
|
// return (n.hi / d.hi) as u128, r.all
|
|
// }
|
|
// if (d.hi & (d.hi-1)) == 0 {
|
|
// r.lo = n.lo
|
|
// r.hi = n.hi & (d.hi-1)
|
|
// return (n.hi >> ctz(d.hi)) as u128, r.all
|
|
// }
|
|
|
|
// sr = clz(d.hi) - clz(n.hi)
|
|
// if sr > 64 - 2 {
|
|
// return 0, n.all
|
|
// }
|
|
// sr++
|
|
// q.lo = 0
|
|
// q.hi = n.lo << (64-sr)
|
|
// r.hi = n.hi >> sr
|
|
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
|
// } else {
|
|
// if d.hi == 0 {
|
|
// if (d.lo & (d.lo - 1)) == 0 {
|
|
// var rem := (n.lo % (d.lo - 1)) as u128
|
|
// if d.lo == 1 {
|
|
// return n.all, rem
|
|
// }
|
|
// sr = ctz(d.lo)
|
|
// q.hi = n.hi >> sr
|
|
// q.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
|
// return q.all, rem
|
|
// }
|
|
|
|
// sr = 1 + 64 + clz(d.lo) - clz(n.hi)
|
|
|
|
// q.all = n.all << (128-sr)
|
|
// r.all = n.all >> sr
|
|
// if sr == 64 {
|
|
// q.lo = 0
|
|
// q.hi = n.lo
|
|
// r.hi = 0
|
|
// r.lo = n.hi
|
|
// } else if sr < 64 {
|
|
// q.lo = 0
|
|
// q.hi = n.lo << (64-sr)
|
|
// r.hi = n.hi >> sr
|
|
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
|
// } else {
|
|
// q.lo = n.lo << (128-sr)
|
|
// q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64))
|
|
// r.hi = 0
|
|
// r.lo = n.hi >> (sr-64)
|
|
// }
|
|
// } else {
|
|
// sr = clz(d.hi) - clz(n.hi)
|
|
// if sr > 64-1 {
|
|
// return 0, n.all
|
|
// }
|
|
// sr++
|
|
// q.lo = 0
|
|
// q.hi = n.lo << (64-sr)
|
|
// r.all = n.all >> sr
|
|
// if sr < 64 {
|
|
// r.hi = n.hi >> sr
|
|
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
|
// } else {
|
|
// r.hi = 0
|
|
// r.lo = n.hi
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// carry: u64
|
|
// for ; sr > 0; sr-- {
|
|
// r.hi = (r.hi << 1) | (r.lo >> (64-1))
|
|
// r.lo = (r.lo << 1) | (r.hi >> (64-1))
|
|
// q.hi = (q.hi << 1) | (q.lo >> (64-1))
|
|
// q.lo = (q.lo << 1) | carry
|
|
|
|
// carry = 0
|
|
// if r.all >= d.all {
|
|
// r.all -= d.all
|
|
// carry = 1
|
|
// }
|
|
// }
|
|
|
|
// q.all = (q.all << 1) | (carry as u128)
|
|
// return q.all, r.all
|
|
// }
|
|
|