マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

大きな定数を定義する話

TeX で定数を表すトークンを作りたい時は、\chardef を「借用」する。LaTeX では次のような定義が行われている。このトークン(\@ne 等)自体は TeX プログラミングをする人なら必ず見たことがあるだろう。((ちなみに \z@ は chardef トークンではない。))


\chardef\@ne=1
\chardef\tw@=2
\chardef\thr@@=3

他にもこんな定数も定義されている。


\chardef\sixt@@n=16
\chardef\@cclv=255

無論、\chardef の本来の目的は、\char〈符号位置〉 と同じ機能をもつトークンを定義することである。だから、例えば、整数があるべき場所以外で \sixt@@n を「実行」すると、現在フォントの符号位置 16 の文字が出力される。そして本来の目的がそういうものであるため、\chardef で定義できる定数は 8 ビット TeX では 0〜255 の範囲に限られる。


\chardef\@cclvi=256 % ダメ

大きな数の定数トークンを作りたい場合は、今度は、数式用の文字出力の命令を定義する命令 \mathchardef を「借用」することになる。この場合、0〜"7FFF *1の範囲の整数が対象になる。LaTeX ではこんな定義がある


\mathchardef\@cclvi=256
\mathchardef\@m=1000
\mathchardef\@M=10000
\mathchardef\@MM=20000

そして、"7FFF(32767)を超える整数については、TeX では定数トークンを作れない。もしどうしても定数トークンが必要なら、(貴重な)整数レジスタを定数として扱うしかない。勿論、「数字表現に展開されるマクロ」(例えば \def\thr@@{3})で代用できる場合もあるが、これは定数トークンとは用法が異なる。

pTeX では、\chardef和文文字に対しても用いることができる。だから、一応 "7FFF より大きな定数を作れるということになるが、使える値は内部漢字コード(sjis または euc)で有効な符号位置でないといけないし、この範囲は不連続である上に sjiseuc のどちらであるかで全く異なるので、定数を作るという目的では全く使えない。


% -kanji-internal=sjis だと OK だが euc だと NG
\chardef\@value="8642

ところが、内部漢字コードが Unicode の upTeX では話が異なってくる。Unicode なので、0〜"10FFFF の範囲の整数が全部使えることになる。実際には upTeX で有効な和文文字コードの範囲は 0〜"FFFFFF *2なので、この範囲の定数が作れることになる。


\chardef\@value="ABCDEF

XeTeX/LuaTeX ではどうなるか。これらのエンジンでは、符号空間は Unicode の定義通りの 0〜"10FFFF なので、\chardef で定義できるのはこの範囲である。Unicode の対応の \mathchardef(XeTeX では \XeTeXmathchardef、LuaTeX では \Umathchardef)は数式クラスとファミリと符号位置を別に指定する方式になっているので、定数の定義には不適である。((実際には、\Umathchardef で定義されたトークンは 32 ビットの単一の整数の役割を果たすのであるが、その下位 21 ビットが符号位置であり、ここが 0〜"10FFFF に限られるので、結局自由には使えないことになる。))

ただし、LuaTeX の場合、Omega(Aleph)互換命令である \omathchardef が使えて、これだと 0〜"7FFFFFF の範囲に対応できる。


\omathchardef\@value="7654321

もっとも、LuaTeX ではレジスタは 65536 個あるので、定数のためにレジスタを使っても全く構わないのであるが……。

*1:〈"〉は TeX で 16 進表現を表わす接頭辞。

*2:ただし実際に出力されるのは 0〜"10FFFF の範囲である。この辺りの仕様の詳細は省略する。