\eqno で行間に余計な空白が入る?

\eqno で行間に余計な空白が入る?

- みなも の投稿
返信数: 16
先日新しいノートパソコンを買って,最新の TeXLive を入れたんですが,
デスクトップパソコンに入っている  W32TeX と異なる挙動がみられました。
TeXLive は 2022 (今年の 2/19 にネットからインストールしたばかり)
W32TeX は TeXLive2021 ベース (2021年の 4 月にインストール)

具体的には
$$x^2 + 3x + 2 = 0 \eqno\cdots(*)$$
$$(x + 1)(x + 2) = 0$$
としたときに,
W32TeX では行間に目立った空白はないのですが,
TeXLive2022 ではほぼ 1 行分余分な空白が入ってしまいます。

ちなみにプリアンブルはシンプルに
\documentclass{jarticle}
だけで実験しています。

\eqno 以下を削除すれば余計な空白は入りません。
また,\usepackage{amsmath} を追加した上で
$$ $$ を \[ \] に変えれば余計な空白は入りません。
(amsmath だと実質的に eqation* 環境になる模様)

ちなみに $$ $$ を使っているのは,仕事柄,別行立て数式が
「センター配置」と「左から一定文字数位置から開始」
が混在する文章を作ることもあって,\[ \] と使い分けているからです。
\eqno を使っているのも,
式番号がイレギュラーな文書を日常的に作っているためです。
(問題文は原題準拠,解答は予備校独自スタイル,
とかが要求されると,同一文書内でスタイルが変わる)

これって,\eqno あたりの仕様が変わったんでしょうか。
余計な空白を回避するには $$ $$ をやめるしかないでしょうか。

%  あと,これは質問ではなく愚痴ですが
% TeXLive2022 の dvipdfmx で作った図入りの PDF が
% 職場の複合機(コピー+プリンタ)の内蔵PDFビューアで開けなくなってしまった。
% 内蔵PDFビューアに対応していると
% USBメモリ直差しでプリントアウトできたのに。。。
みなも への返信

Re: \eqno で行間に余計な空白が入る?

- 和田 勇 の投稿
◆ 数式の前後の空白
  #普段数式は使わないので、不正確なところがあると思います。
  #そのような点に気がついた方、ぜひ補足していただけると幸いです。

amthmath を使われても $$ のご希望はある程度できると思います。

  https://tex.stackexchange.com/questions/374003/changing-above-below-displayshortskip-with-memoir-causes-bad-boxes-in-head-foo
  https://oversleptabit.com/archives/853

を参考に
  \abovedisplayshortskip
  \belowdisplayshortskip
を調整するそうです。(上記で検索して他のも検討してください)

    \setlength\abovedisplayshortskip{-.5\baselineskip}%
    \setlength\belowdisplayshortskip{-.5\baselineskip}%

とすると \eqno ある式はほぼほぼご希望通りになるかと思いますが、
そうでないと持ち上がってしまい、重なって表示されますので、
値の微調整のほか、運用方法も検討する必要かと思います。

◆W32TEX の TEXMFLOCAL やTEXMFHOME に何かあるかもしれない
W32TeX は使っていないのでわかりませんが、
TEXMFLOCAL とかに何か入っていませんか?
W32TEX で処理して、ログをみるとわかるかもしれません。

◆ W32TEX を新しいパソコンで使われてみたらいかがでしょうか?
W32TEX が良いのであれば、
ディレクトリごと丸っとコピーして
新しい環境にコピーしてできないのかな?
macOS ではそのようにして新しいパソコンにコピーして
利用してきましたので、参考にしてください。

◆ PDF でのお困りごとについて

この種の問題は PDF のバージョンが関係すると思います。
これで検索すると
  https://qiita.com/zr_tex8r/items/a590ee544e95c525bba0
  LaTeXで出力PDFのバージョンを指定する ~bxpdfverパッケージ~
が見つかりました。お役に立てば良いのですが。。。
みなも への返信

