From e1927d4fec287e1ac659c9764372ff98403b965e Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 25 Oct 2024 16:57:52 +0300 Subject: [PATCH] Add rational.typ --- rational.typ | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 rational.typ diff --git a/rational.typ b/rational.typ new file mode 100644 index 0000000..3b9c6e1 --- /dev/null +++ b/rational.typ @@ -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) +} \ No newline at end of file