Skip to content

Commit

Permalink
perf: Some performance improvements (#816)
Browse files Browse the repository at this point in the history
Gives ~2 seconds when running tests.
  • Loading branch information
johannes-wolf authored Feb 21, 2025
1 parent 4162117 commit eb91007
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/canvas.typ
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
transform:
((1, 0,-.5, 0),
(0,-1,+.5, 0),
(0, 0, .0, 0),
(0, 0, 0, 0), // FIXME: This should not be zero for Z! Changing it destroys mark & decorations in 3D space.
(0, 0, .0, 1)),
// Nodes, stores anchors and paths
nodes: (:),
Expand Down
2 changes: 1 addition & 1 deletion src/coordinate.typ
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
// dictionary of numbers
return vector.scale(
c.bary.pairs().fold(
vector.new(3),
(0, 0, 0),
(vec, (k, v)) => {
vector.add(
vec,
Expand Down
22 changes: 12 additions & 10 deletions src/matrix.typ
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,17 @@
/// -> vector
#let mul4x4-vec3(mat, vec, w: 1) = {
assert(vec.len() <= 4)
let out = (0, 0, 0)
for m in range(0, 3) {
let v = (mat.at(m).at(0) * vec.at(0, default: 0)
+ mat.at(m).at(1) * vec.at(1, default: 0)
+ mat.at(m).at(2) * vec.at(2, default: 0)
+ mat.at(m).at(3) * vec.at(3, default: w))
out.at(m) = v
}
return out

let x = vec.at(0)
let y = vec.at(1)
let z = vec.at(2, default: 0)
let w = vec.at(3, default: w)

let ((a1,a2,a3,a4), (b1,b2,b3,b4), (c1,c2,c3,c4), _) = mat
return (
a1 * x + a2 * y + a3 * z + a4 * w,
b1 * x + b2 * y + b3 * z + b4 * w,
c1 * x + c2 * y + c3 * z + c4 * w)
}

// Multiply matrix with vector
Expand Down Expand Up @@ -319,7 +321,7 @@
return inverted
}

/// Swaps the ath column with the bth column.
/// Swaps the a-th column with the b-th column.
///
/// - mat (matrix): Matrix
/// - a (int): The index of column a.
Expand Down
64 changes: 20 additions & 44 deletions src/vector.typ
Original file line number Diff line number Diff line change
@@ -1,25 +1,3 @@
/// Returns a new vector of dimension `dim` with all fields set to `init` (defaults to 0).
///
/// - dim (int): Vector dimension
/// - init (float): Initial value of all fields
/// -> vector
#let new(dim, init: 0) = {
return range(0, dim).map(x => init)
}

/// Returns the dimension of a vector.
///
/// - v (vector): The vector to find the dimension of.
/// -> int
#let dim(v) = {
assert(
type(v) == array,
message: "Expected vector to be of array type, got: " + repr(v)
)
return v.len()
}


/// Converts a vector to a row or column matrix.
///
/// - v (vector): The vector to convert.
Expand All @@ -35,13 +13,13 @@
}
}

/// Ensures a vector has an exact dimension. This is done by passing another vector `init` that has the required dimension. If the original vector does not have enough dimensions, the values from `init` will be inserted. It is recommended to use a zero vector for `init`.
/// Ensures a vector has an exact number of components. This is done by passing another vector `init` that has the required dimension. If the original vector does not have enough dimensions, the values from `init` will be inserted. It is recommended to use a zero vector for `init`.
///
/// - v (vector): The vector to ensure.
/// - init (vector): The vector to check the dimension against.
/// -> vector
#let as-vec(v, init: (0, 0, 0)) = {
for i in range(0, calc.min(dim(v), dim(init))) {
for i in range(0, calc.min(v.len(), init.len())) {
init.at(i) = v.at(i)
}
return init
Expand All @@ -62,12 +40,9 @@
/// - v2 (vector): The vector on the right hand side.
/// -> vector
#let add(v1, v2) = {
if dim(v1) != dim(v2) {
v1 = as-vec(v1)
v2 = as-vec(v2)
}
assert(dim(v1) == dim(v2), message: "Cannot add vectors, " + repr(v1) + " and " + repr(v2) + " are not of the same dimensions.")
return v1.zip(v2).map(((a, b)) => a + b)
range(0, calc.max(v1.len(), v2.len())).map(i => {
v1.at(i, default: 0) + v2.at(i, default: 0)
})
}

/// Subtracts two vectors of the same dimension
Expand All @@ -76,12 +51,9 @@
/// - v2 (vector): The vector on the right hand side.
/// -> vector
#let sub(v1, v2) = {
if dim(v1) != dim(v2) {
v1 = as-vec(v1)
v2 = as-vec(v2)
}
assert(dim(v1) == dim(v2), message: "Cannot subtract vectors, " + repr(v1) + " and " + repr(v2) + " are not of the same dimensions.")
return v1.zip(v2).map(((a, b)) => a - b)
range(0, calc.max(v1.len(), v2.len())).map(i => {
v1.at(i, default: 0) - v2.at(i, default: 0)
})
}

/// Calculates the distance between two vectors by subtracting the length of vector `a` from vector `b`.
Expand Down Expand Up @@ -122,7 +94,7 @@
/// - v2 (vector): The vector on the right hand side.
/// -> float
#let dot(v1, v2) = {
assert(dim(v1) == dim(v2))
assert(v1.len() == v2.len())
return v1.enumerate().fold(0, (s, t) => s + t.at(1) * v2.at(t.at(0)))
}

Expand All @@ -131,11 +103,14 @@
/// - v2 (vector): The vector on the right hand side.
/// -> vector
#let cross(v1, v2) = {
assert(dim(v1) == 3 and dim(v2) == 3)
let x = v1.at(1) * v2.at(2) - v1.at(2) * v2.at(1)
let y = v1.at(2) * v2.at(0) - v1.at(0) * v2.at(2)
let z = v1.at(0) * v2.at(1) - v1.at(1) * v2.at(0)
return (x, y, z)
assert(v1.len() == 3 and v2.len() == 3)

let (x1, y1, z1) = v1
let (x2, y2, z2) = v2

return (y1 * z2 - z1 * y2,
z1 * x2 - x1 * z2,
x1 * y2 - y1 * x2)
}

/// Calculates the angle between two vectors and the x-axis in 2d space
Expand All @@ -152,8 +127,9 @@
/// - c (vector): The vector to measure the angle at.
/// - v2 (vector): The vector to measure the angle to.
#let angle(v1, c, v2) = {
assert(dim(v1) == dim(v2), message: "Vectors " + repr(v1) + " and " + repr(v2) + " do not have the same dimensions.")
if dim(v1) == 2 or dim(v1) == 3 {
assert(v1.len() == v2.len(),
message: "Vectors " + repr(v1) + " and " + repr(v2) + " do not have the same dimensions.")
if v1.len() == 2 or v1.len() == 3 {
v1 = sub(v1, c)
v2 = sub(v2, c)
return calc.acos(dot(norm(v1), norm(v2)))
Expand Down
2 changes: 1 addition & 1 deletion tests/transform-precission/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
set-ctx(ctx => {
ctx.transform = ((calc.cos(th), -calc.sin(th), 0, 0),
(-calc.sin(th), -calc.cos(th), 0, 0),
(0, 0, 0, 0),
(0, 0, 1, 0),
(0, 0, 0, 1),)
return ctx
})
Expand Down

0 comments on commit eb91007

Please sign in to comment.