Re: \eqno で行間に余計な空白が入る?

- はやて (h20y6m) の投稿
その場しのぎですが、

$$x^2 + 3x + 2 = 0 \eqno\cdots(*)$$%
$$(x + 1)(x + 2) = 0$$

のように $$ の直後に % を置くと回避できると思います。

https://github.com/latex3/latex2e/issues/886

あたりが関連するような気がするのですがよくわかっていません。
はやて (h20y6m) への返信

Re: \eqno で行間に余計な空白が入る?

- 和田 勇 の投稿
やってみました。
とりあえずは運用で回避できますね。

理由は、紹介されたいる URL をたどって
最初の https://tex.stackexchange.com/questions/649690/weird-small-indentation-after-formula
に書かれていますね。

多くの人が使いたい気持ちは理解しているので
今後も保守は続けるようですが、
「使ってほしくない」非推奨コマンドであることを理解して使用して
欲しい旨のことも書かれていますね。(deepl 他の手助けしてもらいましたが)
和田 勇 への返信

Re: \eqno で行間に余計な空白が入る?

- みなも の投稿
和田 勇 さん,はやて (h20y6m) さん,情報ありがとうございました。

$$ の後ろに % をつけることで回避できました。

紹介いただいたサイトを見た感じ,
・$$ $$ の後ろに単語間空白が入ることがあるよ
    (理由は読んでもよくわかりませんでした。仕様変更の副作用?)
・でもバグじゃないよ
・\[ \] や equation 環境はちゃんと対策しているから,そっちを使ってね
ってことでしょうか。

とりあえず % をつけて対処することにします。

> ◆ PDF でのお困りごとについて

> この種の問題は PDF のバージョンが関係すると思います。

プロパティで確認したところ,PDF のバージョンはどっちも 1.5 のようです。
(PDFメーカーとしての dvipdfmx のバージョン(?) は 8 ヶ月分ほど違っていますが。)
何か別のことが絡んでいるんでしょうか。
まぁ,パソコンから Acrobat Reader でプリントアウトすれば問題ないので,
さほど実害はないのですが。。。
みなも への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
https://tex.stackexchange.com/questions/649690/weird-small-indentation-after-formula

を読んでみました。

2022 年 7 月 3 日時点の David Carlisle さんのご説明と、その
後の経過を見る限りでは、不具合には既に対処済みであるという
ことのようにも見えます。
(いずれにせよ、W32TeX と TeX Live 2022 との違いではなくて、
この間のカーネルの変更の影響ということみたいですね)

流れとしてはまず:

ltfssdcl.dtx
 %  \begin{macro}{\c@localmathalphabets}
 % \changes{v3.0x}{2021/09/26}{Counter added for (gh/676)}

で、数式ファミリ数の制約を超えるのを防ぐために、ファミリ数の
変更をローカルに留めることができる仕組みを導入したらしいので
すが、そのせいで $$ の後ろの \ignorespaces が利かなくなって
しまっていたとのことです。
(cf. LaTeX News 34: Undo math alphabet allocations if necessary)

それで、ひとまずの対処法としては:

If you choose to keep using $$ you can avoid the problem
by disabling the new math alphabet feature by declaring:

  \setcounter{localmathalphabets}{0}

until the underlying problem gets fixed, but ...

と回答されています。
("but" 以下では、このカウンタを 0 にすると、従来通り、数式
ファミリが 16 を超えるとエラーになりますよ、書かれています)

ここで、"until the underlying problem gets fixed" とのこと
なのですが、翌日には、fix されているように見えます:

