Fonctions de type log et mod

\mathrm{sin} et \sin donnent sur le papier exactement le même « sin ». Le premier reste pourtant fautif, et l’écart vaut 3.33325pt. En mesurant $a\operatorname{op}b$ sous LaTeX on obtient 23.46638pt ; $a\mathrm{op}b$ donne 20.13313pt. La forme droite est identique, mais \mathrm ne porte aucune espace autour de lui. Ces 3.33325pt ne sont pas décoratifs : ce sont exactement deux fines espaces, celles que TeX place de part et d’autre d’un atome Op. Cette page part de cet atome, situe ensuite les 32 noms de fonctions intégrés dans les sources de LaTeX, explique pourquoi dix d’entre eux exactement placent leur indice dessous, montre ce que change l’étoile de \DeclareMathOperator, et distingue les quatre formes modulaires \bmod, \pmod, \mod et \pod par leur largeur mesurée.

Pourquoi \mathrm{sin} est fautif : la classe d’atome fixe l’espacement

En mode mathématique, chaque lettre passe pour le nom d’une variable et se compose en italique mathématique : sin x donne donc non pas « sinus » mais le produit des quatre quantités s, i, n, x. Jusque-là c’est bien connu, et beaucoup pensent à \mathrm{sin} comme remède, puisque le problème semble réglé dès que la fonte est droite. Mais \mathrm ne change que la fonte. Pour TeX, la classe d’atome reste Ord, un symbole ordinaire.

TeX range les éléments d’une formule en classes d’atomes — Ord (ordinaire), Op (opérateur), Bin (opérateur binaire), Rel (relation) et quelques autres — et détermine les espaces uniquement d’après les classes voisines. Entre Ord et Ord, pas d’espace. Entre Op et Ord, une fine espace (\thinmuskip, 3mu). \sin est un Op, \mathrm{sin} un Ord : d’où l’écart. Mesurer les quatre expressions suivantes dans un document en 10pt transforme ce mécanisme en chiffres.

measured on TeX Live 2024, 10pt article
\DeclareMathOperator{\myop}{op}
% \sbox0{$...$}\message{\the\wd0}

$a\operatorname{op}b$        23.46638pt
$a\myop b$                   23.46638pt   % identical to \operatorname
$a\mathop{\mathrm{op}}b$     23.46638pt   % same font as \mathrm, but Op class
$a\mathrm{op}b$              20.13313pt   % 3.33325pt narrower

$\mkern3mu$  1.66663pt        % one thin space; two of them = 3.33326pt

La troisième ligne tranche. \mathop{\mathrm{op}} emploie exactement la même fonte que \mathrm et rejoint pourtant \operatorname au cent-millième de point près. Ce qui crée l’écart n’est donc pas la fonte mais la classe Op que confère \mathop. Et les 3.33325pt de différence font précisément deux fines espaces de 1.66663pt — une entre a et « op », une entre « op » et b. L’adage selon lequel « \mathrm fausse l’espacement » se trouve ainsi expliqué jusqu’à la dernière décimale. Conclusion pratique, très simple : écrire les noms de fonctions avec la commande dédiée ou avec \operatorname, jamais avec \mathrm.

Les 32 noms de fonctions intégrés, et où ils sont écrits

Les définitions de \log et \sin ne résident pas dans un paquet mais dans latex.ltx, le fichier de format de LaTeX lui-même. Dans TeX Live 2024, elles occupent les lignes 12487 à 12518 — exactement 32 lignes — chacune de la forme \DeclareRobustCommand\log{\mathop{\operator@font log}\nolimits}. La liste est plus ancienne encore : presque le même ensemble figure dans le plain.tex de Knuth, lignes 1058 à 1085. Pouvoir écrire \sin n’est donc pas dû à amsmath ; cela fonctionne d’emblée, sans le moindre paquet (seule la déclaration de vos propres opérateurs demande amsmath, voir plus bas).

  • Trigonométriques : \sin \cos \tan \cot \sec \csc, et les inverses \arcsin \arccos \arctan.
  • Hyperboliques : \sinh \cosh \tanh \coth — à noter que \sech et \csch n’y sont pas ; il faut les déclarer soi-même.
  • Logarithmes et exponentielle : \log (général), \ln (népérien), \lg (base 2, courant en théorie de l’information), \exp.
  • Algèbre, géométrie et voisins : \deg (degré), \dim (dimension), \ker (noyau), \hom, \arg (argument), \det (déterminant).
  • Les 10 qui placent les indices dessous : \lim \limsup \liminf \max \min \sup \inf \det \Pr \gcd.

