Skip to content

Commit

Permalink
Add rational.typ
Browse files Browse the repository at this point in the history
  • Loading branch information
DanikVitek authored Oct 25, 2024
1 parent 71ab63d commit e1927d4
Showing 1 changed file with 145 additions and 0 deletions.
145 changes: 145 additions & 0 deletions rational.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#let p = plugin("typst_plugin_bigrational.wasm")

#let rational(x) = {
let convert-scalar(x) = if type(x) == str {
x
} else if type(x) == int {
str(x)
} else {
panic("Required a scalar, representing an integer")
}

if type(x) in (int, str) {
let numer = convert-scalar(x)
(numer, "1")
} else if type(x) == array and x.len() == 2 {
(convert-scalar(x.at(0)), convert-scalar(x.at(1)))
} else {
panic("Required a scalar, representing an integer, or an array of two such scalars")
}
}

#let add(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let c-bytes = p.add(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

let c-numer-len = int.from-bytes(c-bytes.slice(0, count: 8))
let c-numer = str(c-bytes.slice(8, count: c-numer-len))

let c-denom-len = int.from-bytes(c-bytes.slice(8 + c-numer-len, count: 8))
let c-denom = str(c-bytes.slice(8 + c-numer-len + 8, count: c-denom-len))

(c-numer, c-denom)
}

#let sub(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let c-bytes = p.sub(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

let c-numer-len = int.from-bytes(c-bytes.slice(0, count: 8))
let c-numer = str(c-bytes.slice(8, count: c-numer-len))

let c-denom-len = int.from-bytes(c-bytes.slice(8 + c-numer-len, count: 8))
let c-denom = str(c-bytes.slice(8 + c-numer-len + 8, count: c-denom-len))

(c-numer, c-denom)
}

#let div(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let c-bytes = p.div(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

let c-numer-len = int.from-bytes(c-bytes.slice(0, count: 8))
let c-numer = str(c-bytes.slice(8, count: c-numer-len))

let c-denom-len = int.from-bytes(c-bytes.slice(8 + c-numer-len, count: 8))
let c-denom = str(c-bytes.slice(8 + c-numer-len + 8, count: c-denom-len))

(c-numer, c-denom)
}

#let mul(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let c-bytes = p.mul(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

let c-numer-len = int.from-bytes(c-bytes.slice(0, count: 8))
let c-numer = str(c-bytes.slice(8, count: c-numer-len))

let c-denom-len = int.from-bytes(c-bytes.slice(8 + c-numer-len, count: 8))
let c-denom = str(c-bytes.slice(8 + c-numer-len + 8, count: c-denom-len))

(c-numer, c-denom)
}

#let repr(x) = {
let (numer, denom) = rational(x)

let repr-bytes = p.repr(bytes(numer), bytes(denom))

let variant = repr-bytes.at(0)
if variant == 0 [
$#(str(repr-bytes.slice(1, none)))$
] else if variant == 1 {
let numer-len = int.from-bytes(repr-bytes.slice(1, count: 8))
let numer = str(repr-bytes.slice(9, count: numer-len))

let denom-len = int.from-bytes(repr-bytes.slice(9 + numer-len, count: 8))
let denom = str(repr-bytes.slice(9 + numer-len + 8, count: denom-len))

$#str(numer)/#str(denom)$
} else if variant == 2 {
let whole-len = int.from-bytes(repr-bytes.slice(1, count: 8))
let whole = str(repr-bytes.slice(9, count: whole-len))

let numer-len = int.from-bytes(repr-bytes.slice(9 + whole-len, count: 8))
let numer = str(repr-bytes.slice(9 + whole-len + 8, count: numer-len))

let denom-len = int.from-bytes(repr-bytes.slice(9 + whole-len + 8 + numer-len, count: 8))
let denom = str(repr-bytes.slice(9 + whole-len + 8 + numer-len + 8, count: denom-len))

$#str(whole) #str(numer)/#str(denom)$
} else {
panic("Unknown variant: " + str(variant))
}
}

#let to-decimal-str(x) = {
let (numer, denom) = rational(x)
str(p.to_decimal_string(bytes(numer), bytes(denom)))
}

#let to-float(x) = {
float(to-decimal-str(x))
}

#let abs-diff(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let c-bytes = p.abs_diff(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

let c-numer-len = int.from-bytes(c-bytes.slice(0, count: 8))
let c-numer = str(c-bytes.slice(8, count: c-numer-len))

let c-denom-len = int.from-bytes(c-bytes.slice(8 + c-numer-len, count: 8))
let c-denom = str(c-bytes.slice(8 + c-numer-len + 8, count: c-denom-len))

(c-numer, c-denom)
}

#let cmp(a, b) = {
let (a-numer, a-denom) = rational(a)
let (b-numer, b-denom) = rational(b)

let ordering-bytes = p.cmp(bytes(a-numer), bytes(a-denom), bytes(b-numer), bytes(b-denom))

int.from-bytes(ordering-bytes)
}

0 comments on commit e1927d4

Please sign in to comment.