ltfssdcl.dtx
 %  \begin{macro}{\freeze@math@version}
 % \changes{v3.0x}{2021/09/26}{Macro added for (gh/676)}
 % \changes{v3.1a}{2022/09/17}{New logic for freezing math versions (gh/921)}
 ...
 %    If this is executed after a math display, we may have to arrange
 %    for ignoring spaces, because they are now hidden if
 %    the tokens from above intervene. This is signaled by the 2e
 %    switch \texttt{@ignore} which is set in \cs{frozen@everymath} and
 %    \cs{frozen@everydisplay}.
 %
 %    This is all 2e code so we use that syntax.
 % \changes{v3.0z}{2022/07/04}{Ignore spaces if necessary (gh/886)}
 %    \begin{macrocode}
         \if@ignore \ignorespaces \fi
     }
 }

ltfssbas.dtx
 % \begin{macro}{\frozen@everydisplay}
 ...
 % \changes{v3.2k}{2022/07/04}{Ignore spaces if necessary (gh/886)}
 %    The issue with handling of spaces was found in 2022, but it is
 %    really a bug fix for the code added in 2021/11.
 ...
 \frozen@everydisplay = {%
   \aftergroup\@ignoretrue  \aftergroup\ignorespaces
   \check@mathfonts
   \the\everydisplay}

 % \begin{macro}{\frozen@everymath}
 ...
 % \changes{v3.2k}{2022/07/04}{Ignore spaces if necessary (gh/886)}
 %    The frozen code for inline math is similar, except that here we
 %    do not want to drop following spaces.
 ...
 \frozen@everymath = {%
   \aftergroup\@ignorefalse
   \check@mathfonts
   \the\everymath}

でも、ディスプレイ数式の行間に「ほぼ 1 行分余分な空白」が入
っているとのことですので、行末の改行をうまく \ignorespaces
できていないのでしょうか。

それならば、localmathalphabets の値を 0 にしてみたり、(p)latexrelease
で 2021/09/26 よりも前に巻き戻したりしたらどうなるのか見てみ
たいところですが、私の手元のシステムは W32TeX [2020/07/19] と
古いので、試してみることができません…。
ut への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
> 不具合には既に対処済みであるという
> ことのようにも見えます。
・・・
> 行末の改行をうまく \ignorespaces
> できていないのでしょうか。

あー、\eqno が挟まってるからですか?!

\eqno がある場合、\aftergroup の引数(というのでしょうか)は
どこに移動することになるのでしょう?
ut への返信

Re: \eqno で行間に余計な空白が入る?

- みなも の投稿
> それならば、localmathalphabets の値を 0
> にしてみたり、(p)latexrelease
> で 2021/09/26
> よりも前に巻き戻したりしたらどうなるのか

試してみました。

localmathalphabet については先の発言の前に試していたのですが,
「効果なし」
でした。(なので,「よくわからない」発言でした。)

(p)latexrelease で 2021/09/26 は
「効果あり」
でした。やはり最近のカーネルの変更が原因のようですね。

おそらく「\eqno がある場合、\aftergroup の引数」が悪さをしているのでは
という指摘が当たっているのだと思いますが。。。

LaTeX チームとしてはプリミティブまわりに手を加えるよりは,
マクロ (\[ \] や equation 環境) で処理しようということのようですね。
「プリミティブに何か仕込んで思わぬ副作用が出るよりは」
ということなんでしょうが,
逆にプリミティブの挙動が変わるのも,それはそれで怖い気がします。
ut への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
# 相変わらずしつこくてすいません…。

昨日:

> あー、\eqno が挟まってるからですか?!
>
> \eqno がある場合、\aftergroup の引数(というのでしょうか)は
> どこに移動することになるのでしょう?

と申し上げましたが、もしかしたら、\aftergroup がうまくいって
ないのは、\eqno のせいじゃなくて、\cdots のせいかも知れません。

私の手元ではテストできないので、最近の TeX Live をお使いの方、
どなたかに試してみていただけたら嬉しいです:

\documentclass{jarticle}
\begin{document}

$$x^2 + 3x + 2 = 0 \eqno\cdots(*)$$
$$(x + 1)(x + 2) = 0$$

$$x^2 + 3x + 2 = 0 \eqno(123)$$
$$(x + 1)(x + 2) = 0$$

\end{document}

