#let is-vec(vec) = { if type(vec) != dictionary {return false} if vec.at("type", default: none) != "vector" {return false} return true } #let _check(vec) = { if not is-vec(vec) { panic("Argument is not a vector") } } #let vec(..args) = { let comps = args.pos() let size = comps.len() return ( type: "vector", comps: comps, size: size ) } #let copy(vec) = { _check(vec) return vec(..vec.comps) } #let of-size(size) = { let comps = (0,) * size return vec(..comps) } #let display(vec) = { _check(vec) math.vec(..vec.comps.map(c => [#c])) } #let add(vec1, vec2) = { _check(vec1) _check(vec2) if vec1.size != vec2.size { panic("Can't add vectors of size " + str(vec1.size) + " and " + str(vec2.size)) } let comps = vec1.comps.zip(vec2.comps).map(p => p.sum()) return vec(..comps) } #let sub(vec1, vec2) = { _check(vec1) _check(vec2) if vec1.size != vec2.size { panic("Can't subtract vectors of size " + str(vec1.size) + " and " + str(vec2.size)) } let comps = vec1.comps.zip(vec2.comps).map(p => p.first() - p.last()) return vec(..comps) } #let dot(vec1, vec2) = { _check(vec1) _check(vec2) if vec1.size != vec2.size { panic("Can't compute dot product of vectors of size " + str(vec1.size) + " and " + str(vec2.size)) } let res = vec1.comps.zip(vec2.comps) .map(p => p.product()) .sum(default: 0) return res } #let cross(vec1, vec2) = { _check(vec1) _check(vec2) if vec1.size != 3 or vec2.size != 3 { panic("Can only compute cross product of vectors of size 3") } let vec3 = of-size(3) for i in range(3) { let i1 = calc.rem(i + 1, 3) let i2 = calc.rem(i1 + 1, 3) vec3.comps.at(i) = vec1.comps.at(i1) * vec2.comps.at(i2) vec3.comps.at(i) -= vec1.comps.at(i2) * vec2.comps.at(i1) } return vec3 } #let to-mat(vec) = { _check(vec) import "mat.typ" as _mat return _mat.mat(..vec.comps.map(c => (c,))) }