Bases et exposants s’ajoutent par le mécanisme ordinaire des indices : \log_2 x place un 2 en bas à droite de « log », et \sin^2\theta en haut à droite, donnant le sin²θ habituel. Un détail que seule la lecture de la source révèle : \limsup est défini comme \mathop{\operator@font lim\,sup}une fine espace \, a été posée à la main entre « lim » et « sup ». Ce n’est pas un mot d’un seul tenant mais deux mots délibérément un peu écartés.

latex
\[
  \sin^2\theta + \cos^2\theta = 1, \qquad
  \log_2 8 = 3, \qquad \ln e = 1.
\]

Les 10 à indices dessous, et pourquoi \limits reste sans effet

Sur les 32, vingt-deux terminent leur définition par \nolimits : leurs indices apparaissent donc en bas à droite. Les dix autres — \lim, \limsup, \liminf, \max, \min, \sup, \inf, \det, \Pr, \gcdn’ont pas de \nolimits. Comme la valeur par défaut de \mathop en style hors texte est « indices dessous », ce sont exactement ces dix-là qui placent x→0 sous \lim dans un affichage. La convention voulant qu’une limite ou un maximum affiche bien en vue « sur quel domaine » est ainsi inscrite dans les définitions. En style texte (en ligne), les dix repassent en bas à droite.

latex
\[
  \lim_{x \to 0} \frac{\sin x}{x} = 1, \qquad
  \max_{1 \le i \le n} a_i .
\]

On songe naturellement à employer \limits, qui agit sur \sum et \int, pour un nom de fonction également. Mais amsmath chargé, \log\limits_{k} ne produit rigoureusement rien : ni erreur, ni avertissement, ignoré en silence. La raison tient à la ligne 27 de amsopn.sty : \def\nolimits@{\@ifnextchar\limits{\nolimits\@gobble}{\nolimits}}. Chaque définition de nom d’opérateur se termine par cet appel à \nolimits@, et si le jeton suivant est \limits, elle émet \nolimits puis avale ce \limits. La mesure le confirme.

measured on TeX Live 2024, 10pt article
% depth of the box tells us where the script went (bigger = below the operator)

% WITHOUT amsmath — \log is \mathop{...}\nolimits, and \limits overrides it
$\displaystyle\log_{k}x$          d = 2.44443pt
$\displaystyle\log\limits_{k}x$   d = 9.47220pt   % moved below

% WITH amsmath — the \limits is swallowed by \nolimits@
$\displaystyle\log_{k}x$          d = 2.44443pt
$\displaystyle\log\limits_{k}x$   d = 2.44443pt   % unchanged: nothing happened

La règle générale sur \limits — applicable aux grands opérateurs comme \sum, traitée dans « Sommes, intégrales et grands opérateurs » — ne s’étend donc pas aux noms d’opérateurs sous amsmath. Le sens inverse passe sans encombre : \lim\nolimits_{k} repousse bel et bien l’indice de \lim en bas à droite. Pour un indice dessous, la bonne réponse n’est pas \limits mais la déclaration étoilée de la section suivante.

\DeclareMathOperator et \operatorname : ce que décide l’étoile

Pour un nom absent de la liste — la fonction signe sgn, la trace tr, le rang rank, ess sup, argmax —, amsmath prend le relais. Pour un usage unique, écrivez \operatorname{sgn} x ; pour un usage répété, déclarez-le dans le préambule par \DeclareMathOperator{\sgn}{sgn}. Comme le montre la mesure en tête de page, un \sgn déclaré fait exactement la même largeur que \operatorname{sgn} : tous deux appellent le même \qopname et sont littéralement la même chose. L’intérêt de déclarer n’est pas la qualité mais le regroupement en un seul endroit : changer plus tard de notation ne coûte qu’une ligne du préambule.

preamble
\usepackage{amsmath}
\DeclareMathOperator{\sgn}{sgn}            % scripts to the right, like \log
\DeclareMathOperator*{\argmax}{arg\,max}   % scripts underneath, like \lim

% in the body:
% \[ \sgn x, \qquad \argmax_{x \in S} f(x) \]