(まったく的外れかも知れませんので、お手数をお掛けしてしまい
ますことを、予めお詫び申し上げます)
ut への返信

Re: \eqno で行間に余計な空白が入る?

- みなも の投稿
こちらでも試してみました。(OS は Windows11 Home)

結果,和田 勇 さんと同じく,
\cdots の有無は関係なく,\eqno があれば余計な空白が空いてしまいました。
みなも への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
和田 勇 さま、みなも さま

私の下手な思い付きに応答をしてくださいまして、本当にありがと
うございます。

結局のところ、「的外れ」だったようです…(すいません)。

お二方ともお忙しいところご協力を賜り、本当にありがとうござい
ました。

(和田さん、みなも さん以外にもお手元で試してくださった方が
いらっしゃいましたら、その皆さまにも御礼とお詫びを申し上げ
ます)
ut への返信

Re: \eqno で行間に余計な空白が入る?

- はやて (h20y6m) の投稿
(Markdownだとコードブロックなのに `<`, `>` が勝手に変換されてしまうのでプレーンテキストに変更)

> \eqno がある場合、\aftergroup の引数(というのでしょうか)は
> どこに移動することになるのでしょう?

最小化していくと以下のようになるようです。

```
%#!etex

\def\ignorefalse{\global\let\ifignore\iffalse}
\def\ignoretrue {\global\let\ifignore\iftrue}

\everydisplay={\aftergroup\ignoretrue \aftergroup\ignorespaces}
\everymath={\aftergroup\ignorefalse}

\parindent0pt

\tracingonline=1
\tracingmacros=2
\tracingcommands=3
\tracinggroups=1
\tracingnesting=2

Test
$$
% entering math shift group (level 1)
% \everydisplay->\aftergroup \ignoretrue \aftergroup \ignorespaces
  1+1=2
  \eqno
% entering math shift group (level 2)
% \everymath->\aftergroup \ignorefalse
  ...(1)
$$
% leaving math shift group (level 2)
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
% \ignorefalse ->\global \let \ifignore \iffalse                <- !!
% blank space                                                  <- extra space
space.\par
space.\par

\tracingonline=0
\tracingmacros=0
\tracingcommands=0
\tracinggroups=0
\tracingnesting=0

\bye
```

`\aftergroup` でされたトークンはその時点のグループが終了したときに入力の先頭に挿入されます。(挿入されるだけで展開や実行はされない。)複数の `\aftergroup` があったときは実行された順に入力の先頭から並ぶように挿入されます。

閉じの `$$` のところでは `$$` のグループ(level 1)と `\eqno` のグループ(level 2)の両方が終了します。

まず、`\eqno` のグループ(level 2)が終了し、このグループで `\aftergroup` された `\ignorefalse` が入力の先頭に挿入されます。(この時点では `\ignorefalse` は展開・実行されません。)

次に、`$$` のグループ(level 1)が終了し、このグループで `\aftergroup` された `\ignoretrue\ignorespaces` が入力の先頭(つまり `\ignorefalse` の手前)に挿入されます。

結果として、`$$` 終了時点で、入力の先頭は `\ignoretrue\ignorespaces\ignorefalse` という状態になります。
このため、`\ignorespaces` の後ろに `\ignorefalse`(`\global\let`)が来るので、後続のスペースが無視されないということになります。
はやて (h20y6m) への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
# みなも さんを差し置いて(?)、私が反応してしまってもよいも
# のか、若干躊躇しますが。

はやて (h20y6m) さん、詳しいご説明をありがとうございます!

> 最小化していくと以下のようになるようです。

\eqno のところで math shift していて、そこで \everymath が入
るのですか!!!
(で、gh/886 対応でも、inline math の後ろではスペースが削られ
ないように \everymath では \@ignorefalse にしてあったので、そ
れが利いているわけですね)
(それにしても、gh/886 対応の際に、\eqno が入る可能性は想定さ
れてなかったのですかね…?)

