Variant limits

Variants for superior, inferior, projective, and injective limits are an interesting challenge for typesetting engines with mathematical capabilities.

They have both a subscript expression and a stretchy symbol (an arrow or a bar) that indicates the direction and nature of the limit.

The symbol is stacked below or above the limit.

In display mode, the expression is below the limit.

In inline mode, the expression is on the right of the limit, but the symbol remains above or below the limit. So the symbol is not moveable, while the expression is, depending on the context.

sile

Download: ( source | pdf )

Input document

\begin[papersize=a7]{document}
\nofolios
\neverindent
\use[module=packages.math]
\font[size=12pt]
\set[parameter=math.font.family,value=Libertinus Math]
\set[parameter=math.font.size,value=12]

\begin[mode=display]{math}
  \projlim_{i \in I} A_i = \varprojlim_{i \in I} A_i
\end{math}

Inline: \math{\projlim_{i \in I} A_i = \varprojlim_{i \in I} A_i}

\begin[mode=display]{math}
  \injlim_{i \in I} A_i = \varinjlim_{i \in I} A_i
\end{math}

Inline: \math{\injlim_{i \in I} A_i = \varinjlim_{i \in I} A_i}

\begin[mode=display]{math}
  \limsup_{n \to \infty} a_n = \varlimsup_{n \to \infty} a_n
\end{math}

Inline: \math{\limsup_{n \to \infty} a_n = \varlimsup_{n \to \infty} a_n}

\begin[mode=display]{math}
  \liminf_{n \to \infty} a_n = \varliminf_{n \to \infty} a_n
\end{math}

Inline: \math{\liminf_{n \to \infty} a_n = \varliminf_{n \to \infty} a_n}

\end{document}

Render command

sile -o varlimits-sile.pdf varlimits-sile.sil

xelatex

Download: ( source | pdf )

Input document

\documentclass[12pt]{article}
\usepackage[paperheight=105mm,paperwidth=74mm,margin=4mm]{geometry}
\pagenumbering{gobble}
\setlength{\parindent}{0pt}
\usepackage{libertinus}
\usepackage{fontspec}
\usepackage{unicode-math}
\begin{document}

$$
  \projlim_{i \in I} A_i = \varprojlim_{i \in I} A_i
$$

Inline: $\projlim_{i \in I} A_i = \varprojlim_{i \in I} A_i$


$$
  \injlim_{i \in I} A_i = \varinjlim_{i \in I} A_i
$$

Inline: $\injlim_{i \in I} A_i = \varinjlim_{i \in I} A_i$

$$
  \limsup_{n \to \infty} a_n = \varlimsup_{n \to \infty} a_n
$$

Inline: $\limsup_{n \to \infty} a_n = \varlimsup_{n \to \infty} a_n$

$$
  \liminf_{n \to \infty} a_n = \varliminf_{n \to \infty} a_n
$$

Inline: $\liminf_{n \to \infty} a_n = \varliminf_{n \to \infty} a_n$

\end{document}

Render command

xelatex -interaction=batchmode -halt-on-error -jobname data/varlimits-xelatex varlimits-xelatex.tex

typst

Download: ( source | pdf )

Input document

// 2025, Didier Willis
// License: MIT.
// Typst does not have these extended limits out of the box:
//   projlim, injlim, varprojlim, varinjlim,
//   varlimsup, varliminf.
// So here is a possible implementation...
// Total newbie, so it's maybe not idiomatic
#let varlim(arrow) = context {
  let lim = "lim"
  let lim-width = measure(lim).width
  let arrow-height = measure(arrow).height  
  let varlimop = box(
    width: lim-width,
    baseline: arrow-height,
    box(
      width: 0pt,
      baseline: arrow-height,
      [#math.stretch(arrow, size: lim-width)]
    )
    +
    box(
      baseline: 0pt,
      width: 0pt,
      lim
    )
  )
  return varlimop
}
// Helpers
#let strut = context {
  // Weird way to do a small adjustment for varliminf
  // so that the limit expression is a bit lower
  block(height: measure("").height, width: 0pt)
}
#let varprojlim = math.limits(varlim(sym.arrow.l), inline:false)
#let projlim = math.limits("proj\u{2009}lim", inline: false)
#let varinjlim = math.limits(varlim(sym.arrow.r), inline:false)
#let injlim = math.limits("inj\u{2009}lim", inline: false)
#let varliminf = math.limits(underline("lim"+strut), inline: false)
#let varlimsup = math.limits(overline("lim"), inline: false)

// --- Now the intended document ---

#set page(
  paper: "a7",
  margin: 4mm,
)
#set text(
    font: "Libertinus Serif",
    size: 12pt,
)

$ projlim_(i in I) A_i = varprojlim_(i in I) A_i $
Inline: $projlim_(i in I) A_i = varprojlim_(i in I) A_i$

$ injlim_(i in I) A_i = varinjlim_(i in I) A_i $
Inline: $injlim_(i in I) A_i = varinjlim_(i in I) A_i$

$ limsup_(n -> oo) a_n = varlimsup_(n -> oo) a_n $

Inline: $limsup_(n -> oo) a_n = varlimsup_(n -> oo) a_n$

$ liminf_(n -> oo) a_n = varliminf_(n -> oo) a_n $

Inline: $liminf_(n -> oo) a_n = varliminf_(n -> oo) a_n$

Render command

typst compile varlimits-typst.typ varlimits-typst.pdf