diff --git a/README.md b/README.md
index 536fe98..addfaa3 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
-:green_book: The [manual](https://github.com/Leedehai/typst-physics/blob/master/physica-manual.pdf).
+:green_book: The [manual](https://github.com/Leedehai/typst-physics/blob/v0.9.1/physica-manual.pdf).
-# The physica package for Typst
+# The physica package for Typst (v0.9.1)
[![CI](https://github.com/Leedehai/typst-physics/actions/workflows/ci.yml/badge.svg)](https://github.com/Leedehai/typst-physics/actions/workflows/ci.yml)
[![Latest release](https://img.shields.io/github/v/release/Leedehai/typst-physics.svg?color=gold)][latest-release]
@@ -27,7 +27,7 @@ natural sciences, including:
## A quick look
-See the [manual](https://github.com/Leedehai/typst-physics/blob/master/physica-manual.pdf) for more details and examples.
+See the [manual](https://github.com/Leedehai/typst-physics/blob/v0.9.1/physica-manual.pdf)for more details and examples.
![demo-quick](https://github.com/Leedehai/typst-physics/assets/18319900/4a9f40df-f753-4324-8114-c682d270e9c7)
@@ -89,7 +89,7 @@ typst 0.10.0 (70ca0d25)
## Manual
-See the manual [physica-manual.pdf](https://github.com/Leedehai/typst-physics/blob/master/physica-manual.pdf) for a more comprehensive coverage, a PDF file
+See the [manual](https://github.com/Leedehai/typst-physics/blob/v0.9.1/physica-manual.pdf) for a more comprehensive coverage, a PDF file
generated directly with the [Typst](https://typst.app) binary.
To regenerate the manual, use command
@@ -107,8 +107,9 @@ request. If it is large, the best first step is creating an issue and let us
explore the design together. Some features might warrant a package on its own.
* Testing: currently testing is done by closely inspecting the generated
-[physica-manual.pdf](https://github.com/Leedehai/typst-physics/blob/master/physica-manual.pdf). This does not scale well. I plan to add programmatic
-testing by comparing rendered pictures with golden images.
+[manual](https://github.com/Leedehai/typst-physics/blob/v0.9.1/physica-manual.pdf).
+This does not scale well. I plan to add programmatic testing by comparing
+rendered pictures with golden images.
## License
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000..8178e9e
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,66 @@
+# Changelog
+
+## 0.9.2 (pending)
+
+* Let `braket()` take an optional third argument to render `braket(u,A,v)` as
+`⟨u|A|v⟩`. The one argument case `braket(a)` is still rendered as `⟨a|a⟩` and
+the two argument case `braket(u,v)` is still rendered as `⟨u|v⟩`.
+* Let `expval()` take an optional second argument to render `expval(A,a)` as
+`⟨a|A|a⟩`. The one argument case `expval(A)` is still rendered as `⟨A⟩`.
+* **(breaking)** Differentiated big-O `Order(...)` and little-o `order(...)`.
+* Let Taylor series term `taylorterm(...)` automatically add parenthesis, so
+that e.g. `tarlorterm(f,x,1+a,n-1)`'s `1+a` and `n-1` can be put inside
+parenthesis when needed.
+* Fixed a rendering issue of `Set(...)` when it contains tall contents.
+* Removed the `box(..)` layer from `tensor(...)`'s phantom index.
+* Added 2D and 3D rotation matrix `rot2mat(...)` and `rot3mat(...)`.
+* Added Gram matrix `grammat(...)`.
+* Removed `gradient` and `divergence`, since most users will use the abbreviated
+names `grad` and `div`. This prevents name collisions when users do wildcard
+importing, especially with Typst's built-in `gradient` that shows color
+gradients on texts.
+
+## 0.9.1
+
+* Added show rules `super-T-as-transpose` and `super-plus-as-dagger`, so that
+`..^T` and `..^+` can be rendered as a transpose operator and a dagger
+(i.e. conjugate transpose) operator, respectively, just like handwriting.
+* Adjusted spacing for `dd()`, following advice in TeXBook Chapter 18. The
+intra spacing can be disabled by a new optional argument `compact:#true`.
+* Fixed a spacing issue of `vecrow(..)`.
+* **(breaking)** Let `iprod(..)` be rendered in the more familiar inner
+product `⟨a,b⟩`, instead of `⟨a|b⟩`--that can be done with `braket(a,b)`.
+* Added optional argument `big:#true` to Jacobian matrix and Hessian matrix, so
+that the fractions can be rendered in an "uncramped" form. The default is the
+"cramped" form just like LaTeX.
+* Added `taylorterm(...)` to display terms in the Taylor series.
+
+## 0.9.0
+
+Changed the minimum Typst version to 0.10.0.
+
+* Fixed the appearance of `braket`, `ketra`, and `mel`.
+* Fixed Hessian matrix `hmax(...)`.
+
+## 0.8.1
+
+## 0.8.0
+
+* Added CI.
+* **(breaking)** Let `va(...)` (vector arrow) be not bold, according to the ISO
+standard.
+
+## 0.7.5
+
+* First appeared in the official package collection
+[typst/packages](https://github.com/typst/packages).
+
+## 0.7.4
+
+* Renamed from `physics` to `physica`, meaning _natural sciences_.
+
+## 0.7.1
+
+## 0.6
+
+## 0.5
diff --git a/physica-manual.pdf b/physica-manual.pdf
index f062981..2343fc8 100644
Binary files a/physica-manual.pdf and b/physica-manual.pdf differ
diff --git a/physica-manual.typ b/physica-manual.typ
index 31a584d..774c851 100644
--- a/physica-manual.typ
+++ b/physica-manual.typ
@@ -109,10 +109,15 @@ All symbols need to be used in *math mode* `$...$`.
[`norm(phi(x))` #sym.arrow $norm(phi(x))$],
[norm],
+ [`Order(`_content_`)`],
+ [],
+ [`Order(x^2)` #sym.arrow $Order(x^2)$],
+ [big O],
+
[`order(`_content_`)`],
[],
- [`order(x^2)` #sym.arrow $order(x^2)$],
- [order of magnitude],
+ [`order(1)` #sym.arrow $order(1)$],
+ [small O],
[`Set(`_content_`)`],
[],
@@ -134,9 +139,9 @@ All symbols need to be used in *math mode* `$...$`.
[`expval`],
[
`expval(u)` #sym.arrow $expval(u)$ \
- `expval(f/N)` #sym.arrow $expval(f/N)$ \
+ `expval(p,psi)` #sym.arrow $expval(p,psi)$ \
],
- [expectation value],
+ [expectation value, also see bra-ket @dirac-braket below],
)
== Vector notations
@@ -182,13 +187,13 @@ All symbols need to be used in *math mode* `$...$`.
[`va(a),va(mu_1)` #sym.arrow $va(a),va(mu_1)$],
[vector, arrow \ #sub[(not bold: see ISO 80000-2:2019)]],
- [`gradient`],
[`grad`],
+ [],
[`grad f` #sym.arrow $grad f$],
[gradient],
- [`divergence`],
[`div`],
+ [],
[`div vb(E)` #sym.arrow $div vb(E)$],
[divergence],
@@ -225,6 +230,8 @@ All symbols need to be used in *math mode* `$...$`.
#v(1em)
+=== Determinant, (anti-)diagonal, identity, zero matrix
+
#table(
columns: (auto, auto, auto, auto),
align: left,
@@ -279,24 +286,11 @@ All symbols need to be used in *math mode* `$...$`.
#hl(`zmat(3,delim:"[")`) #sym.arrow \ $zmat(3,delim:"[")$
],
[zero matrix],
-
- [`jacobianmatrix(`...`)`],
- [`jmat`],
- [See below],
- [Jacobian matrix],
-
- [`hessianmatrix(`...`)`],
- [`hmat`],
- [See below],
- [Hessian matrix],
-
- [`xmatrix(`...`)`],
- [`xmat`],
- [See below],
- [Matrix built with an element building function],
)
-Jacobian matrix: `jacobianmatrix(`...`)`, i.e. `jmat(`...`)`.
+=== Jacobian matrix
+
+`jacobianmatrix(`...`)`, i.e. `jmat(`...`)`.
#table(
columns: (25%, auto, auto),
@@ -328,7 +322,9 @@ Jacobian matrix: `jacobianmatrix(`...`)`, i.e. `jmat(`...`)`.
],
)
-Hessian matrix: `hessianmatrix(`...`)`, i.e. `hmat(`...`)`.
+=== Hessian matrix
+
+`hessianmatrix(`...`)`, i.e. `hmat(`...`)`.
#table(
columns: (25%, auto, auto),
@@ -360,7 +356,10 @@ Hessian matrix: `hessianmatrix(`...`)`, i.e. `hmat(`...`)`.
],
)
-Matrix built with an element building function: `xmatrix(`_m, n, func_`)`, i.e. `xmat(`...`)`. The element building function _func_ takes two integers which are the row and column numbers starting from 1.
+=== Matrix with an element builder
+
+`xmatrix(`_m, n, func_`)`, i.e. `xmat(`...`)`. The element building function
+_func_ takes two integers which are the row and column numbers starting from 1.
#table(
columns: (auto, auto),
@@ -385,7 +384,64 @@ xmat(2, 2, #g)`)
],
)
-== Dirac braket notations
+=== Rotation matrices, 2D and 3D
+
+#table(
+ columns: (auto, auto, auto),
+ align: center,
+ stroke: none,
+ column-gutter: 1em,
+
+ [
+ #hl(`rot2mat(theta)`)
+ $ rot2mat(theta) $
+ ],
+ [
+ #hl(`rot2mat(-a/2,delim:"[")`)
+ $ rot2mat(-a/2, delim:"[") $
+ ],
+ [
+ #hl(`rot2mat(display(a/2),delim:"[")`)
+ $ rot2mat(display(a/2),delim:"[") $
+ ],
+
+ [
+ #hl(`rot3xmat(theta)`)
+ $ rot3xmat(theta) $
+ ],
+ [
+ #hl(`rot3ymat(45^degree)`)
+ $ rot3ymat(45^degree) $
+ ],
+ [
+ #hl(`rot3zmat(theta,delim:"[")`)
+ $ rot3zmat(theta,delim:"[") $
+ ],
+)
+
+=== Gram matrix
+
+#table(
+ columns: (auto, auto, auto),
+ align: center,
+ stroke: none,
+ column-gutter: 1em,
+
+ [
+ #hl(`grammat(alpha,beta)`)
+ $ grammat(alpha, beta) $
+ ],
+ [
+ #hl(`grammat(v_1,v_2,v_3, delim:"[")`)
+ $ grammat(v_1,v_2,v_3, delim:"[") $
+ ],
+ [
+ #hl(`grammat(v_1,v_2, norm:#true)`)
+ $ grammat(v_1,v_2, norm:#true) $
+ ],
+)
+
+== Dirac braket notations
#v(1em)
@@ -411,37 +467,36 @@ xmat(2, 2, #g)`)
],
[ket],
- [`expval(`_content_`)`],
+ [`braket(`..`)`],
[],
[
- `expval(u)` #sym.arrow $expval(u)$ \
- `expval(vec(1,2))` #sym.arrow $expval(vec(1,2))$
+ `braket(a), braket(u, v)` \ #sym.arrow $braket(a), braket(u, v)$ \
+ `braket(psi,A/N,phi)` #sym.arrow $braket(psi,A/N,phi)$
],
- [expectation],
+ [braket, with 1, 2, or 3 arguments],
- [`braket(`_a_, _b_`)`],
+ [`ketbra(`..`)`],
[],
[
- `braket(a), braket(u, v)` \ #sym.arrow $braket(a), braket(u, v)$ \
- `braket(vec(1,2), b)` #sym.arrow $braket(vec(1,2), b)$
+ `ketbra(a), ketbra(u, v)` \ #sym.arrow $ketbra(a), ketbra(u, v)$ \
+ `ketbra(a/N, b)` #sym.arrow $ketbra(a/N, b)$
],
- [braket],
+ [ketbra, with 1 or 2 arguments],
- [`ketbra(`_a_, _b_`)`],
+ [`expval(`_content_`)`],
[],
[
- `ketbra(a), ketbra(u, v)` \ #sym.arrow $ketbra(a), ketbra(u, v)$ \
- `ketbra(vec(1,2), b)` #sym.arrow $ketbra(vec(1,2), b)$
+ `expval(u)` #sym.arrow $expval(u)$ \
+ `expval(A,psi)` #sym.arrow $expval(A,psi)$
],
- [ketbra],
+ [expectation],
- [`matrixelement(`_n_, _M_, _m_`)`],
+ [`matrixelement(`..`)`],
[`mel`],
[
- `mel(n, diff_nu H, m)` \ #sym.arrow $mel(n, diff_nu H, m)$ \
- `mel(vec(U,V),A,m)` #sym.arrow $mel(vec(U,V),A,m)$
+ `mel(n, diff_nu H, m)` \ #sym.arrow $mel(n, diff_nu H, m)$
],
- [matrix element],
+ [matrix element, same as `braket(n,M,n)`],
)
== Math functions
@@ -780,7 +835,7 @@ transposition instead of a normal capital letter $T$.
This $square.stroked.dotted^T => square.stroked.dotted^TT$
conversion is disabled if the base is either
- a `limits(...)` or `scripts(...)` element, or
-- an integration symbol $integral$ or vertical bar $|$, or
+- an integration $integral$ or sum $sum$ (not greek $Sigma$) or product $product$ (not greek $Pi$) or vertical bar $|$, or
- an equation or `lr(...)` element whose last child is one of the above.
Overrides: if you really want to
@@ -812,20 +867,28 @@ If you only want to enable it within a content block's scope, you may do
[
*(1)* #hl(`(U V_n W')^T = W'^T V_n^T U^T`) \
- $ (U V_n W')^T = W'^T V_n^T U^T $
+ $ (Sigma V_n W')^T = W'^T V_n^T Sigma^T $
],
[
*(2)* #hl(`vec(a, b)^T, mat(a, b; c, d)^T`) \
$ vec(a, b)^T, mat(a, b; c, d)^T $
],
[
- *(3)* #hl(`limits(sum)^T, scripts(e)^T`) \
- $ limits(sum)^T, scripts(e)^T $
+ *(3)* #hl(`abs(a)^T, norm(a)^T, eval(F(t))^T_0`) \
+ $ abs(a)^T, norm(a)^T, eval(F(t))^T_0 $
+ ],
+ [
+ *(4)* #hl(`integral^T, sum^T, product^T`) \
+ $ integral^T, sum^T, product^T $
],
[
- *(4)* #hl(`integral_0^T, abs(a)^T, eval(F(t))^T_0`) \
- $ integral_0^T, abs(a)^T, eval(F(t))^T_0 $
+ *(5)* #hl(`limits(e)^T, scripts(e)^T`) \
+ $ limits(e)^T, scripts(e)^T $
],
+ [
+ *(6)* #hl(`(M+N)^T, (m+n)^scripts(T)`) \
+ $ (M+N)^T, (m+n)^scripts(T) $
+ ]
)
=== Matrix dagger with superscript +
@@ -962,8 +1025,8 @@ Function: `tensor(`_symbol_, \*_args_`)`.
$ tensor(AA,+a,+b,-c,-d,+e,-f,+g,-h) $
],
[
- *(7)* #hl(`tensor(R, -a, -b, -c, +d)`) \
- $ tensor(R, -a, -b, -c, +d) $
+ *(7)* #hl(`tensor(R, -a, -b, +d)`) \
+ $ tensor(R, -a, -b, +d) $
],
[
*(8)* #hl(`tensor(T,+1,-I(1,-1),+a_bot,-+,+-)`) \
@@ -1001,11 +1064,11 @@ Function: `isotope(`_element_, _a_: ..., _z_: ...`)`.
],
)
-*(3)* #hl(`isotope("Bi",a:211,z:83) --> isotope("Tl",a:207,z:81) + isotope("He",a:4,z:2)`)
-$ isotope("Bi",a:211,z:83) --> isotope("Tl",a:207,z:81) + isotope("He",a:4,z:2) $
+*(3)* #hl(`isotope("Bi",a:211,z:83) -> isotope("Tl",a:207,z:81) + isotope("He",a:4,z:2)`)
+$ isotope("Bi",a:211,z:83) -> isotope("Tl",a:207,z:81) + isotope("He",a:4,z:2) $
-*(4)* #hl(`isotope("Tl",a:207,z:81) --> isotope("Pb",a:207,z:82) + isotope(e,a:0,z:-1)`)
-$ isotope("Tl",a:207,z:81) --> isotope("Pb",a:207,z:82) + isotope(e,a:0,z:-1) $
+*(4)* #hl(`isotope("Tl",a:207,z:81) -> isotope("Pb",a:207,z:82) + isotope(e,a:0,z:-1)`)
+$ isotope("Tl",a:207,z:81) -> isotope("Pb",a:207,z:82) + isotope(e,a:0,z:-1) $
=== The n-th term in Taylor series
@@ -1016,8 +1079,8 @@ Function: `taylorterm(`_func_, _x_, _x0_, _idx_`)`.
- _x_: the variable name e.g. `x`,
- _x0_: the variable value at the expansion point e.g. `x_0`, `(1+a)`,
- _idx_: the index of the term, e.g. `0`, `1`, `2`, `n`, `(n+1)`.
-If _x0_ or _idx_ is in a parenthesis e.g. `(1+k)`, then the function
-automatically removes the outer parenthesis where appropriate.
+If _x0_ or _idx_ is an add/sub sequence e.g. `-a`, `a+b`, then the function
+automatically adds a parenthesis where appropriate.
#align(center, [*Examples*])
@@ -1034,20 +1097,20 @@ automatically removes the outer parenthesis where appropriate.
$ taylorterm(f,x,x_0,1) $
],
[
- *(3)* #hl(`taylorterm(f,x,(1+a),2)`) \
- $ taylorterm(f,x,(1+a),2) $
+ *(3)* #hl(`taylorterm(F,x^nu,x^nu_0,n)`) \
+ $ taylorterm(F,x^nu,x^nu_0,n) $
],
[
*(4)* #hl(`taylorterm(f,x,x_0,n)`) \
$ taylorterm(f,x,x_0,n) $
],
[
- *(5)* #hl(`taylorterm(F,x^nu,x^nu_0,n)`) \
- $ taylorterm(F,x^nu,x^nu_0,n) $
+ *(5)* #hl(`taylorterm(f,x,1+a,2)`) \
+ $ taylorterm(f,x,1+a,2) $
],
[
- *(6)* #hl(`taylorterm(f_p,x,x_0,(n+1))`) \
- $ taylorterm(f_p,x,x_0,(n+1)) $
+ *(6)* #hl(`taylorterm(f_p,x,x_0,n-1)`) \
+ $ taylorterm(f_p,x,x_0,n-1) $
],
)
diff --git a/physica.typ b/physica.typ
index 4b78249..9c3c1b7 100644
--- a/physica.typ
+++ b/physica.typ
@@ -3,8 +3,32 @@
// Repository: https://github.com/Leedehai/typst-physics
// Please see physica-manual.pdf for user docs.
+// Returns whether a Content object is an add/sub sequence, e.g. -a, a+b, a-b.
+// The caller is responsible for ensuring the input is a Content object.
+#let __is_add_sub_sequence(content) = {
+ if not content.has("children") { return false }
+
+ let impl(seq) = {
+ // Only check the top level, don't descend into the child, since we don't
+ // care if the child is a parenthesis group that contains +/-.
+ for child in seq.at("children") {
+ if child == [+] or child == [#sym.minus] { return true }
+ }
+ return false
+ }
+
+ // Before my https://github.com/typst/typst/pull/3063:
+ return impl(content)
+ // After my https://github.com/typst/typst/pull/3063:
+ // if content.func() == math.math-style {
+ // return impl(content.at("body"))
+ // } else {
+ // return impl(content)
+ // }
+}
+
// Returns whether a Content object holds an integer. The caller is responsible
-// for ensuring the input argument is a Content object.
+// for ensuring the input is a Content object.
#let __content_holds_number(content) = {
return content.func() == text and regex("^\d+$") in content.text
}
@@ -123,28 +147,37 @@
// == Braces
-#let Set(..sink) = style(styles => {
+#let Set(..sink) = {
let args = sink.pos() // array
let expr = args.at(0, default: none)
let cond = args.at(1, default: none)
- let height = measure($ expr cond $, styles).height;
- let phantom = box(height: height, width: 0pt, inset: 0pt, stroke: none);
if expr == none {
- if cond == none { ${}$ } else { ${lr(|phantom#h(0pt))#cond}$ }
+ if cond == none { ${}$ } else { ${mid(|) #cond}$ }
} else {
- if cond == none { ${#expr}$ } else { ${#expr lr(|phantom#h(0pt))#cond}$ }
+ if cond == none { ${#expr}$ } else { ${#expr mid(|) #cond}$ }
}
-})
+}
-#let order(content) = $cal(O)(content)$
+#let Order(content) = $cal(O)(content)$
+#let order(content) = $cal(o)(content)$
#let evaluated(content) = {
$lr(zwj#content|)$
}
#let eval = evaluated
-#let expectationvalue(f) = $lr(angle.l #f angle.r)$
+#let expectationvalue(..sink) = {
+ let args = sink.pos() // array
+ let expr = args.at(0, default: none)
+ let func = args.at(1, default: none)
+
+ if func == none {
+ $lr(angle.l expr angle.r)$
+ } else {
+ $lr(angle.l func#h(0pt)mid(|)#h(0pt)expr#h(0pt)mid(|)#h(0pt)func angle.r)$
+ }
+}
#let expval = expectationvalue
// == Vector notations
@@ -196,14 +229,9 @@
#let vectorarrow(a) = __vector(a, math.arrow, false)
#let va = vectorarrow
-#let gradient = $bold(nabla)$
-#let grad = gradient
-
-#let divergence = $bold(nabla)dot.c$
-#let div = divergence
-
+#let grad = $bold(nabla)$
+#let div = $bold(nabla)dot.c$
#let curl = $bold(nabla)times$
-
#let laplacian = $nabla^2$
#let dotproduct = $dot$
@@ -273,11 +301,12 @@
#let admat = antidiagonalmatrix
#let identitymatrix(order, delim:"(", fill:none) = {
- let order_num = 1
- if type(order) == content and __content_holds_number(order) {
- order_num = int(order.text)
+ let order_num = if type(order) == content and __content_holds_number(order) {
+ int(order.text)
+ } else if type(order) == "integer" {
+ order
} else {
- panic("the order shall be an integer, e.g. 2")
+ panic("imat/identitymatrix: the order shall be an integer, e.g. 2")
}
let ones = range(order_num).map((i) => 1)
@@ -286,11 +315,12 @@
#let imat = identitymatrix
#let zeromatrix(order, delim:"(") = {
- let order_num = 1
- if type(order) == content and __content_holds_number(order) {
- order_num = int(order.text)
+ let order_num = if type(order) == content and __content_holds_number(order) {
+ int(order.text)
+ } else if type(order) == "integer" {
+ order
} else {
- panic("the order shall be an integer, e.g. 2")
+ panic("zmat/zeromatrix: the order shall be an integer, e.g. 2")
}
let ones = range(order_num).map((i) => 0)
@@ -333,18 +363,22 @@
#let hmat = hessianmatrix
#let xmatrix(m, n, func, delim:"(") = {
- let rows = none
- if type(m) == content and __content_holds_number(m) {
- rows = int(m.text)
+ let rows = if type(m) == content and __content_holds_number(m) {
+ int(m.text)
+ } else if type(m) == "integer" {
+ m
} else {
- panic("the first argument shall be an integer, e.g. 2")
+ panic("xmat/xmatrix: the first argument shall be an integer, e.g. 2")
}
- let cols = none
- if type(n) == content and __content_holds_number(m) {
- cols = int(n.text)
+
+ let cols = if type(n) == content and __content_holds_number(m) {
+ int(n.text)
+ } else if type(n) == "integer" {
+ n
} else {
- panic("the second argument shall be an integer, e.g. 2")
+ panic("xmat/xmatrix: the second argument shall be an integer, e.g. 2")
}
+
assert(
type(func) == function,
message: "func shall be a function (did you forget to add a preceding '#' before the function name)?"
@@ -361,6 +395,56 @@
}
#let xmat = xmatrix
+#let rot2mat(theta, delim:"(") = {
+ let operand = if type(theta) == "content" and __is_add_sub_sequence(theta) {
+ $(theta)$
+ } else { theta }
+ $mat(cos operand, -sin operand;
+ sin operand, cos operand; delim: delim)$
+}
+
+#let rot3xmat(theta, delim:"(") = {
+ let operand = if type(theta) == "content" and __is_add_sub_sequence(theta) {
+ $(theta)$
+ } else { theta }
+ $mat(1, 0, 0;
+ 0, cos operand, -sin operand;
+ 0, sin operand, cos operand; delim: delim)$
+}
+
+#let rot3ymat(theta, delim:"(") = {
+ let operand = if type(theta) == "content" and __is_add_sub_sequence(theta) {
+ $(theta)$
+ } else { theta }
+ $mat(cos operand, 0, sin operand;
+ 0, 1, 0;
+ -sin operand, 0, cos operand; delim: delim)$
+}
+
+#let rot3zmat(theta, delim:"(") = {
+ let operand = if type(theta) == "content" and __is_add_sub_sequence(theta) {
+ $(theta)$
+ } else { theta }
+ $mat(cos operand, -sin operand, 0;
+ sin operand, cos operand, 0;
+ 0, 0, 1; delim: delim)$
+}
+
+#let grammat(..sink) = {
+ let vs = sink.pos() // array
+ let delim = sink.named().at("delim", default: "(")
+ let asnorm = sink.named().at("norm", default: false)
+
+ xmat(vs.len(), vs.len(), (i,j) => {
+ if (i == j and (not asnorm)) or i != j {
+ iprod(vs.at(i - 1), vs.at(j - 1))
+ } else {
+ let v = vs.at(i - 1)
+ $norm(#v)^2$
+ }
+ }, delim: delim)
+}
+
// == Dirac braket notations
#let bra(f) = $lr(angle.l #f|)$
@@ -368,12 +452,16 @@
#let braket(..sink) = style(styles => {
let args = sink.pos() // array
- assert(args.len() == 1 or args.len() == 2, message: "expecting 1 or 2 args")
- let bra = args.at(0)
- let ket = args.at(1, default: bra)
+ let bra = args.at(0, default: none)
+ let ket = args.at(-1, default: bra)
- $ lr(angle.l bra#h(0pt)mid(bar.v)#h(0pt)ket angle.r) $
+ if args.len() <= 2 {
+ $ lr(angle.l bra#h(0pt)mid(|)#h(0pt)ket angle.r) $
+ } else {
+ let middle = args.at(1)
+ $ lr(angle.l bra#h(0pt)mid(|)#h(0pt)middle#h(0pt)mid(|)#h(0pt)ket angle.r) $
+ }
})
#let ketbra(..sink) = style(styles => {
@@ -383,11 +471,11 @@
let ket = args.at(0)
let bra = args.at(1, default: ket)
- $ lr(bar.v ket#h(0pt)mid(angle.r#h(0pt)angle.l)#h(0pt)bra bar.v) $
+ $ lr(|ket#h(0pt)mid(angle.r#h(0pt)angle.l)#h(0pt)bra|) $
})
#let matrixelement(n, M, m) = style(styles => {
- $ lr(angle.l #n#h(0pt)mid(bar.v)#h(0pt)#M#h(0pt)mid(bar.v)#h(0pt)#m angle.r) $
+ $ lr(angle.l #n#h(0pt)mid(|)#h(0pt)#M#h(0pt)mid(|)#h(0pt)#m angle.r) $
})
#let mel = matrixelement
@@ -664,7 +752,9 @@
if e.func() == math.equation {
return __eligible(e.at("body"))
}
- (e != [∫]) and (e != [|]) and (e != sym.bar.v.double)
+ ((e != [∫]) and (e != [|]) and (e != [‖])
+ and (e != [∑]/*U+2211, not greek Sigma U+03A3*/)
+ and (e != [∏]/*U+220F, not greek Pi U+03A0 */))
}
if __eligible(elem.base) and elem.at("t", default: none) == [T] {
@@ -713,7 +803,7 @@
let args = sink.pos()
let (uppers, lowers) = ((), ()) // array, array
- let hphantom(s) = { hide(box(height: 0em, s)) } // Like Latex's \hphantom
+ let hphantom(s) = { hide($#s$) } // Like Latex's \hphantom
for i in range(args.len()) {
let arg = args.at(i)
@@ -751,21 +841,17 @@
}
#let taylorterm(fn, xv, x0, idx) = {
- let noparen(expr) = {
- if type(expr) == content and expr.func() == math.lr {
- let children = expr.at("body").at("children")
- children.slice(1, children.len() - 1).join()
- } else {
- expr
- }
+ let maybeparen(expr) = {
+ if __is_add_sub_sequence(expr) { $(expr)$ }
+ else { expr }
}
if idx == [0] or idx == 0 {
- $fn (noparen(x0))$
+ $fn (x0)$
} else if idx == [1] or idx == 1 {
- $fn^((1)) (noparen(x0))(xv - x0)$
+ $fn^((1)) (x0)(xv - maybeparen(x0))$
} else {
- $frac(fn^((noparen(idx))) (noparen(x0)), idx !)(xv - x0)^noparen(idx)$
+ $frac(fn^((idx)) (x0), maybeparen(idx) !)(xv - maybeparen(x0))^idx$
}
}