log 型関数と mod

\mathrm{sin}\sin は、紙の上ではまったく同じ「sin」に見えます。それでも前者は間違いで、その差は 3.33325pt です。LaTeX で $a\operatorname{op}b$ の幅を測ると 23.46638pt、$a\mathrm{op}b$ は 20.13313pt——立体という見た目は同じでも、\mathrm のほうは前後の空きを持っていません。この 3.33325pt は装飾ではなく、TeX が Op という原子(atom) の左右に入れる細空き二つ分ちょうどです。このページでは、その原子の話から始めて、組み込みで用意されている 32 個の関数名がどこに書かれているか、添字が真下に来るのはなぜどの 10 個か、\DeclareMathOperator の星が何を変えるか、そして \bmod\pmod\mod\pod という四つの「latex mod 書き方」を実測値で見分けます。

\mathrm{sin} が間違いである理由——原子の種類が空きを決める

数式モードでは英字の一文字ずつが変数の名前とみなされ、数式イタリックで組まれます。だから sin x と打つと、出力は「正弦」ではなく sinx という四つの量の積になります。ここまでは有名な話で、対処として \mathrm{sin} を思いつく人が多い——立体になれば解決したように見えるからです。ところが \mathrm が変えるのは 書体だけ で、TeX から見た 原子の種類は Ord(普通の記号)のまま です。

TeX は数式の要素を Ord(普通)・Op(作用素)・Bin(二項演算子)・Rel(関係子)などの 原子の種類 に分類し、隣り合う種類の組み合わせだけを見て空きを決めます。Ord と Ord のあいだには空きが入りません。Op と Ord のあいだには 細空き(\thinmuskip、3mu) が入ります。\sin は Op、\mathrm{sin} は Ord——だから差が出ます。次の四つを 10pt の本文で測ると、その仕組みがそのまま数字になって現れます。

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

三行目が決め手です。\mathop{\mathrm{op}} は書体としては \mathrm とまったく同じものを使いながら、幅は \operatorname と 1pt の 10 万分の 1 まで一致します。つまり違いを生んでいるのは書体ではなく \mathop が付ける Op という種類 です。そして差の 3.33325pt は、細空き 1.66663pt のちょうど二つ分——a と「op」のあいだに一つ、「op」と b のあいだに一つ。「\mathrm では空きが狂う」という言い伝えは、こうして小数点以下まで説明がつきます。実務上の結論は単純で、関数名は必ず専用の命令か \operatorname で書き、\mathrm は使わない ことです。

組み込みの関数名は 32 個——どこに書かれているか

\log\sin の定義は、パッケージではなく LaTeX 本体のフォーマットファイル latex.ltx にあります。TeX Live 2024 では 12487 行目から 12518 行目までの ちょうど 32 行\DeclareRobustCommand\log{\mathop{\operator@font log}\nolimits} という形が並ぶだけです。この一覧はさらに古く、クヌースの plain.tex(1058〜1085 行)にほぼそのまま存在します。つまり \sin を書けるのは amsmath のおかげではなく、追加パッケージなしで最初から使えます(自作するときだけ amsmath が要ります。後述)。

  • 三角関数: \sin \cos \tan \cot \sec \csc、逆関数 \arcsin \arccos \arctan
  • 双曲線関数: \sinh \cosh \tanh \coth\sech\csch入っていません。必要なら自分で宣言します)。
  • 対数・指数: \log(一般)、\ln(自然対数)、\lg(底 2、情報理論でよく使う)、\exp
  • 代数・幾何など: \deg(次数)、\dim(次元)、\ker(核)、\hom\arg(偏角)、\det(行列式)。
  • 添字が真下に来る 10 個: \lim \limsup \liminf \max \min \sup \inf \det \Pr \gcd

底や指数はふつうの添字の仕組みでそのまま添えられます。\log_2 x は「log」の右下に 2、\sin^2\theta は右肩に 2 が付いて慣用の sin²θ になります。ひとつ、原典を読まないと気づかない小ネタ:\limsup の定義は \mathop{\operator@font lim\,sup} で、「lim」と「sup」のあいだに \, の細空きが手で入れてあります。ひとつづきの単語ではなく、二語をわざと少し離して組んでいるわけです。

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

添字が真下に来る 10 個と、\limits が効かない理由

32 個のうち 22 個は定義の末尾に \nolimits が付き、添字は 記号の右下 に出ます。残りの 10 個——\lim \limsup \liminf \max \min \sup \inf \det \Pr \gcd——には \nolimits書かれていません\mathop の既定はディスプレイスタイルで「添字を真下」なので、この 10 個だけが別行立てで \lim の下に x→0 を置きます。極限や最大は「どの範囲で」を大きく見せたい、という数学の慣習がそのまま定義に現れているわけです。インライン(テキストスタイル)では 10 個も右下に付きます。

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