一応手元でも \tracingcommands で処理を追うくらいのことはして
みていたのですけれど、ご投稿を最初拝見した際には:

 「\tracingcommands が 3?」「\tracinggroups?」「\tracingnesting?」

と少々戸惑いましたが、e-TeX でいろいろ追加されてたのですね。
(私は TeXbook レベルの show と tracing しか頭にありませんで
した…)

今回の件は、私の手元では試すこともできないことでしたが、丁寧
にご説明をしていただき、とても勉強になりました。本当にありが
とうございました。
ut への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
> \eqno のところで math shift していて、そこで \everymath が入
> るのですか!!!

The TeXbook にもちゃんと書かれていました…:

p. 293 (Chapter 26: Summary of Math Mode)

■〈eqno〉〈math mode material〉|$|. Here〈eqno〉stands for either |\eqno| or |\leqno|;
these commands are allowed only in display math mode. Upon reading〈eqno〉, TeX
enters a new level of grouping, inserts the |\everymath| tokens, and enters non-display
math mode to put the〈math mode material〉into a math list. When that math list is
completed, TeX converts it to a horizontal list and puts the result into a box that will
be used as the equation number of the current display. The closing |$| token will be put
back into the input, where it will terminate the display.

ただ、この説明だけだと、必ずしも:

  % leaving math shift group (level 2)
  % leaving math shift group (level 1)
  % \ignoretrue ->\global \let \ifignore \iftrue
  % \ignorespaces
  % \ignorefalse ->\global \let \ifignore \iffalse 

という風にグループが連続して閉じるというのは、すぐには分から
ないような気もしないではないのですけれど。

(素朴に考えると:

  % leaving math shift group (level 2)
  % \ignorefalse ->\global \let \ifignore \iffalse 
  % leaving math shift group (level 1)
  % \ignoretrue ->\global \let \ifignore \iftrue
  % \ignorespaces

という順番になりそうに思えてしまいますので)
(その辺り、simple group や semi simple group と、math shift group
とでは、振舞いが違うのでしょうかね)
ut への返信

Re: \eqno で行間に余計な空白が入る?

- ut の投稿
> simple group や semi simple group と、math shift group
> とでは、振舞いが違うのでしょうかね

なんて言ってないで、自分でやってみれば良いのですよね:

------------------------------------------------------------
(1)simple groups

\def\cmdX{ddd }
\def\cmdY{ccc }

{\aftergroup\cmdX aaa {\aftergroup\cmdY bbb }}

% ---> aaa bbb ccc ddd

{begin-group character {}
{entering simple group (level 1) at line 9}
{\aftergroup}
{the letter a}
{begin-group character {}
{entering simple group (level 2) at line 9}
{\aftergroup}
{the letter b}
{end-group character }}
{leaving simple group (level 2) entered at line 9}
{the letter c}
{end-group character }}
{leaving simple group (level 1) entered at line 9}
{the letter d}

------------------------------------------------------------
(2)\eqno in display math

\def\cmdX{ddd }
\def\cmdY{ccc }
\everydisplay={\aftergroup\cmdX}
\everymath={\aftergroup\cmdY}

$$aaa \eqno bbb $$

% --->        aaa    bbb
%    ddd ccc

{math shift character $}
. . .
{endgroup}
{leaving semi simple group (level 2) entered at line 11}
{\relax}
{\let}
{\def}
{\aftergroup}
{the letter a}
{the letter a}
{the letter a}
{blank space  }
{\eqno}
{entering math shift group (level 2) at line 11}
{math mode: \let}
{\def}
{\aftergroup}
{the letter b}
{the letter b}
{the letter b}
{blank space  }
{math shift character $}
{leaving math shift group (level 2) entered at line 11}
{leaving math shift group (level 1) entered at line 11}
{horizontal mode: the letter d}
{blank space  }
{the letter c}

------------------------------------------------------------
素朴な想定とは異なるのですけれど、これまでの流れからしたら、
こういう結果になるというのは、当然とも言えそうです。