[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Satvik Saha\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# typst-theorems\n\nAn implementation of numbered theorem environments in\n[typst](https://github.com/typst/typst).\nAvailable as [ctheorems](https://typst.app/universe/package/ctheorems) in the\nofficial Typst Universe.\nImport with\n\n```typst\n#import \"@preview/ctheorems:1.1.3\": *\n#show: thmrules\n```\n\nAlternatively, copy and import the [theorems.typ](theorems.typ) file to use in\nyour own projects.\n\n### Features\n- Numbered theorem environments can be created and customized.\n- Environments can share the same counter, via same `identifier`s.\n- Environment counters can be _attached_ (just as subheadings are attached to headings) to other environments, headings, or keep a global count via `base`.\n- The depth of a counter can be manually set, via `base_level`.\n- Environments can be `<label>`'d and `@reference`'d.\n\n## Manual and Examples\nGet acquainted with `typst-theorems` by checking out the minimal example below!\n\nYou can read the [manual](manual.pdf) for a full walkthrough of functionality offered by this module; flick through [manual_examples](manual_examples.pdf) and its [typ file](manual_examples.typ) to just see the examples.\n\nThe [differential_calculus.typ](differential_calculus.typ) ([render](differential_calculus.pdf)) project provides a practical use case. _(Hastily translated from my notes written in LaTeX)_\n\n![basic example](basic.png)\n\n### Preamble\n```typst\n#import \"theorems.typ\": *\n#show: thmrules.with(qed-symbol: $square$)\n\n#set page(width: 16cm, height: auto, margin: 1.5cm)\n#set text(font: \"Libertinus Serif\", lang: \"en\")\n#set heading(numbering: \"1.1.\")\n\n#let theorem = thmbox(\"theorem\", \"Theorem\", fill: rgb(\"#eeffee\"))\n#let corollary = thmplain(\n  \"corollary\",\n  \"Corollary\",\n  base: \"theorem\",\n  titlefmt: strong\n)\n#let definition = thmbox(\"definition\", \"Definition\", inset: (x: 1.2em, top: 1em))\n\n#let example = thmplain(\"example\", \"Example\").with(numbering: none)\n#let proof = thmproof(\"proof\", \"Proof\")\n```\n\n### Document\n```typst\n= Prime numbers\n\n#definition[\n  A natural number is called a #highlight[_prime number_] if it is greater\n  than 1 and cannot be written as the product of two smaller natural numbers.\n]\n#example[\n  The numbers $2$, $3$, and $17$ are prime.\n  @cor_largest_prime shows that this list is not exhaustive!\n]\n\n#theorem(\"Euclid\")[\n  There are infinitely many primes.\n]\n#proof[\n  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration\n  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,\n  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since\n  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a\n  contradiction.\n]\n\n#corollary[\n  There is no largest prime number.\n] <cor_largest_prime>\n#corollary[\n  There are infinitely many composite numbers.\n]\n\n#theorem[\n  There are arbitrarily long stretches of composite numbers.\n]\n#proof[\n  For any $n > 2$, consider $\n    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere\n  $\n]\n```\n\n\n## Acknowledgements\n\nThanks to\n\n- [MJHutchinson](https://github.com/MJHutchinson) for suggesting and\n  implementing the `base_level` and `base: none` features,\n- [rmolinari](https://github.com/rmolinari) for suggesting and\n  implementing the `separator: ...` feature,\n- [DVDTSB](https://github.com/DVDTSB) for contributing\n  - the idea of passing named arguments from the theorem directly to the `fmt`\n    function.\n  - the `number: ...` override feature.\n  - the `title: ...` override feature in `thmbox`.\n- [PgBiel](https://github.com/PgBiel) for fixing breaking changes in version\n  updates.\n- The awesome devs of [typst.app](https://typst.app/) for their\n  support.\n"
  },
  {
    "path": "basic.typ",
    "content": "#import \"theorems.typ\": *\n#show: thmrules.with(qed-symbol: $square$)\n\n#set page(width: 16cm, height: auto, margin: 1.5cm)\n#set text(font: \"Libertinus Serif\", lang: \"en\")\n#set heading(numbering: \"1.1.\")\n\n#let theorem = thmbox(\"theorem\", \"Theorem\", fill: rgb(\"#eeffee\"))\n#let corollary = thmplain(\n  \"corollary\",\n  \"Corollary\",\n  base: \"theorem\",\n  titlefmt: strong\n)\n#let definition = thmbox(\"definition\", \"Definition\", inset: (x: 1.2em, top: 1em))\n\n#let example = thmplain(\"example\", \"Example\").with(numbering: none)\n#let proof = thmproof(\"proof\", \"Proof\")\n\n\n= Prime numbers\n\n#definition[\n  A natural number is called a #highlight[_prime number_] if it is greater\n  than 1 and cannot be written as the product of two smaller natural numbers.\n]\n#example[\n  The numbers $2$, $3$, and $17$ are prime.\n  @cor_largest_prime shows that this list is not exhaustive!\n]\n\n#theorem(\"Euclid\")[\n  There are infinitely many primes.\n]\n#proof[\n  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration\n  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,\n  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since\n  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a\n  contradiction.\n]\n\n#corollary[\n  There is no largest prime number.\n] <cor_largest_prime>\n#corollary[\n  There are infinitely many composite numbers.\n]\n\n#theorem[\n  There are arbitrarily long stretches of composite numbers.\n]\n#proof[\n  For any $n > 2$, consider $\n    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere\n  $\n]\n"
  },
  {
    "path": "differential_calculus.typ",
    "content": "#import \"theorems.typ\": *\n#show: thmrules\n\n// Define theorem environments\n\n#let theorem = thmbox(\n  \"theorem\",\n  \"Theorem\",\n  fill: rgb(\"#e8e8f8\")\n)\n#let lemma = thmbox(\n  \"theorem\",            // Lemmas use the same counter as Theorems\n  \"Lemma\",\n  fill: rgb(\"#efe6ff\")\n)\n#let corollary = thmbox(\n  \"corollary\",\n  \"Corollary\",\n  base: \"theorem\",      // Corollaries are 'attached' to Theorems\n  fill: rgb(\"#f8e8e8\")\n)\n\n#let definition = thmbox(\n  \"definition\",         // Definitions use their own counter\n  \"Definition\",\n  fill: rgb(\"#e8f8e8\")\n)\n\n#let exercise = thmbox(\n  \"exercise\",\n  \"Exercise\",\n  stroke: rgb(\"#ffaaaa\") + 1pt,\n  base: none,           // Unattached: count globally\n).with(numbering: \"I\")  // Use Roman numerals\n\n// Examples and remarks are not numbered\n#let example = thmplain(\"example\", \"Example\").with(numbering: none)\n#let remark = thmplain(\n  \"remark\",\n  \"Remark\",\n  inset: 0em\n).with(numbering: none)\n\n// Proofs are attached to theorems, although they are not numbered\n#let proof = thmproof(\n  \"proof\",\n  \"Proof\",\n  base: \"theorem\",\n)\n\n#let solution = thmplain(\n  \"solution\",\n  \"Solution\",\n  base: \"exercise\",\n  inset: 0em,\n).with(numbering: none)\n\n\n// Template\n\n#let project(title: \"\", authors: (), body) = {\n  set document(author: authors, title: title)\n  set text(font: \"Libertinus Serif\", lang: \"en\")\n  set heading(numbering: \"1.1.\", )\n  set par(justify: true)\n\n  show heading: it => [\n    #v(1em)\n    #it\n  ]\n\n  align(center)[\n    #block(text(weight: 700, 1.75em, title))\n    #v(2em)\n  ]\n\n  outline(fill: none, indent: true)\n\n  body\n}\n\n// Shorthand for vectors\n#let va = $bold(a)$\n#let vb = $bold(b)$\n#let vx = $bold(x)$\n#let vy = $bold(y)$\n#let vz = $bold(z)$\n#let vv = $bold(v)$\n#let vw = $bold(w)$\n#let ve = $bold(e)$\n\n// Mapping arrow\n#let mapsto = $arrow.r.bar$\n\n// Operators\n#let grad = (x) => $nabla #x$\n#let ip = (x, y) => $angle.l #x, #y angle.r$\n#let pp = (x, y) => $(diff #x) / (diff #y)$\n#let dd = (x, y) => $(d #x) / (d #y)$\n#let Df = $D f$\n#let Dg = $D g$\n#let DT = $D T$\n\n\n// Document starts here\n\n#show: project.with(\n  title: \"Notes on Differential Calculus\"\n)\n\n= Differentiability\n\n#definition[\n    Let $f : (a, b) -> RR^n$, and let $f_i = pi_i compose  f$ be its\n    components. Then, $f$ is differentiable at $t_0  in  (a, b)$ if the\n    following limit exists. $ \n        f'(t_0) =  lim _(h -> 0)  frac(f(t_0 + h) - f(t_0), h)  .\n    $\n    #remark[\n        The vector $f'(t_0)$ represents the tangent to the curve $f$ at the\n        point $f(t_0)$. The full tangent line is the parametric curve $f(t) +\n        f'(t_0)(t - t_0)$.\n    ]\n]\n\n#definition[\n    Let $U  subset.eq  RR^n$ be open, and let $f: U -> RR^m$. Then, $f$ is\n    differentiable at $x  in  U$ if there exists a linear transformation $\n    lambda : RR^n -> RR^m$ such that $ \n         lim _(h -> 0)   frac(f(x + h) - f(x) -  lambda  h,  norm(h))  = 0.\n    $ The derivative of $f$ at $x$ is denoted by $lambda  = Df(x)$.\n    #remark[\n        In a neighbourhood of $x$, we may approximate $ \n            f(x + h)  approx  f(x) + Df(x)(h).\n        $\n    ]\n    #remark[\n        The statement that this quantity goes to zero means that each of the\n        $m$ components must also go to zero. For each of these limits, there\n        are $n$ axes along which we can let $h -> 0$. As a result, we obtain\n        $m times n$ limits, which allow us to identify the $m times n$\n        components of the matrix representing the linear transformation\n        $lambda$ (in the standard basis). These are the partial derivatives of\n        $f$, and the matrix of $lambda$ is the Jacobian matrix of $f$\n        evaluated at $x$.\n    ]\n]\n\n#example[\n    Let $T: RR^n -> RR^m$ be a linear map. By choosing $ lambda = T$, we see\n    that $T$ is differentiable everywhere, with $DT(x) = T$ for every choice\n    of $x  in  RR^n$. This is made obvious by the fact that the best linear\n    approximation of a linear map at some point is the map itself; indeed, the\n    'approximation' is exact.\n]\n\n#lemma[\n    If $f: RR^n -> RR^m$ is differentiable at $x  in  RR^n$, with derivative\n    $Df(x)$, then\n        + $f$ is continuous at $x$.\n        + The linear transformation $Df(x)$ is unique.\n]\n#proof[\n    We prove the second part. Suppose that $lambda$, $mu$ satisfy the\n    requirements for $Df(x)$; it can be shown that $ lim _(h -> 0) ( lambda  -\n    mu )h \\/  norm(h)  = 0$. Now, if $ lambda  v  !=   mu  v$ for some\n    non-zero vector $v  in  RR^n$, then $ \n         lambda  v -  mu  v =   frac(lambda (t v) - mu(t v), norm(t v))\n         dot.c norm(v) -> 0,\n    $ a contradiction.\n]\n\n= Chain rule\n\n#exercise[\n    Let $T: RR^n -> RR^m$ be a linear transformation. Then, there exists $M\n    > 0$ such that for all $ vx   in  RR^n$, we have $ \n         norm(T vx )   <=  M norm( vx ) .\n    $\n    #solution[\n        Set $ vv _i = T( ve _i)$ where $ ve _i$ are the standard unit basis\n        vectors of $RR^n$. Then, $ \n             norm(T vx )\n             =   norm( sum _(i) x_i vv _i)\n             <=  sum _(i) norm(x_i vv _i) \n             <=  max  norm( vv _i)   sum _i |x_i|.\n        $  Since each $|x_i|  <=   norm( vx ) $, set $M = n max  norm( vv _i)\n        $ and write $ \n             norm(T vx )\n             <=  max  norm( vv _i)  sum _i |x_i|\n             <=  max  norm( vv _i)  dot.c  n norm( vx )\n             = M norm( vx ) .\n        $\n    ]\n]\n#theorem(\"Chain Rule\")[\n    Let $f: RR^n -> RR^m$, $g: RR^m -> RR^k$ where $f$ is differentiable at $a\n    in  RR^n$ and $g$ is differentiable at $f(a)  in  RR^m$.  Then, $g compose\n    f$ is differentiable, with $D(g compose  f)(a) = Dg(f(a))  compose Df(a)$.\n    Note that this means that the Jacobian matrices simply multiply.\n]\n#proof[\n    Set $b = f(a)  in  RR^m$, $ lambda  = Df(a)$, $ mu  = Dg(f(a))$. Define \n    $\n         phi : RR^n -> RR^m, quad   phi (x) &= f(x) - f(a) -  lambda (x\n        - a), \\\n         psi : RR^m -> RR^k, quad   psi (y) &= g(y) - g(b) -  mu (y - b).\n    $\n    We claim that $ \n         lim _(x -> a) frac(g compose  f(x) - g compose  f(a) -  mu  compose   lambda (x\n        - a),  norm(x - a) ) = 0.\n    $  Write the numerator as $ \n        g compose  f(x) - g compose  f(a) -  mu  compose   lambda (x - a) =  psi (f(x)) +\n         mu ( phi (x)).\n    $  Note that $ \n         lim _(x -> a)   frac( phi (x),  norm(x - a)  )  = 0, quad\n         lim _(y -> b)   frac( psi (y),  norm(y - b)  )  = 0.\n    $  Thus, find $M > 0$ such that $ norm( mu ( phi (x)))   <= \n     norm( phi (x)) $ for all $x  in  RR^n$, hence $ \n         lim _(x -> a)   frac( norm( mu ( phi (x))) ,  norm(x - a)  )   <=\n         lim _{x -> a}   frac(M norm( phi (x)) ,  norm(x - a)  )  = 0.\n    $  Now write $ \n         lim _(f(x) -> b)   frac( psi (f(x)),  norm(f(x)  - b) )  = 0, \n    $  hence for any $ epsilon  > 0$, there is a neighbourhood of $b$ on which $ \n         norm( psi (f(x)))   <=   epsilon   norm(f(x) - b)  =  epsilon \n         norm( phi (x) +  lambda (x - a)) .\n    $  Apply the triangle inequality and find $M' > 0$ such that $ \n         norm( psi (f(x)))   <= \n         epsilon  norm( phi (x))  +  epsilon  M' norm(x - a) .\n    $  Thus, $ \n         lim _(x -> a)   frac( norm( psi (f(x))) ,  norm(x - a)  )   <= \n         lim _(x -> a)   frac( epsilon  norm( phi (x)) ,  norm(x - a)  )  +  epsilon \n        M' =  epsilon  M'.\n    $  Since $ epsilon  > 0$ was arbitrary, this limit is zero, completing the proof.\n] \n\n\n= Partial derivatives\n\n#definition[\n    Let $U  subset.eq  RR^n$ be open, and let $f: U -> RR$. The partial\n    derivative of $f$ with respect to the coordinate $x_j$ at some $a  in  U$\n    is defined by the following limit, if it exists. $ \n         pp(f, x_j) (a) =  lim _(h -> 0)   frac(f(a + h ve_j) - f(a), h)  .\n    $  \n]\n#lemma[\n    If $f: U -> RR$ is differentiable at a point $a  in  RR^n$, then $ \n        Df(a)(x_1,  dots , x_n) = x_1 \\, pp(f, x_1) (a) +  dots  + x_n\n        \\, pp(f, x_n) (a).\n    $  \n]\n#example[\n    Consider $ \n        f: RR^2 -> RR,  quad  (x, y)  mapsto  cases(\n             (x y) \\/ (x^2 + y^2)\\, & \" if \"  (x, y)  !=  (0, 0),\n            0\\, & \" if \"  (x, y) = (0, 0).\n        )\n    $  Note that $f$ is not differentiable at $(0, 0)$; it is not even continuous\n    there. However, both partial derivatives of $f$ exist at $(0, 0)$.\n]\n\n#lemma[\n    If $f: RR^n -> RR^m$ is differentiable at $a  in  RR^n$, then the matrix\n    representation of $Df(a)$ in the standard basis is given by $ \n        [Df(a)] = [ pp(f_i, x_j) (a)]_(i j).\n    $  \n]\n\n#lemma[\n    Let $f: RR^n -> RR^m$ be differentiable at $a  in  RR^n$, and let $g: RR^m\n    -> RR^k$ be differentiable at $f(a)  in  RR^m$. Then, the matrix\n    representation of $D(g compose  f)(a)$ in the standard basis is the\n    product $ \n        [D(g compose  f)(a)] = [Dg(f(a))][Df(a)] = [ sum _( ell  = 1)^m\n         pp(g_i, y_ ell )  pp(f_ ell , x_j) ]_(i j).\n    $  In other words, $ \n         pp(, x_j) (g compose  f)_i(a) =  sum _( ell  = 1)^m  pp(g_i, y_ ell ) (f(a))\n         pp(f_ ell , x_j) (a).\n    $  \n]\n\n#example[\n    Let $f: RR^2-> RR$ be differentiable, and let $ Gamma (f) = {(x, y, f(x,\n    y)): x, y  in  RR}$ be the graph of $f$. Now, let $gamma : [-1, 1] ->\n    Gamma (f)$ be a differentiable curve, represented by $ \n         gamma (t) = (g(t), h(t), f(g(t), h(t))).\n    $  Then, we can compute the derivative $ \n         gamma '(a) = (g'(a), h'(a), lr(g'(a) pp(f, x)  + h'(a) pp(f, y) \n            \\|)_((g(a), h(a))))\n    $  \n]\n\n#exercise[\n    Consider the inner product map, $ ip( dot.c ,  dot.c ) : RR^n  times RR^n\n    -> RR$. What is its derivative?\n    #solution[\n        We treat the inner product as a map $g: RR^(2n) -> RR$, which acts\n        as $ \n             ip( vx ,  vy )  colon.eq g(x_1,  dots , x_n, y_1,  dots , y_n) = x_1y_1 +\n             dots  + x_n y_n.\n        $  Now, note that $ \n             pp(g, x_i)  = y_i,  quad   pp(g, y_i)  = x_i.\n        $  Thus, $\n            Dg( va ,  vb )( vx ,  vy ) &=  sum _(i = 1)^n x_i  pp(g, x_i) ( va ,  vb ) +\n             sum _(i = 1)^n y_i  pp(g, y_i) ( va ,  vb ) \\\n            &=  sum _(i = 1)^n x_i b_i +  sum _(i = 1)^n y_i a_i \\\n            &=  ip( vx ,  vb )  +  ip( vy ,  va ) .\n        $\n        In other words, the matrix representation of the derivative of the inner\n        product map at the point $( va ,  vb )$ is given by $[ vb^top\n         va^top]$.\n    ]\n]\n\n#exercise[\n    Let $gamma : RR -> RR^n$ be a differentiable curve. What is the\n    derivative of the real map $t  mapsto   norm( gamma (t)) ^2$?\n    #solution[\n        We write this map as $t  mapsto   ip( gamma (t),  gamma (t)) $. Consider the\n        scheme $\n            RR -> RR^(2n) -> RR, quad\n            t  mapsto  mat(\n                 gamma (t) ;  gamma (t)\n            )  mapsto   ip( gamma (t),  gamma (t)) .\n        $  Pick a point $t in  RR$, whence the derivative of the map at $t$ is $ \n            mat(\n                 gamma (t)^top ,  gamma (t)^top\n            ) mat(\n                 gamma '(t) ;  gamma '(t)\n            ) = 2 ip( gamma (t),  gamma '(t)) .\n        $\n    ]\n    #remark[\n        Consider the surface $S^(n - 1)  subset  RR^n$, and pick an arbitrary\n        differentiable curve $gamma : RR -> S^(n - 1)$. Now, the tangent\n        vector $gamma '(t)$ is tangent to the sphere $S^(n - 1)$ at any point\n        $gamma (t)$. We claim that this tangent drawn at $ gamma (t)$ is always\n        perpendicular to the position vector $ gamma (t)$. This is made trivial by\n        our exercise: the map $t  mapsto   norm( gamma (t)) ^2 = 1$ is a constant\n        map since $gamma$ is a curve on the unit sphere. This means that it has\n        zero derivative, forcing $ ip( gamma (t),  gamma '(t))  = 0$.\n    ]\n]\n\n== Directional derivatives\n\n#definition[\n    Let $U  subset.eq  RR^n$ be open, and let $f: U -> RR$. The directional\n    derivative of $f$ along a direction $ vv   in  RR^n$ at a point $a  in  U$ is\n    defined by the following limit, if it exists. $ \n         nabla _v f(a) =  lim _(h -> 0)   frac(f(a + h vv ) - f(a), h)  .\n    $  \n]\n\n#example[\n    Consider $ \n        f: RR^2 -> RR,  quad  (x, y)  mapsto  cases(\n            x^3\\/(x^2 + y^2)\\, & \" if \"  (x, y)  !=  (0, 0),\n            0\\, & \" if \"  (x, y) = (0, 0).\n        )\n    $  Note that $f$ is not differentiable at $(0, 0)$. However, all\n    directional derivatives derivatives of $f$ exist at $(0, 0)$. Indeed,\n    consider a direction $( cos  theta , sin theta )$, and examine the limit\n    $ \n         lim_(t -> 0)   frac(1, t)  [f(t cos  theta , t sin theta ) - f(0,\n        0)] =  cos ^3 theta .\n    $  \n]\n\n#definition[\n    Let $f: RR^n -> RR$ be differentiable. The gradient of $f$ is defined\n    as the map $ \n         grad(f) : RR^n -> RR^n,  quad  x  mapsto \n        [ pp(f, x_i) (x)]_i.\n    $  \n    #remark[\n        The gradient at a point $x  in  RR^n$ is thought of as a vector. In\n        contrast, the derivative is thought of as a linear transformation.\n        Otherwise, we see that $ grad(f) (x) = [Df(x)]$.\n    ]\n]\n\n#definition[\n    Let $C^1(RR^n)$ be the set of real-valued differentiable functions on $RR^n$.\n    Fix a point $a  in  RR^n$, then fix a tangent vector $v  in  RR^n$. Then, the\n    map $ \n         nabla _v: C^1(RR^n) -> RR,  quad  f mapsto  Df(a)(v)\n    $  is a linear functional. The quantity $ nabla _v f$ is called the\n    directional derivative of $f$ in the direction $v$ at the point $a$.\n    #remark[\n        We can represent $ nabla _v$ as the operator $ \n             nabla _v ( dot.c ) = D( dot.c )(a)(v) =  sum _i v_i  lr(pp(, x_i)\\|)_a =\n            v dot.c   nabla  ( dot.c ).\n        $ \n    ]\n]\n\n#lemma[\n    The directional derivatives $ nabla _v$ form a vector space called the tangent\n    space, attached to the point $a  in  RR^n$. This can be identified with the\n    vector space $RR^n$ by the natural map $ nabla _v  mapsto  v$. The standard\n    basis can be informally denoted by the vectors $ \n         nabla_( ve _1) colon.eq  pp(, x_1) ,  quad dots quad,  nabla _( ve _n) colon.eq  pp(, x_n) .\n    $  \n]\n\n\n== Differentiation on manifolds \\*\n\n#definition[\n    A homeomorphism is a continuous, bijective map whose inverse is also continuous.\n]\n\n#lemma[\n    Let $f: RR^n -> RR$ be continuous. Denote the graph of $f$ as $ \n         Gamma (f) = \\{(x, f(x)): x  in  RR^n\\}.\n    $  Then, $ Gamma (f)$ is a smooth manifold.\n]\n#proof[\n    Consider the homeomorphism $ \n         phi :  Gamma (f) -> RR^n,  quad  (x, f(x))  mapsto  x.\n    $  This is clearly bijective, continuous (restriction of a projection map),\n    with a continuous inverse (from the continuity of $f$). Call this\n    homeomorphism $phi$ a coordinate map on $Gamma (f)$.\n]\n\n#definition[\n    Let $f: M -> RR$ where $M$ is a smooth manifold, with a coordinate map\n    $phi : M -> RR^n$. We say that $f$ is differentiable at a point $a\n     in  M$ if $f compose   phi ^(-1): RR^n -> RR$ is differentiable at\n    $ phi (a)$.\n]\n\n#definition[\n    Let $f: M -> RR$ where $M$ is a smooth manifold, let $ phi : M\n    -> RR^n$ be a coordinate map, and let $a  in  M$. Let $gamma : RR -> M$\n    be a curve such that $ gamma (0) = a$, and further let $gamma$ be\n    differentiable in the sense that $phi  compose   gamma : RR -> RR^n$ is\n    differentiable. The directional derivative of $f$ at $a$ along $gamma$ is\n    defined as $ \n         dd(, t)  f( gamma (t)) \\|_ (t = 0) =  lim _(h -> 0) lr(frac(f( gamma (t +\n        h)) - f( gamma (t)), h) \\|)_ (t = 0).\n    $  Note that we are taking the derivative of $f compose   gamma : RR -> RR$\n    in the conventional sense.\n]\n\n#lemma[\n    Let $ gamma _1$ and $gamma _2$ be two curves in $M$ such that $gamma_1(0) =\n     gamma _2(0) = a$, and $ \n         dd(, t) lr( phi  compose  gamma _1(t) \\|)_ (t = 0) \n         = dd(, t)  lr( phi  compose  gamma _2(t)  \\|)_ (t = 0).\n    $  In other words, $gamma _1$ and $ gamma _2$ pass through the same point $a$\n    at $t = 0$, and have the same velocities there. Then, the directional\n    derivatives of $f$ at $a$ along $gamma _1$ and $ gamma _2$ are the same.\n]\n\n#definition[\n    Let $M$ be a smooth manifold, and let $a  in  M$. Consider the following\n    equivalence relation on the set of all curves $gamma$ in $M$ such that\n    $gamma (0) = a$. $ \n         gamma_1 tilde.op gamma_2  quad arrow.r.double.long quad\n         dd(, t) lr( phi  compose gamma _1(t)  \\|)_ (t = 0) \n         = dd(, t) lr( phi  compose   gamma _2(t) \\|)_ (t = 0).\n    $ Each resultant equivalence class of curves is called a tangent vector at\n    $a  in  M$. Note that all these curves in a particular equivalence class pass\n    through $a$ with the same velocity vector.\n\n    The collection of all such tangent vectors, i.e. the space of all curves\n    through $a$ modulo the equivalence relation which identifies curves with the\n    same velocity vector through $a$, is called the tangent space to $M$ at $a$,\n    denoted $T_a M$.\n\n    #remark[\n        Each tangent vector $v in  T_a M$ acts on a differentiable function\n        $f: M -> RR$ yielding a (well-defined) directional derivative at\n        $a$. $ \n            v: C^1(M) -> RR,  quad  f mapsto   dd(, t) \n            lr(f( gamma _v(t)) \\|)_ (t = 0).\n        $ \n        Thus, the tangent space represents all the directions in which taking a\n        derivative of $f$ makes sense.\n    ]\n    #remark[\n        The tangent space $T_a M$ is a vector space. Upon fixing $f$, the map\n        $Df(a): T_a M -> RR$, $v  mapsto  v f(a)$ is a linear functional on\n        the tangent space.\n    ]\n    #remark[\n        Given a tangent vector $v  in  T_a M$, it can be identified with its\n        corresponding velocity vector in $RR^n$. Thus, the tangent space $T_a M$\n        can be identified with the geometric tangent plane drawn to the manifold\n        $M$ at the point $a$.\n    ]\n]\n\n\n= Mean value theorem\nConsider a differentiable function $f: RR^n -> RR$, and fix $a  in  RR^n$.\nDefine the functions $ \n    g_i: RR -> RR,  quad  g_i(x) = f(a_1,  dots , a_(i - 1), x, a_(i + 1),\n     dots , a_n).\n$  Then, each $g_i$ is differentiable, with $ \n    g_i'(x) =  pp(f, x_i) (a_1,  dots , a_(i - 1), x, a_(i + 1),  dots , a_n).\n$  By applying the Mean Value Theorem on some interval $[c, d]$, we can find\n$ alpha  in  (c, d)$ such that $g_i(d) - g_i(c) = g_i'( alpha )(d - c)$. In other\nwords,\n$ \n    f( dots , d,  dots ) - f( dots , c,  dots ) =  pp(f, x_i) ( dots ,  alpha ,  dots )(d\n    - c).\n$\n\n#theorem[\n    Let $f: RR^n -> RR^m$ and $a  in  RR^n$. Then, $f$ is differentiable at\n    $a$ if all the partial derivatives $diff  f\\/diff  x_j$ exist in a\n    neighbourhood of $a$ and are continuous at $a$.\n]\n#proof[\n    Without loss of generality, let $m = 1$. We claim that $ \n         lim _(h -> 0)     frac(1,  norm(h)  )  norm(f(a + h) - f(a) -  sum _(i = 0) ^n\n         pp(f, x_i) (a)h_i) = 0.\n    $  Examine $\n        f(a + h) - f(a) &= f(a_1 + h_1,  dots , a_n + h_n) - f(a_1,  dots ,\n        a_n) \\\n        &= f(a_1 + h_1,  dots , a_n + h_n) - f(a_1 + h_1,  dots , a_(n - 1) +\n        h_(n - 1), a_n) + \\\n        &   quad  f(a_1 + h_1,  dots , a_(n - 1) + h_(n - 1), a_n) - f(a_1 + h_1,\n         dots , a_(n - 1), a_n) + \\\n        &   quad   dots.h  \\\n        &   quad  f(a_1 + h_1, a_2,  dots , a_n) - f(a_1,  dots , a_n) \\\n        &=  pp(f, x_n) (c_n)h_n +  dots  +  pp(f, x_1) (c_1)h_1.\n    $\n    The last step follows from the Mean Value Theorem. As $h -> 0$, each $c_i\n    -> a$. Thus, $\n          frac(1,  norm(h))  norm(f(a + h) - f(a) -  sum _(i = 0)^n\n         pp(f, x_i) (a)h_i) \n        &=   frac(1,  norm(h))  norm( sum _(i = 0) ^n (pp(f, x_i)(c_i) -\n         pp(f, x_i) (a))h_i) \\\n        & <=   sum _(i = 0)^n | pp(f, x_i) (c_i) -  pp(f, x_i) (a) |\n          frac(|h_i|,  norm(h)  )  \\\n        & <=   sum _(i = 0)^n | pp(f, x_i) (c_i) -  pp(f, x_i) (a) |.\n    $\n    Taking the limit $h -> 0$, observe that $(diff  f\\/diff  x_i) (c_i) ->\n    (diff  f \\/ diff  x_i) (a)$ by the continuity of the partial derivatives,\n    completing the proof.\n]\n\n#corollary[\n    All polynomial functions on $RR^n$ are differentiable.\n]\n\n#theorem[\n    Let $f: RR^n -> RR$ be differentiable with continuous partial\n    derivatives, and let $a  in  RR^n$ be a point of local maximum. Then, $Df(a) =\n    0$.\n]\n#proof[\n    We need only show that each $ \n         pp(f, x_i) (a) = 0.\n    $  This must be true, since $a$ is also a local maximum of each of the\n    restrictions $g_i$ as defined earlier.\n]\n\n= Inverse and implicit function theorems\n#theorem([Inverse function theorem])[\n    Let $f: RR^n -> RR^n$ be continuously differentiable on a neighbourhood\n    of $a  in  RR^n$, and let $\"det\" (Df(a))  !=  0$. Then, there exist neighbourhoods\n    $U$ of $a$ and $W$ of $f(a)$ such that the restriction $f: U -> W$ is\n    invertible. Furthermore, $f^(-1)$ is continuous on $U$ and differentiable on\n    $U$.\n]\n\n#lemma[\n    Consider a continuously differentiable function $f: RR^n -> RR$, and\n    let $M$ denote the surface defined by the zero set of $f$. Then, $M$ can be\n    represented as the graph of a differentiable function $h: RR^(n - 1) ->\n    RR$ at those points where $Df  !=  0$.\n]\n#proof[\n    Without loss of generality, suppose that $diff  f \\/ diff  x_n  !=  0$\n    at some point $a  in  M$. It can be shown that the map $ \n        F: RR^n -> RR^n ,  quad  x  mapsto  (x_1, x_2,  dots , x_(n - 1),\n        f(x))\n    $  is invertible in a neighbourhood $W$ of $a$, with a continuous and\n    differentiable inverse of the form\n    $ \n        G: RR^n -> RR^n,  quad  u  mapsto  (u_1, u_2,  dots , u_(n - 1),\n        g(u)).\n    $\n    Since $F compose G$ must be the identity map on $W$, we demand $ \n        (x_1, x_2,  dots , x_(n - 1), f(x_1, x_2,  dots , x_(n - 1), g(x))) = (x_1,\n        x_2,  dots , x_(n - 1), x_n).\n    $  Thus, the zero set of $f$ in this neighbourhood of $a$ satisfies $x_n =\n    0$, hence $ \n        f(x_1, x_2,  dots , x_(n - 1), g(x_1, x_2,  dots , x_(n - 1), 0)) = 0.\n    $  In other words, the part of the surface $M$ in the neighbourhood of $a$ is\n    precisely the set of points $ \n        (x_1, x_2,  dots , x_(n - 1), g(x_1, x_2,  dots , x_(n - 1), 0)).\n    $  Simply set $ \n        h: RR^(n - 1) -> RR,  quad  x  mapsto  g(x_1, x_2,  dots , x_(n - 1),\n        0),\n    $  whence the surface $M$ is locally represented by the graph of $h$.\n]\n\n#block(inset: 1em)[\n#remark()[\n    Note that by using $ \n        f(x_1,  dots , x_(n - 1), h(x_1,  dots , x_(n - 1))) = 0\n    $  on the surface, we can use the chain rule to conclude that for all $1  <= \n    i < n$, we have $ \n         pp(f, x_i) (a) +  pp(f, x_n) (a) pp(h, x_i) (a_1,  dots , a_(n - 1)) = 0.\n    $  \n]\n]\n\n#theorem([Implicit function theorem])[\n    Let $f: RR^n times RR^m -> RR^m$ be continuously differentiable in an open\n    set containing $(a, b)$, with $f(a, b) = 0$. Let $\"det\" (diff  f^j \\/ diff\n    x_(n + k) (a, b))  !=  0$. Then, there exists an open set $U  subset RR^n$\n    containing $a$, an open set $V  subset  RR^m$ containing $b$, and a\n    differentiable function $g: U -> V$ such that $f(x, g(x)) = 0$.\n\n    #remark[\n        The condition on the determinant can be rephrased as\n        $\"rank\" Df(a, b) = m$.\n    ]\n]\n\n#theorem[\n    Let $f: RR^n -> RR$ be continuously differentiable, and let $M$ be the\n    surface defined by its zero set. Furthermore, let $ grad(f) (a)  !=  0$ for\n    some $a  in  M$; thus, $M$ can be locally represented by a graph on $RR^(n\n    - 1)$. Then, $ grad(f) (a)$ is normal to the tangent vectors drawn at $a$\n    to $M$; in fact, the perpendicular space of $ grad(f) (a)$ is precisely\n    the tangent space $T_a M$.\n]\n#proof[\n    Consider a tangent vector drawn at $a$ to $M$, represented by the\n    differentiable curve $gamma : RR -> M$, $ gamma (0) = a$; note that\n    we use the identification $gamma '(0) = v  in  RR^n$. Then, calculate $ \n         dd(, t) lr(f( gamma (t))  \\|)_ (t = 0) = Df( gamma (0))( gamma '(0))\n         = Df(a)(v).\n    $  On the other hand, we have $f( gamma (t)) = 0$ identically. Thus, $ \n        v dot.c   grad(f) (a) = Df(a)(v) = 0\n    $ as claimed.\n]\n\n= Taylor's theorem\n\n#theorem(\"Clairaut\")[\n    Let $f: RR^n -> RR$ have continuous second order partial derivatives.\n    Then, $ \n          frac(diff ^2 f, diff  x_i diff  x_j)   = frac(diff ^2\n        f, diff  x_j diff  x_i).\n    $\n]\n\n#theorem(\"Taylor\")[\n    Let $f: RR^2 -> RR$ have continuous second order partial derivatives,\n    and let $(x_0, y_0)  in  RR^2$. Then, there exists $ epsilon  > 0$ such that\n    for all $norm((x - x_0, y - y_0))  <  epsilon$,\n    $\n        f(x, y)   =   &f(x_0, y_0) +  pp(f, x) (x - x_0) +  pp(f, y) (y - y_0) \\\n        & + space frac(1, 2)  frac(diff^2 f, diff x^2)(x - x_0)^2 + frac(1, 2)\n        frac(diff^2 f, diff y^2)(y - y_0)^2 \\\n        & + space frac(diff ^2 f, diff  x diff  y)  (x - x_0)(y - x_0) + R(x,\n        y),\n    $\n    where as $(x, y) -> (x_0, y_0)$, the remainder term vanishes as $ \n          frac(|R(x, y)|,  norm((x - x_0, y - y_0) ) ^2)  -> 0.\n    $  All partial derivatives here are evaluated at $(x_0, y_0)$.\n]\n#proof[\n    This follows from applying the Taylor's Theorem in one variable to the real\n    function $g: RR -> RR$, $t  mapsto  f((1 - t)(x_0, y_0) + t(x, y))$.\n]\n\n\n= Critical points and extrema\n#definition[\n    We say that $a  in  RR^n$ is a critical point of $f: RR^n -> RR$ if all\n    $diff  f \\/ diff  x^j = 0$ there.\n]\n\n#lemma[\n    All points of extrema of a differentiable function are critical points.\n]\n#proof[\n    We already know that $Df(a) = 0$ where $a$ is either a point of maximum or\n    minimum.\n]\n\n#example[\n    In order to find a point of extrema of a $C^2$-smooth function $f: RR^2\n    -> RR$, we first identify a critical point $(x_0, y_0)$. Next, we must find\n    a neighbourhood of $(x_0, y_0)$ which contains no other critical points -- to\n    do this, apply Taylor's Theorem. Indeed, we see that $ \n        f(x, y) = f(x_0, y_0) + A(x - x_0)^2 + 2B(x - x_0)(y - y_0) + C(y -\n        y_0)^2 + R_2.\n    $  For non-degeneracy of solutions, we demand $A C - B^2  !=  0$, i.e. at\n    $(x_0, y_0)$, we want $ \n        [  frac(diff ^2 f, diff  x diff  y)  ]^2  != \n          frac(diff ^2 f, diff  x^2)  \n          frac(diff ^2 f, diff  y^2)  .\n    $  \n\n    If $A C - B^2 > 0$ and $diff ^2f \\/ diff  x^2 > 0$, then we have found a\n    point of minima; if $diff ^2 f \\/ diff  x^2 < 0$, then we have found a\n    point of maximum. If $A C - B^2 < 0$, then we have found a saddle point.\n]\n\n#example[\n    Suppose that we wish to maximize the function $f: RR^2 -> RR$, given an\n    equation of constraint $g = 0$, where $g: RR^2 -> RR$. Using the method\n    of Lagrange multipliers, we look for solutions of the system $ \n        cases(\n            grad(f) (x, y) +  lambda   grad(&g) (x, y) &= 0,\n            &g(x, y) &= 0.\n        )\n    $\n]\n"
  },
  {
    "path": "manual.typ",
    "content": "#import \"manual_template.typ\": *\n#import \"theorems.typ\": *\n#show: thmrules\n\n#show: project.with(\n  title: \"typst-theorems\",\n  authors: (\n    \"sahasatvik\",\n  ),\n  url: \"https://github.com/sahasatvik/typst-theorems\"\n)\n\n\n\n= Introduction\n\nThe `typst-theorems` package provides `Typst` functions that help create\nnumbered `theorem` environments. This is heavily inspired by the `\\newtheorem`\nfunctionality of `LaTeX`.\n\nA _theorem environment_ lets you wrap content together with automatically\nupdating _numbering_ information. Such environments use internal `state`\ncounters for this purpose. Environments can\n\n- share the same counter (_Theorems_ and _Lemmas_ often do so)\n- keep a global count, or be attached to\n  - other environments (_Corollaries_ are often numbered based upon the parent _Theorem_)\n  - headings\n- have a numbering level depth fixed (for instance, use only top level heading\n  numbers)\n- be referenced elsewhere in the document, via `label`s\n\n\n= Using `typst-theorems`\n\nImport all functions provided by `typst-theorems` using\n```typst\n#import \"theorems.typ\": *\n#show: thmrules\n```\nThe second line is crucial for displaying `thmenv`s and references correctly!\n\nThe core of this module consists of `thmenv`.\nThe functions `thmbox`, `thmplain`, and `thmproof` provide some simple\ndefaults for the appearance of `thmenv`s.\n\n\n= Feature demonstration <feat>\n\nCreate box-like _theorem environments_ using `thmbox`, a wrapper around\n`thmenv` which provides some simple defaults.\n\n```typst\n#let theorem = thmbox(\n  \"theorem\",              // identifier\n  \"Theorem\",              // head\n  fill: rgb(\"#e8e8f8\")\n)\n```\n#let theorem = thmbox(\n  \"theorem\",\n  \"Theorem\",\n  fill: rgb(\"#e8e8f8\")\n)\n\nSuch definitions are convenient to place in the preamble or a template; use\nthe environment in your document via\n```typst\n#theorem(\"Euclid\")[\n  There are infinitely many primes.\n] <euclid>\n```\n\nThis produces the following.\n#theorem(\"Euclid\")[\n  There are infinitely many primes.\n] <euclid>\n\nNote that the `name` is optional. This `theorem` environment will be numbered\nbased on its parent `heading` counter, with successive `theorem`s\nautomatically updating the final index.\n\nThe `<euclid>` label can be used to refer to this Theorem via the reference\n`@euclid`. Go to @references to read more.\n\nYou can create another environment which uses the same counter, say for\n_Lemmas_, as follows.\n\n```typst\n#let lemma = thmbox(\n  \"theorem\",              // identifier - same as that of theorem\n  \"Lemma\",                // head\n  fill: rgb(\"#efe6ff\")\n)\n\n#lemma[\n  If $n$ divides both $x$ and $y$, it also divides $x - y$.\n]\n```\n#let lemma = thmbox(\n  \"theorem\",\n  \"Lemma\",\n  fill: rgb(\"#efe6ff\")\n)\n#lemma[\n  If $n$ divides both $x$ and $y$, it also divides $x - y$.\n]\n\nYou can _attach_ other environments to ones defined earlier. For instance,\n_Corollaries_ can be created as follows.\n\n```typst\n#let corollary = thmbox(\n  \"corollary\",            // identifier\n  \"Corollary\",            // head\n  base: \"theorem\",        // base - use the theorem counter\n  fill: rgb(\"#f8e8e8\")\n)\n\n#corollary(numbering: \"1.1\")[\n  If $n$ divides two consecutive natural numbers, then $n = 1$.\n]\n```\n#let corollary = thmbox(\n  \"corollary\",\n  \"Corollary\",\n  base: \"theorem\",\n  fill: rgb(\"#f8e8e8\")\n)\n\n#corollary(numbering: \"1.1\")[\n  If $n$ divides two consecutive natural numbers, then $n = 1$.\n]\n\nNote that we have provided a `numbering` string; this can be any valid\nnumbering pattern as described in the\n#link(\"https://typst.app/docs/reference/meta/numbering/\")[numbering]\ndocumentation.\n\n\n== Proofs\n\nThe `thmproof` function gives nicer defaults for formatting proofs.\n```typst\n#let proof = thmproof(\"proof\", \"Proof\")\n\n#proof([of @euclid])[\n  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration\n  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,\n  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since\n  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a\n  contradiction.\n]\n```\n#let proof = thmproof(\"proof\", \"Proof\")\n\n#proof([of @euclid])[\n  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration\n  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,\n  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since\n  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a\n  contradiction.\n]\n\nIf your proof ends in a block equation, or a list/enum, you can place\n`qedhere` to correctly position the qed symbol.\n```typst\n#theorem[\n  There are arbitrarily long stretches of composite numbers.\n]\n#proof[\n  For any $n > 2$, consider $\n    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere\n  $\n]\n```\n#theorem[\n  There are arbitrarily long stretches of composite numbers.\n]\n#proof[\n  For any $n > 2$, consider $\n    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere\n  $\n]\n\n*Caution*: The `qedhere` symbol does not play well with numbered/multiline\nequations!\n\nYou can set a custom qed symbol (say $square$) by setting the appropriate\noption in `thmrules` as follows.\n```typst\n#show: thmrules.with(qed-symbol: $square$)\n```\n\n== Suppressing numbering\nSupplying `numbering: none` to an environment suppresses numbering for that\nblock, and prevents it from updating its counter.\n\n```typst\n#let example = thmplain(\n  \"example\",\n  \"Example\"\n).with(numbering: none)\n\n#example[\n  The numbers $2$, $3$, and $17$ are prime.\n]\n```\n#let example = thmplain(\n  \"example\",\n  \"Example\"\n).with(numbering: none)\n\n#example[\n  The numbers $2$, $3$, and $17$ are prime.\n]\n\nHere, we have used the `thmplain` function, which is identical to `thmbox` but\nsets some plainer defaults. You can also write\n```typst\n#lemma(numbering: none)[\n  The square of any even number is divisible by $4$.\n]\n#lemma[\n  The square of any odd number is one more than a multiple of $4$.\n]\n```\n#lemma(numbering: none)[\n  The square of any even number is divisible by $4$.\n]\n#lemma[\n  The square of any odd number is one more than a multiple of $4$.\n]\n\nNote that the last _Lemma_ is _not_ numbered 3.1.2!\n\nYou can also override the automatic numbering as follows.\n```typst\n#lemma(number: \"42\")[\n  The square of any natural number cannot be two more than a multiple of 4.\n]\n```\n#lemma(number: \"42\")[\n  The square of any natural number cannot be two more than a multiple of 4.\n]\n\nNote that this does _not_ affect the counters either!\n\n\n== Limiting depth\n\nYou can limit the number of levels of the `base` numbering used as follows.\n```typst\n#let definition = thmbox(\n  \"definition\",\n  \"Definition\",\n  base_level: 1,          // take only the first level from the base\n  stroke: rgb(\"#68ff68\") + 1pt\n)\n\n#definition(\"Prime numbers\")[\n  A natural number is called a _prime number_ if it is greater than $1$ and\n  cannot be written as the product of two smaller natural numbers. <prime>\n]\n```\n#let definition = thmbox(\n  \"definition\",\n  \"Definition\",\n  base_level: 1,\n  stroke: rgb(\"#68ff68\") + 1pt\n)\n#definition(\"Prime numbers\")[\n  A natural number is called a _prime number_ if it is greater than $1$ and\n  cannot be written as the product of two smaller natural numbers. <prime>\n]\n\nNote that this environment is _not_ numbered 3.2.1!\n\n```typst\n#definition(\"Composite numbers\")[\n  A natural number is called a _composite number_ if it is greater than $1$\n  and not prime.\n]\n```\n#definition(\"Composite numbers\")[\n  A natural number is called a _composite number_ if it is greater than $1$\n  and not prime.\n]\n\nSetting a `base_level` higher than what `base` provides will introduce padded\nzeroes.\n\n```typst\n#example(base_level: 4, numbering: \"1.1\")[\n  The numbers $4$, $6$, and $42$ are composite.\n]\n```\n#example(base_level: 4, numbering: \"1.1\")[\n  The numbers $4$, $6$, and $42$ are composite.\n]\n\n\n== Custom formatting\nThe `thmbox` function lets you specify rules for formatting the `title`, the\n`name`, and the `body` individually. Here, the `title` refers to the `head`\nand `number` together.\n\n```typst\n#let proof-custom = thmplain(\n  \"proof\",\n  \"Proof\",\n  base: \"theorem\",\n  titlefmt: smallcaps,\n  bodyfmt: body => [\n    #body #h(1fr) $square$    // float a QED symbol to the right\n  ]\n).with(numbering: none)\n\n#lemma[\n  All even natural numbers greater than 2 are composite.\n]\n#proof-custom[\n  Every even natural number $n$ can be written as the product of the natural\n  numbers $2$ and $n\\/2$. When $n > 2$, both of these are smaller than $2$\n  itself.\n]\n```\n#let proof-custom = thmplain(\n  \"proof\",\n  \"Proof\",\n  base: \"theorem\",\n  titlefmt: smallcaps,\n  bodyfmt: body => [\n    #body #h(1fr) $square$\n  ]\n).with(numbering: none)\n\n#lemma[\n  All even natural numbers greater than 2 are composite.\n]\n#proof-custom[\n  Every even natural number $n$ can be written as the product of the natural\n  numbers $2$ and $n\\/2$. When $n > 2$, both of these are smaller than $2$\n  itself.\n]\n\nYou can go even further and use the `thmenv` function directly. It accepts an\n`identifier`, a `base`, a `base_level`, and a `fmt` function.\n```typst\n#let notation = thmenv(\n  \"notation\",                 // identifier\n  none,                       // base - do not attach, count globally\n  none,                       // base_level - use the base as-is\n  (name, number, body, color: black) => [\n                              // fmt - format content using the environment\n                              // name, number, body, and an optional color\n    #text(color)[#h(1.2em) *Notation (#number) #name*]:\n    #h(0.2em)\n    #body\n    #v(0.5em)\n  ]\n).with(numbering: \"I\")        // use Roman numerals\n\n#notation[\n  The variable $p$ is reserved for prime numbers.\n]\n#notation(\"for Reals\", color: green)[\n  The variable $x$ is reserved for real numbers.\n]\n```\n#let notation = thmenv(\n  \"notation\",                 // identifier\n  none,                       // base - do not attach, count globally\n  none,                       // base_level - use the base as-is\n  (name, number, body, color: black) => [\n                              // fmt - format content using the environment name, number, body, and an optional color\n    #text(color)[#h(1.2em) *Notation (#number) #name*]:\n    #h(0.2em)\n    #body\n    #v(0.5em)\n  ]\n).with(numbering: \"I\")        // use Roman numerals\n\n#notation[\n  The variable $p$ is reserved for prime numbers.\n]\n#notation(\"for Reals\", color: green)[\n  The variable $x$ is reserved for real numbers.\n]\n\nNote that the `color: green` named argument supplied to the theorem\nenvironment gets passed to the `fmt` function. In general, all extra named\narguments supplied to the theorem will be passed to `fmt`.\nOn the other hand, the positional argument `\"for Reals\"` will always be\ninterpreted as the `name` argument in `fmt`.\n\n```typst\n#lemma(title: \"Lem.\", stroke: 1pt)[\n  All multiples of 3 greater than 3 are composite.\n]\n```\n#lemma(title: \"Lem.\", stroke: 1pt)[\n  All multiples of 3 greater than 3 are composite.\n]\n\nHere, we override the `title` (which defaults to the `head`) as well as the\n`stroke` in the `fmt` produced by `thmbox`. All `block` arguments can be\noverridden in `thmbox` environments in this way.\n\n\n== Labels and references <references>\n\nYou can place a `<label>` outside a theorem environment, and reference it\nlater via `@` references! For example, go back to @euclid.\n\n```typst\nRecall that there are infinitely many prime numbers via @euclid.\n```\n#pad(\n  left: 1.2em,\n  [\n    Recall that there are infinitely many prime numbers via @euclid.\n  ]\n)\n\n\n```typst\nYou can reference future environments too, like @oddprime[Cor.].\n```\n#pad(\n  left: 1.2em,\n  [\n    You can reference future environments too, like @oddprime[Cor.].\n  ]\n)\n\n```typst\n#lemma(supplement: \"Lem.\", refnumbering: \"(1.1)\")[\n  All primes apart from $2$ and $3$ are of the form $6k plus.minus 1$.\n] <primeform>\n\nYou can modify the supplement and numbering to be used in references, like @primeform.\n```\n#lemma(supplement: \"Lem.\", refnumbering: \"(1.1)\")[\n  All primes apart from $2$ and $3$ are of the form $6k plus.minus 1$.\n] <primeform>\n\nYou can modify the supplement and numbering to be used in references, like @primeform.\n\n*Caution*: Links created by references to `thmenv`s will be styled according\nto `#show link:` rules.\n\n\n== Overriding `base`\n\n```typst\n#let remark = thmplain(\"remark\", \"Remark\", base: \"heading\")\n#remark[\n  There are infinitely many composite numbers.\n]\n\n#corollary[\n  All primes greater than $2$ are odd.\n] <oddprime>\n#remark(base: \"corollary\")[\n  Two is a _lone prime_.\n]\n```\n\n#let remark = thmplain(\"remark\", \"Remark\", base: \"heading\")\n#remark[\n  There are infinitely many composite numbers.\n]\n#corollary[\n  All primes greater than $2$ are odd.\n] <oddprime>\n#remark(base: \"corollary\")[\n  Two is a _lone prime_.\n]\n\nThis `remark` environment, which would normally be attached to the current\n_heading_, now uses the `corollary` as a base.\n\n\n#v(4em)\n\n= Function reference\n== `thmenv`\n\nThe `thmenv` function produces a _theorem environment_.\n```typst\n#let thmenv(\n  identifier,             // environment counter name\n  base,                   // base counter name, can be \"heading\" or none\n  base_level,             // number of base number levels to use\n  fmt                     // formatting function of the form\n                          // (name, number, body, ..args) -> content\n) = { ... }\n```\n\nThe `fmt` function must accept a theorem `name`, `number`, `body`, and produce\nformatted content. It may also accept additional positional arguments, via\n`args`.\n\nA _theorem environment_ is itself a map of the following form.\n```typst\n(\n  ..args,\n  body,                   // body content\n  number: auto,           // number, overrides numbering if present\n  numbering: \"1.1\",       // numbering style, can be a function\n  refnumbering: auto,     // numbering style used in references,\n                          // defaults to \"numbering\"\n  supplement: identifier, // supplement used in references\n  base: base,             // base counter name override\n  base_level: base_level  // base_level override\n) -> content\n```\n\nPositional arguments in `args` are as follows\n- `name`: The name of the theorem, typically displayed after the title.\n\nAll additional named arguments in `args` will be passed on to the associated\n`fmt` function supplied in `thmenv`.\n\n\n== `thmbox` and `thmplain`\n\nThe `thmbox` wraps `thmenv`, supplying a box-like `fmt` function.\n```typst\n#let thmbox(\n  identifier,             // identifier\n  head,                   // head - common name, used in the title\n  ..blockargs,            // named arguments, passed to #block\n  supplement: auto,       // supplement for references, defaults to \"head\"\n  padding: (top: 0.5em, bottom: 0.5em),\n                          // box padding, passed to #pad\n  namefmt: x => [(#x)],   // formatting for name\n  titlefmt: strong,       // formatting for title (head + number)\n  bodyfmt: x => x,        // formatting for body\n  separator: [#h(0.1em):#h(0.2em)],\n                          // separator inserted between name and body\n  base: \"heading\",        // base - defaults to using headings\n  base_level: none,       // base_level - defaults to using base as-is\n) = { ... }\n```\n\nThe `thmbox` function sets the following defaults for the `block`.\n```typst\n(\n  width: 100%,\n  inset: 1.2em,\n  radius: 0.3em,\n  breakable: false,\n)\n```\n\nThe `thmplain` function is identical to `thmbox`, except with plainer\ndefaults.\n\n```typst\n#let thmplain = thmbox.with(\n  padding: (top: 0em, bottom: 0em),\n  breakable: true,\n  inset: (top: 0em, left: 1.2em, right: 1.2em),\n  namefmt: name => emph([(#name)]),\n  titlefmt: emph,\n)\n```\n\n\n== `thmproof`, `proof-bodyfmt` and `qedhere`\n\nThe `thmproof` function is identical to `thmplain`, except with defaults\nappropriate for proofs.\n\n```typst\n#let thmproof(..args) = thmplain(\n    ..args,\n    namefmt: emph,\n    bodyfmt: proof-bodyfmt,\n    ..args.named()\n).with(numbering: none)\n```\n\nThe `proof-bodyfmt` function is a `bodyfmt` function that automatically places\na qed symbol at the end of the body.\n\nYou can place `#qedhere` inside a block equation, or at the end of a list/enum\nitem to place the qed symbol on the same line.\n\n\n== `thmrules`\n\nThe `thmrules` show rule sets important styling rules for theorem\nenvironments, references, and equations in proofs.\n\n```typst\n#let thmrules(\n  qed-symbol: $qed$,      // QED symbol used in proofs\n  doc\n) = { ... }\n```\n\n\n= Acknowledgements\n\nThanks to\n- #link(\"https://github.com/MJHutchinson\")[MJHutchinson] for suggesting and\n  implementing the `base_level` and `base: none` features,\n- #link(\"https://github.com/rmolinari\")[rmolinari] for suggesting and\n  implementing the `separator: ...` feature,\n- #link(\"https://github.com/DVDTSB\")[DVDTSB] for contributing\n  - the idea of passing named arguments from the theorem directly to the `fmt`\n    function.\n  - the `number: ...` override feature.\n  - the `title: ...` override feature in `thmbox`.\n- The awesome devs of #link(\"https://typst.app/\")[typst.app] for their\n  support.\n"
  },
  {
    "path": "manual_examples.typ",
    "content": "#import \"manual_template.typ\": *\n#import \"theorems.typ\": *\n#show: thmrules\n\n#show: project.with(\n  title: \"typst-theorems\",\n  authors: (\n    \"sahasatvik\",\n  ),\n  url: \"https://github.com/sahasatvik/typst-theorems\"\n)\n\n\n\n= Introduction\n\nThis document only includes the examples given in the manual; each one of\nthese has been explained in full detail there.\n\n\n= Feature demonstration\n\n#let theorem = thmbox(\n  \"theorem\",\n  \"Theorem\",\n  fill: rgb(\"#e8e8f8\")\n)\n\n#theorem(\"Euclid\")[\n  There are infinitely many primes.\n] <euclid>\n\n\n#let lemma = thmbox(\n  \"theorem\",\n  \"Lemma\",\n  fill: rgb(\"#efe6ff\")\n)\n\n#lemma[\n  If $n$ divides both $x$ and $y$, it also divides $x - y$.\n]\n\n#let corollary = thmbox(\n  \"corollary\",\n  \"Corollary\",\n  base: \"theorem\",\n  fill: rgb(\"#f8e8e8\")\n)\n\n#corollary(numbering: \"1.1\")[\n  If $n$ divides two consecutive natural numbers, then $n = 1$.\n]\n\n\n== Proofs\n\n#let proof = thmproof(\"proof\", \"Proof\")\n\n#proof([of @euclid])[\n  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration\n  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,\n  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since\n  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a\n  contradiction.\n]\n\n#theorem[\n  There are arbitrarily long stretches of composite numbers.\n]\n#proof[\n  For any $n > 2$, consider $\n    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere\n  $\n]\n\n\n== Suppressing numbering\n\n#let example = thmplain(\n  \"example\",\n  \"Example\"\n).with(numbering: none)\n\n#example[\n  The numbers $2$, $3$, and $17$ are prime.\n]\n\n#lemma(numbering: none)[\n  The square of any even number is divisible by $4$.\n]\n#lemma[\n  The square of any odd number is one more than a multiple of $4$.\n]\n\n#lemma(number: \"42\")[\n  The square of any natural number cannot be two more than a multiple of 4.\n]\n\n\n== Limiting depth\n\n#let definition = thmbox(\n  \"definition\",\n  \"Definition\",\n  base_level: 1,\n  stroke: rgb(\"#68ff68\") + 1pt\n)\n#definition(\"Prime numbers\")[\n  A natural number is called a _prime number_ if it is greater than $1$ and\n  cannot be written as the product of two smaller natural numbers. <prime>\n]\n\n#definition(\"Composite numbers\")[\n  A natural number is called a _composite number_ if it is greater than $1$\n  and not prime.\n]\n\n#example(base_level: 4, numbering: \"1.1\")[\n  The numbers $4$, $6$, and $42$ are composite.\n]\n\n\n== Custom formatting\n\n#let proof-custom = thmplain(\n  \"proof\",\n  \"Proof\",\n  base: \"theorem\",\n  titlefmt: smallcaps,\n  bodyfmt: body => [\n    #body #h(1fr) $square$\n  ]\n).with(numbering: none)\n\n#lemma[\n  All even natural numbers greater than 2 are composite.\n]\n#proof-custom[\n  Every even natural number $n$ can be written as the product of the natural\n  numbers $2$ and $n\\/2$. When $n > 2$, both of these are smaller than $2$\n  itself.\n]\n\n#let notation = thmenv(\n  \"notation\",                 // identifier\n  none,                       // base - do not attach, count globally\n  none,                       // base_level - use the base as-is\n  (name, number, body, color: black) => [\n                              // fmt - format content using the environment name, number, body, and an optional color\n    #text(color)[#h(1.2em) *Notation (#number) #name*]:\n    #h(0.2em)\n    #body\n    #v(0.5em)\n  ]\n).with(numbering: \"I\")        // use Roman numerals\n\n#notation[\n  The variable $p$ is reserved for prime numbers.\n]\n#notation(\"for Reals\", color: green)[\n  The variable $x$ is reserved for real numbers.\n]\n\n#lemma(title: \"Lem.\", stroke: 1pt)[\n  All multiples of 3 greater than 3 are composite.\n]\n\n\n== Labels and references <references>\n\n#pad(\n  left: 1.2em,\n  [\n    Recall that there are infinitely many prime numbers via @euclid.\n  ]\n)\n\n\n#pad(\n  left: 1.2em,\n  [\n    You can reference future environments too, like @oddprime[Cor.].\n  ]\n)\n\n#lemma(supplement: \"Lem.\", refnumbering: \"(1.1)\")[\n  All primes apart from $2$ and $3$ are of the form $6k plus.minus 1$.\n] <primeform>\n\nYou can modify the supplement and numbering to be used in references, like @primeform.\n\n\n== Overriding `base`\n\n\n#let remark = thmplain(\"remark\", \"Remark\", base: \"heading\")\n#remark[\n  There are infinitely many composite numbers.\n]\n#corollary[\n  All primes greater than $2$ are odd.\n] <oddprime>\n#remark(base: \"corollary\")[\n  Two is a _lone prime_.\n]\n"
  },
  {
    "path": "manual_template.typ",
    "content": "#let project(title: \"\", authors: (), url: \"\", body) = {\n  set page(paper: \"a4\", numbering: \"1\", number-align: center)\n  set document(author: authors, title: title)\n  set text(font: \"Libertinus Serif\", lang: \"en\")\n  set heading(numbering: \"1.1.\")\n  set par(justify: true)\n  set list(marker: ([•], [--]))\n  show heading: it => pad(bottom: 0.5em, it)\n  show raw.where(block: true): it => pad(left: 4em, it)\n  show link: it => underline(text(fill: blue, it))\n\n\n\n  align(center)[\n    #block(text(weight: 700, 1.75em, title))\n  ]\n\n  pad(\n    top: 0.5em,\n    bottom: 2em,\n    x: 2em,\n    grid(\n      columns: (1fr,) * calc.min(3, authors.len()),\n      gutter: 1em,\n      ..authors.map(author => align(center)[\n        #author \\\n        #link(url)\n      ]),\n    ),\n  )\n\n  outline(indent: true)\n\n  v(2em)\n\n  body\n}\n"
  },
  {
    "path": "theorems.typ",
    "content": "// Store theorem environment numbering\n\n#let thmcounters = state(\"thm\",\n  (\n    \"counters\": (\"heading\": ()),\n    \"latest\": ()\n  )\n)\n\n\n#let thmenv(identifier, base, base_level, fmt) = {\n\n  let global_numbering = numbering\n\n  return (\n    ..args,\n    body,\n    number: auto,\n    numbering: \"1.1\",\n    refnumbering: auto,\n    supplement: identifier,\n    base: base,\n    base_level: base_level\n  ) => {\n    let name = none\n    if args != none and args.pos().len() > 0 {\n      name = args.pos().first()\n    }\n    if refnumbering == auto {\n      refnumbering = numbering\n    }\n    let result = none\n    if number == auto and numbering == none {\n      number = none\n    }\n    if number == auto and numbering != none {\n      result = context {\n        let heading-counter = counter(heading).get()\n        return thmcounters.update(thmpair => {\n          let counters = thmpair.at(\"counters\")\n          // Manually update heading counter\n          counters.at(\"heading\") = heading-counter\n          if not identifier in counters.keys() {\n            counters.insert(identifier, (0, ))\n          }\n\n          let tc = counters.at(identifier)\n          if base != none {\n            let bc = counters.at(base)\n\n            // Pad or chop the base count\n            if base_level != none {\n              if bc.len() < base_level {\n                bc = bc + (0,) * (base_level - bc.len())\n              } else if bc.len() > base_level{\n                bc = bc.slice(0, base_level)\n              }\n            }\n\n            // Reset counter if the base counter has updated\n            if tc.slice(0, -1) == bc {\n              counters.at(identifier) = (..bc, tc.last() + 1)\n            } else {\n              counters.at(identifier) = (..bc, 1)\n            }\n          } else {\n            // If we have no base counter, just count one level\n            counters.at(identifier) = (tc.last() + 1,)\n            let latest = counters.at(identifier)\n          }\n\n          let latest = counters.at(identifier)\n          return (\n            \"counters\": counters,\n            \"latest\": latest\n          )\n        })\n      }\n\n      number = context {\n        global_numbering(numbering, ..thmcounters.get().at(\"latest\"))\n      }\n    }\n\n    return figure(\n      result +  // hacky!\n      fmt(name, number, body, ..args.named()) +\n      [#metadata(identifier) <meta:thmenvcounter>],\n      kind: \"thmenv\",\n      outlined: false,\n      caption: name,\n      supplement: supplement,\n      numbering: refnumbering,\n    )\n  }\n}\n\n\n#let thmbox(\n  identifier,\n  head,\n  ..blockargs,\n  supplement: auto,\n  padding: (top: 0.5em, bottom: 0.5em),\n  namefmt: x => [(#x)],\n  titlefmt: strong,\n  bodyfmt: x => x,\n  separator: [#h(0.1em):#h(0.2em)],\n  base: \"heading\",\n  base_level: none,\n) = {\n  if supplement == auto {\n    supplement = head\n  }\n  let boxfmt(name, number, body, title: auto, ..blockargs_individual) = {\n    if not name == none {\n      name = [ #namefmt(name)]\n    } else {\n      name = []\n    }\n    if title == auto {\n      title = head\n    }\n    if not number == none {\n      title += \" \" + number\n    }\n    title = titlefmt(title)\n    body = bodyfmt(body)\n    pad(\n      ..padding,\n      block(\n        width: 100%,\n        inset: 1.2em,\n        radius: 0.3em,\n        breakable: false,\n        ..blockargs.named(),\n        ..blockargs_individual.named(),\n        [#title#name#separator#body]\n      )\n    )\n  }\n  return thmenv(\n    identifier,\n    base,\n    base_level,\n    boxfmt\n  ).with(\n    supplement: supplement,\n  )\n}\n\n\n#let thmplain = thmbox.with(\n  padding: (top: 0em, bottom: 0em),\n  breakable: true,\n  inset: (top: 0em, left: 1.2em, right: 1.2em),\n  namefmt: name => emph([(#name)]),\n  titlefmt: emph,\n)\n\n\n// Track whether the qed symbol has already been placed in a proof\n#let thm-qed-done = state(\"thm-qed-done\", false)\n\n// The configured QED symbol\n#let thm-qed-symbol = state(\"thm-qed-symbol\", $qed$)\n\n// Show the qed symbol, update state\n#let thm-qed-show = {\n  thm-qed-done.update(true)\n  context [#thm-qed-symbol.get()]\n}\n\n// If placed in a block equation/enum/list, place a qed symbol to its right\n#let qedhere = metadata(\"thm-qedhere\")\n\n// Checks if content x contains the qedhere tag\n#let thm-has-qedhere(x) = {\n  if x == \"thm-qedhere\" {\n    return true\n  }\n\n  if type(x) == content {\n    for (f, c) in x.fields() {\n      if thm-has-qedhere(c) {\n        return true\n      }\n    }\n  }\n\n  if type(x) == array {\n    for c in x {\n      if thm-has-qedhere(c) {\n        return true\n      }\n    }\n  }\n\n  return false\n}\n\n\n// bodyfmt for proofs\n#let proof-bodyfmt(body) = {\n  thm-qed-done.update(false)\n  body\n  context {\n    if thm-qed-done.at(here()) == false {\n      h(1fr)\n      thm-qed-show\n    }\n  }\n}\n\n#let thmproof(..args) = thmplain(\n    ..args,\n    namefmt: emph,\n    bodyfmt: proof-bodyfmt,\n    ..args.named()\n).with(numbering: none)\n\n\n#let thmrules(qed-symbol: $qed$, doc) = {\n\n  show figure.where(kind: \"thmenv\"): set block(breakable: true)\n  show figure.where(kind: \"thmenv\"): set align(start)\n  show figure.where(kind: \"thmenv\"): it => it.body\n\n  show ref: it => {\n    if it.element == none {\n      return it\n    }\n    if it.element.func() != figure {\n      return it\n    }\n    if it.element.kind != \"thmenv\" {\n      return it\n    }\n\n    let supplement = it.element.supplement\n    if it.citation.supplement != none {\n      supplement = it.citation.supplement\n    }\n\n    let loc = it.element.location()\n    let thms = query(selector(<meta:thmenvcounter>).after(loc))\n    let number = thmcounters.at(thms.first().location()).at(\"latest\")\n    return link(\n      it.target,\n      [#supplement~#numbering(it.element.numbering, ..number)]\n    )\n  }\n\n  show math.equation.where(block: true): eq => {\n    if thm-has-qedhere(eq) and thm-qed-done.at(eq.location()) == false {\n      grid(\n        columns: (1fr, auto, 1fr),\n        [], eq, align(right + horizon)[#thm-qed-show]\n      )\n    } else {\n      eq\n    }\n  }\n\n  show enum.item: it => {\n    show metadata.where(value: \"thm-qedhere\"): {\n      h(1fr)\n      thm-qed-show\n    }\n    it\n  }\n\n  show list.item: it => {\n    show metadata.where(value: \"thm-qedhere\"): {\n      h(1fr)\n      thm-qed-show\n    }\n    it\n  }\n\n  thm-qed-symbol.update(qed-symbol)\n\n  doc\n}\n"
  }
]