221 lines
4.1 KiB
Plaintext
221 lines
4.1 KiB
Plaintext
include "std/io.zr"
|
|
|
|
func i64.abs[n: i64] : i64
|
|
if n == -9223372036854775808
|
|
panic("MIN_I64 passed to math.abs")
|
|
if n < 0
|
|
return -n
|
|
return n
|
|
|
|
func i64.sign[n: i64] : i64
|
|
if n < 0
|
|
return -1
|
|
else if n > 0
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
func i64.isqrt[n: i64] : i64
|
|
if n < 0
|
|
panic("negative number passed to math.isqrt")
|
|
if n == 0 || n == 1
|
|
return n
|
|
|
|
guess := n
|
|
next_guess := (guess + n / guess) / 2
|
|
|
|
while next_guess < guess
|
|
guess = next_guess
|
|
next_guess = (guess + n / guess) / 2
|
|
|
|
return guess
|
|
|
|
func i64.is_prime[n: i64]: bool
|
|
if n <= 1
|
|
return false
|
|
if n == 2 || n == 3
|
|
return true
|
|
if n % 2 == 0 || n % 3 == 0
|
|
return false
|
|
|
|
i := 5
|
|
while i * i <= n
|
|
if n % i == 0 || n % (i + 2) == 0
|
|
return false
|
|
i += 6
|
|
return true
|
|
|
|
func i64.to_str_buf[n: i64, buf: ptr] : void
|
|
if n == 0
|
|
buf[0] = '0'
|
|
buf[1] = 0
|
|
return
|
|
|
|
neg : bool = n < 0
|
|
if neg
|
|
// MIN_I64 will fail but i so dont care
|
|
n = -n
|
|
tmp := _stackalloc(21)
|
|
end := 20
|
|
tmp[end] = 0
|
|
end -= 1
|
|
for i in 0..19
|
|
if n == 0
|
|
break
|
|
tmp[end] = '0' + (n % 10)
|
|
n = n / 10
|
|
end -= 1
|
|
if neg
|
|
tmp[end] = '-'
|
|
end -= 1
|
|
len := 19 - end
|
|
for i in 0..len
|
|
buf[i] = tmp[end + 1 + i]
|
|
buf[len] = 0
|
|
|
|
func i64.to_hex_str_buf[n: i64, buf: ptr] : void
|
|
hex_chars := "0123456789abcdef"
|
|
|
|
if n == 0
|
|
buf[0] = '0'
|
|
buf[1] = 0
|
|
return
|
|
|
|
mask := (1 << 60) - 1
|
|
tmp := _stackalloc(17)
|
|
len := 0
|
|
|
|
for i in 0..16
|
|
if n == 0
|
|
break
|
|
tmp[len] = hex_chars[n & 15]
|
|
n = (n >> 4) & mask
|
|
len += 1
|
|
|
|
for j in 0..len
|
|
buf[j] = tmp[len - 1 - j]
|
|
|
|
buf[len] = 0
|
|
|
|
func i64.to_str[n: i64] : str
|
|
out := mem.alloc(21)
|
|
n->to_str_buf(out)
|
|
return out as str
|
|
|
|
func i64.to_hex_str[n: i64] : str
|
|
out := mem.alloc(17)
|
|
n->to_hex_str_buf(out)
|
|
return out as str
|
|
|
|
func f64.to_str_buf[x: i64, buf: ptr] : void
|
|
bits := x
|
|
sign := (bits >> 63) & 1
|
|
exp := (bits >> 52) & 0x7ff
|
|
mant := bits & 0x000fffffffffffff
|
|
|
|
if exp == 0x7ff
|
|
panic("invalid float")
|
|
|
|
p := 0
|
|
if sign
|
|
buf[p] = '-'
|
|
p += 1
|
|
bits = bits & 0x7fffffffffffffff
|
|
|
|
if exp == 0 && mant == 0
|
|
buf[p] = '0'
|
|
buf[p+1] = '.'
|
|
buf[p+2] = '0'
|
|
buf[p+3] = 0
|
|
return
|
|
|
|
sig := mant
|
|
if exp != 0
|
|
sig = sig | 0x0010000000000000
|
|
|
|
shift := exp - 1075
|
|
|
|
if shift >= 0
|
|
(sig << shift)->to_str_buf(buf + p)
|
|
while buf[p]
|
|
p += 1
|
|
buf[p] = '.'
|
|
buf[p+1] = '0'
|
|
buf[p+2] = 0
|
|
return
|
|
|
|
ns := -shift
|
|
|
|
if ns <= 52
|
|
int_part := sig >> ns
|
|
int_part->to_str_buf(buf + p)
|
|
while buf[p]
|
|
p += 1
|
|
else
|
|
buf[p] = '0'
|
|
p += 1
|
|
|
|
buf[p] = '.'
|
|
p += 1
|
|
|
|
mask := (1 << ns) - 1
|
|
frac := sig & mask
|
|
|
|
for i in 0..6
|
|
if frac == 0
|
|
if i > 0
|
|
break
|
|
buf[p] = '0'
|
|
p += 1
|
|
break
|
|
frac = frac * 10
|
|
digit := frac >> ns
|
|
buf[p] = '0' + digit as u8
|
|
p += 1
|
|
frac = frac & mask
|
|
buf[p] = 0
|
|
|
|
func math.gcd[a: i64, b: i64] : i64
|
|
a = a->abs()
|
|
b = b->abs()
|
|
while b != 0
|
|
tmp := b
|
|
b = a % b
|
|
a = tmp
|
|
return a
|
|
|
|
func math.min[a: i64, b: i64] : i64
|
|
if a < b
|
|
return a
|
|
return b
|
|
|
|
func math.max[a: i64, b: i64] : i64
|
|
if a > b
|
|
return a
|
|
return b
|
|
|
|
func math.pow[b: i64, e: i64] : i64
|
|
if e < 0
|
|
panic("negative exponent passed to math.pow")
|
|
out := 1
|
|
while e > 0
|
|
if e & 1
|
|
out = out * b
|
|
b = b * b
|
|
e = e >> 1
|
|
return out
|
|
|
|
func math.lcm[a: i64, b: i64] : i64
|
|
return (a / math.gcd(a, b)) * b
|
|
|
|
func math.octal_to_decimal[octal: i64] : i64
|
|
decimal := 0
|
|
base := 1
|
|
|
|
while octal > 0
|
|
digit := octal % 10
|
|
decimal += digit * base
|
|
base = base * 8
|
|
octal = octal / 10
|
|
return decimal
|