L’étoile ne décide que de la position des indices. Sans elle, on obtient un membre de la famille \log (en bas à droite) ; avec elle, un membre de la famille \lim (dessous, en style hors texte). Pour un usage unique, \operatorname*{…} fait de même. Cela aussi se mesure : en composant le même op en affichage avec _{n\to\infty}, la profondeur de la boîte vaut 2.44443pt sans étoile et 8.94444pt avec. Ce surcroît de profondeur, c’est l’indice suspendu sous le symbole. Le \, glissé dans le nom (arg\,max) est là pour la même raison que dans la définition de \limsup : ménager la bonne espace entre les deux mots.

amsmath ajoute encore du vocabulaire autour des limites supérieure et inférieure. \varlimsup et \varliminf sont des variantes portant une barre au-dessus (ou au-dessous) de « lim », plus symboliques que l’orthographe « lim sup » de \limsup. \injlim et \projlim composent les limites directe et inverse en « inj lim » et « proj lim », tandis que \varinjlim et \varprojlim donnent la forme familière en théorie des catégories, avec une flèche → (ou ←) sous « lim ». Toutes, comme une déclaration étoilée, placent les indices dessous. Le choix suit la convention de votre domaine ; dans le doute, vérifiez si la feuille de style de la revue visée n’en définit pas déjà une.

\bmod, \pmod, \mod, \pod : distinguer les quatre par la mesure

Si les quatre formes modulaires prêtent à confusion, c’est qu’elles impriment toutes « mod » et ne diffèrent que par l’espacement et les parenthèses. \bmod et \pmod appartiennent au LaTeX standard ; \mod et \pod viennent d’amsmath. La différence de conception saute aux yeux dans les définitions : seul \bmod est défini avec \mathbin{…} — c’est-à-dire comme un atome Bin, la classe de + et - — tandis que les trois autres se contentent d’insérer une espace puis de composer leur contenu, à la manière d’une annotation postposée.

amsmath.sty, lines 905-912
\DeclareRobustCommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
  {\operator@font mod}\penalty900
  \mkern5mu\nonscript\mskip-\medmuskip}
\DeclareRobustCommand{\pod}[1]{\allowbreak
  \if@display\mkern18mu\else\mkern8mu\fi(#1)}
\DeclareRobustCommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
\DeclareRobustCommand{\mod}[1]{\allowbreak\if@display\mkern18mu
  \else\mkern12mu\fi{\operator@font mod}\,\,#1}

Observez \if@display. \pod et \pmod insèrent 18mu en affichage et 8mu en ligne, \mod 18mu et 12mu. \bmod ignore cette bifurcation : en opérateur binaire, il pose simplement \mkern5mu de façon symétrique de part et d’autre — ce qui en fait le seul des quatre dont la largeur ne change pas entre affichage et texte courant. Mesurer la même expression a … n en 10pt convertit directement la conception en chiffres.

CommandeSortieLargeur en ligne → affichageQuand l’employer
a \bmod na mod n36.01039pt → 36.01039pt (inchangé)Quand on désigne le reste comme valeur. Atome Bin, donc symétrique. LaTeX standard
a \pmod{n}a (mod n)46.01036pt → 51.56578ptLa fin habituelle d’une congruence, x \equiv y \pmod{n}. LaTeX standard
a \mod{n}a mod n40.45473pt → 43.78798ptPour les congruences sans parenthèses ; espace initiale plus large que \bmod. Nécessite amsmath
a \pod{n}a (n)23.51038pt → 29.06580ptParenthèses sans le mot « mod », quand le module est évident d’après le contexte. Nécessite amsmath

Soustrayez la largeur en ligne de la largeur en affichage et les définitions réapparaissent exactement. Pour \pmod et \pod, l’écart vaut 5.55542pt — soit 18mu − 8mu = 10mu, et en 10pt 9.99976 − 4.44434 = 5.55542pt. Pour \mod, il vaut 3.33325pt, c’est-à-dire 18mu − 12mu = 6mu. Pour \bmod, il est nul. Le choix relève du sens : \bmod quand on désigne le reste comme valeur (5 \bmod 3 = 2), et \pmod quand on affirme que deux nombres sont congrus modulo n (17 \equiv 5 \pmod{12}). Les confondre, c’est priver le lecteur de la distinction entre une valeur et une relation.

latex
\[
  5 \bmod 3 = 2, \qquad
  17 \equiv 5 \pmod{12}.
\]