added polynomials
This commit is contained in:
parent
cfda844ebc
commit
c4bb53ccf7
Binary file not shown.
BIN
gallery/example4.pdf
Normal file
BIN
gallery/example4.pdf
Normal file
Binary file not shown.
34
gallery/example4.typ
Normal file
34
gallery/example4.typ
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#import "/src/lib.typ": *
|
||||||
|
|
||||||
|
#let p = poly.poly(0,1,2,3,4)
|
||||||
|
#let q = poly.poly(5,6,7)
|
||||||
|
|
||||||
|
#let a = poly.add(p, q)
|
||||||
|
#let b = poly.sub(p, q)
|
||||||
|
|
||||||
|
$
|
||||||
|
p = #poly.display(p) quad q = #poly.display(q)\
|
||||||
|
p + q = #poly.display(a)\
|
||||||
|
p - q = #poly.display(b)\
|
||||||
|
$
|
||||||
|
|
||||||
|
#let P = poly.poly(7, -3, -3, 1, 1)
|
||||||
|
#let Q = poly.poly(-2, 1, 1)
|
||||||
|
|
||||||
|
$
|
||||||
|
P = #poly.display(P) quad Q = #poly.display(Q)\
|
||||||
|
P / Q = #poly.display(P) / #poly.display(Q)
|
||||||
|
$
|
||||||
|
|
||||||
|
#let div = poly.div(P, Q)
|
||||||
|
#align(center, grid(
|
||||||
|
columns: 2,
|
||||||
|
align: left,
|
||||||
|
column-gutter: 2em,
|
||||||
|
row-gutter: 1em,
|
||||||
|
[dividend: #poly.display(div.dividend)],
|
||||||
|
grid.cell(rowspan: 4, (div.display)()),
|
||||||
|
[divisor: #poly.display(div.divisor)],
|
||||||
|
[quotient: #poly.display(div.quotient)],
|
||||||
|
[rest: #poly.display(div.rest)],
|
||||||
|
))
|
@ -1,4 +1,5 @@
|
|||||||
#import "mat.typ"
|
#import "mat.typ"
|
||||||
|
#import "poly.typ"
|
||||||
#import "vec.typ"
|
#import "vec.typ"
|
||||||
|
|
||||||
#import "gauss.typ"
|
#import "gauss.typ"
|
233
src/poly.typ
Normal file
233
src/poly.typ
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
#let is-poly(poly) = {
|
||||||
|
if type(poly) != dictionary {return false}
|
||||||
|
if poly.at("type", default: none) != "polynomial" {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
#let _check(poly) = {
|
||||||
|
if not is-poly(poly) {
|
||||||
|
panic("Argument is not a polynomial")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let poly(..args, trim-zeros: true) = {
|
||||||
|
let coefs = args.pos()
|
||||||
|
|
||||||
|
if trim-zeros {
|
||||||
|
let last-i = coefs.rev().position(c => c != 0)
|
||||||
|
if last-i == none {
|
||||||
|
last-i = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
coefs = coefs.slice(0, calc.min(coefs.len(), coefs.len() - last-i))
|
||||||
|
}
|
||||||
|
|
||||||
|
if coefs.len() == 0 {
|
||||||
|
coefs.push(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
type: "polynomial",
|
||||||
|
coefs: coefs,
|
||||||
|
deg: coefs.len() - 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let copy(original) = {
|
||||||
|
_check(original)
|
||||||
|
return poly(..original.coefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let display(poly) = {
|
||||||
|
_check(poly)
|
||||||
|
|
||||||
|
let fractions = (2, 3, 4, 5, 6)
|
||||||
|
let beautify-frac(value) = {
|
||||||
|
if calc.round(value) == value {
|
||||||
|
return str(value)
|
||||||
|
}
|
||||||
|
for den in fractions {
|
||||||
|
for num in range(1, 2 * den) {
|
||||||
|
if value == num / den {
|
||||||
|
return str(num) + "/" + str(den)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = ""
|
||||||
|
for (i, coef) in poly.coefs.rev().enumerate() {
|
||||||
|
if coef == 0 and poly.deg > 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i != 0 {
|
||||||
|
res += " "
|
||||||
|
if coef < 0 { res += "-" }
|
||||||
|
else { res += "+" }
|
||||||
|
} else if coef < 0 {
|
||||||
|
res += "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
if calc.abs(coef) != 1 or poly.deg - i == 0 {
|
||||||
|
res += str(beautify-frac(calc.abs(coef)))
|
||||||
|
}
|
||||||
|
if poly.deg - i > 0 {
|
||||||
|
res += "x"
|
||||||
|
}
|
||||||
|
if poly.deg - i > 1 {
|
||||||
|
res += "^" + str(poly.deg - i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eval("$" + res + "$")
|
||||||
|
}
|
||||||
|
|
||||||
|
#let pad(poly1, deg) = {
|
||||||
|
let coefs = poly1.coefs
|
||||||
|
coefs += (0,) * calc.max(0, (deg - poly1.deg))
|
||||||
|
return poly(..coefs, trim-zeros: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let shift(poly1, deg) = {
|
||||||
|
let coefs = (0,) * calc.max(0, (deg - poly1.deg))
|
||||||
|
coefs += poly1.coefs
|
||||||
|
return poly(..coefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let add(poly1, poly2) = {
|
||||||
|
let deg = calc.max(poly1.deg, poly2.deg)
|
||||||
|
let poly1 = pad(poly1, deg)
|
||||||
|
let poly2 = pad(poly2, deg)
|
||||||
|
|
||||||
|
let coefs = poly1.coefs.zip(poly2.coefs).map(p => p.sum())
|
||||||
|
|
||||||
|
return poly(..coefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let sub(poly1, poly2) = {
|
||||||
|
let deg = calc.max(poly1.deg, poly2.deg)
|
||||||
|
let poly1 = pad(poly1, deg)
|
||||||
|
let poly2 = pad(poly2, deg)
|
||||||
|
|
||||||
|
let coefs = poly1.coefs.zip(poly2.coefs).map(p => p.at(0) - p.at(1))
|
||||||
|
|
||||||
|
return poly(..coefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let mul(poly1, f) = {
|
||||||
|
let coefs = poly1.coefs.map(c => c * f)
|
||||||
|
return poly(..coefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let to-cells(poly) = {
|
||||||
|
let cells = ()
|
||||||
|
let first = true
|
||||||
|
for (i, coef) in poly.coefs.rev().enumerate() {
|
||||||
|
if coef == 0 and poly.deg > 0 {
|
||||||
|
cells.push("")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let cell = ""
|
||||||
|
if i != 0 {
|
||||||
|
if coef < 0 { cell += "-" }
|
||||||
|
else if not first { cell += "+" }
|
||||||
|
} else if coef < 0 {
|
||||||
|
cell += "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
if calc.abs(coef) != 1 or poly.deg - i == 0 {
|
||||||
|
cell += str(calc.abs(coef))
|
||||||
|
}
|
||||||
|
if poly.deg - i > 0 {
|
||||||
|
cell += "x"
|
||||||
|
}
|
||||||
|
if poly.deg - i > 1 {
|
||||||
|
cell += "^" + str(poly.deg - i)
|
||||||
|
}
|
||||||
|
cells.push(eval("$" + cell + "$"))
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
if poly.coefs.position(c => c != 0) == none {
|
||||||
|
cells.last() = "0"
|
||||||
|
}
|
||||||
|
return cells
|
||||||
|
}
|
||||||
|
|
||||||
|
#let div(
|
||||||
|
poly1,
|
||||||
|
poly2,
|
||||||
|
max-steps: 10
|
||||||
|
) = {
|
||||||
|
let P = poly1
|
||||||
|
let Q = poly2
|
||||||
|
let p = P
|
||||||
|
let rows = ()
|
||||||
|
let steps = ()
|
||||||
|
let D = poly()
|
||||||
|
let count = 0
|
||||||
|
|
||||||
|
while p.deg >= Q.deg and p.coefs.position(c => c != 0) != none {
|
||||||
|
let f = p.coefs.at(p.deg) / Q.coefs.at(Q.deg)
|
||||||
|
let sub = shift(mul(Q, -f), p.deg)
|
||||||
|
let rem = add(p, sub)
|
||||||
|
let d = shift(poly(f), p.deg - Q.deg)
|
||||||
|
steps.push((
|
||||||
|
p: p,
|
||||||
|
sub: sub,
|
||||||
|
rem: rem,
|
||||||
|
f: f,
|
||||||
|
d: d
|
||||||
|
))
|
||||||
|
|
||||||
|
D = add(D, d)
|
||||||
|
p = rem
|
||||||
|
if count >= max-steps {
|
||||||
|
panic("Exceeded maximum number of steps")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
let make-table(
|
||||||
|
vpad: 5pt,
|
||||||
|
hpad: 5pt,
|
||||||
|
stroke: black + 1pt,
|
||||||
|
debug-grid: false
|
||||||
|
) = {
|
||||||
|
let cells = ()
|
||||||
|
cells += to-cells(P)
|
||||||
|
cells.push(table.vline(stroke: stroke))
|
||||||
|
cells.push(display(Q))
|
||||||
|
cells.push(table.hline(start: P.deg + 1, stroke: stroke))
|
||||||
|
|
||||||
|
for (i, step) in steps.enumerate() {
|
||||||
|
cells += to-cells(pad(step.sub, P.deg))
|
||||||
|
if i == 0 {
|
||||||
|
cells.push(display(D))
|
||||||
|
} else {
|
||||||
|
cells.push("")
|
||||||
|
}
|
||||||
|
cells.push(table.hline(start: P.deg - step.sub.deg, end: P.deg - step.sub.deg + Q.deg + 1, stroke: stroke))
|
||||||
|
cells += to-cells(pad(step.rem, P.deg))
|
||||||
|
cells.push("")
|
||||||
|
}
|
||||||
|
|
||||||
|
table(
|
||||||
|
columns: P.deg + 2,
|
||||||
|
stroke: if debug-grid {gray + 1pt} else {none},
|
||||||
|
fill: none,
|
||||||
|
align: (x, _) => if x == P.deg + 1 {left} else {right},
|
||||||
|
inset: (left: hpad, right: hpad, top: vpad, bottom: vpad),
|
||||||
|
..cells
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
dividend: P,
|
||||||
|
divisor: Q,
|
||||||
|
quotient: D,
|
||||||
|
rest: p,
|
||||||
|
steps: steps,
|
||||||
|
display: make-table
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user