ここで、\sum\int に効く \limits を関数名にも使えばよい、と考えるのが自然です。ところが amsmath を読み込んでいると \log\limits_{k} は何も起こしません。エラーも警告も出ず、静かに無視されます。理由は amsopn.sty の 27 行目にあります——\def\nolimits@{\@ifnextchar\limits{\nolimits\@gobble}{\nolimits}}。関数名の定義は末尾でこの \nolimits@ を呼び、次のトークンが \limits だったら \nolimits を出したうえでその \limits を食べてしまう のです。実測でも裏が取れます。

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

つまり \limits の一般則(\sum などの大型作用素で使える、詳しくは「和・積分・大型作用素」を参照)は、amsmath 下の関数名には適用されません。逆向きの \nolimits は素通りするので、\lim\nolimits_{k}\lim の添字を右下に追い出すことはできます。真下に置きたい側の正しい答えは \limits ではなく、次節の星付き宣言 です。

\DeclareMathOperator\operatorname——星が決めるもの

一覧にない名前——符号関数 sgn、跡 tr、階数 rankess supargmax——を正しく組みたいときは amsmath の出番です。その場限りなら \operatorname{sgn} x、繰り返し使うならプリアンブルで \DeclareMathOperator{\sgn}{sgn}宣言 します。冒頭の実測どおり、宣言した \sgn の幅は \operatorname{sgn} と完全に一致します——両者は同じ \qopname を呼ぶ、文字どおり同じものだからです。宣言する利点は品質ではなく 一箇所に集約されること で、表記を変えたくなったらプリアンブルの一行を直すだけで済みます。

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) \]

星が決めるのは添字の位置だけ です。星なしは \log の仲間(右下)、星付きは \lim の仲間(別行立てで真下)になります。その場限りなら \operatorname*{…} が同じ働きをします。ここも寸法で確かめられます——同じ op を別行立てで組み、_{n\to\infty} を付けたときの箱の深さは、星なしが 2.44443pt、星付きが 8.94444pt。深さが増えているのは、添字が記号の下にぶら下がったからです。名前に \, を挟んでいる(arg\,max)のは、\limsup の定義と同じ理由で、二語のあいだに適切な空きを残すためです。

amsmath は上下極限まわりの語彙も足します。\varlimsup\varliminf は「lim」に 横線を上(下)に引いた 異体字で、\limsup の「lim sup」という綴りより記号的です。\injlim\projlim は順極限・逆極限を「inj lim」「proj lim」と組み、\varinjlim\varprojlim は「lim」の下に →(←)を敷いた圏論でおなじみの形になります。いずれも星付き宣言と同じく 添字は真下 です。どれを選ぶかは分野の慣習に従うのが安全で、迷ったら投稿先のスタイルファイルが既に定義していないか確認してください。

\bmod \pmod \mod \pod——四つの mod を実測で見分ける

「latex mod 書き方」で迷うのは、四つある綴りがどれも「mod」と出るのに、空きと括弧だけが違う からです。\bmod\pmod は標準の LaTeX に、\mod\pod は amsmath にあります。設計の違いは定義を見れば一目瞭然で、\bmod だけが \mathbin{…}——つまり +- と同じ Bin(二項演算子)の原子 として定義されており、残る三つは前に空きを置いてから中身を並べるだけの、いわば「後置の注記」です。

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}

\if@display に注目してください。\pod\pmod別行立てなら 18mu、本文中なら 8mu\mod18mu と 12mu を前に置きます。\bmod にはこの分岐がありません——二項演算子として左右対称に \mkern5mu を置くだけなので、別行立てでも本文中でも幅が変わらない唯一の一つ です。同じ式 a … n を 10pt で測ると、設計がそのまま数字に出ます。

命令出力幅 本文中 → 別行立て使いどころ
a \bmod na mod n36.01039pt → 36.01039pt(不変)余りという を書くとき。Bin 原子なので前後が対称。標準 LaTeX
a \pmod{n}a (mod n)46.01036pt → 51.56578pt合同式 x \equiv y \pmod{n} の末尾に添える定番。標準 LaTeX
a \mod{n}a mod n40.45473pt → 43.78798pt括弧を嫌う流儀の合同式に。\bmod より前の空きが広い。amsmath が必要
a \pod{n}a (n)23.51038pt → 29.06580pt「mod」を省いて括弧だけ。法が文脈で自明なときに。amsmath が必要

別行立てと本文中の差を引き算すると、定義がぴったり再現されます。\pmod\pod の差は 5.55542pt——これは 18mu − 8mu = 10mu で、10pt 本文では 9.99976 − 4.44434 = 5.55542pt。\mod の差は 3.33325pt で、18mu − 12mu = 6mu にあたります。\bmod の差は 0。使い分けは意味で決まります。余りという値そのもの を書くなら \bmod5 \bmod 3 = 2)、二つの数が法 n で合同である と主張するなら \pmod17 \equiv 5 \pmod{12})。この二つを取り違えると、読者には「値」と「関係」の区別が伝わりません。

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