\ThisStyle \SavedStyle は非常に遅いです...代替手段はありますか?

\ThisStyle \SavedStyle は非常に遅いです...代替手段はありますか?

最初のバージョンを使用してカスタマイズされた帽子のグリフを操作しながらこの解決策pdflatexドキュメントのコンパイルに長い時間がかかり始めました。リンクされた回答では、これはより遅い解決策であると述べられていますが、最初はヒックアップするほど遅いだけで、問題ではありませんでした。その後、2 つのスタックされた帽子を使用した後、許容できるほど遅くなりました。そして、調査して 3 つの帽子をスタックした後、永遠に遅くなりました。

要約すると、次のようになります。

  \documentclass[12pt, a4paper]{article}
  \usepackage{scalerel}

  \begin{document}
  \ensuremath{
  \ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
      \SavedStyle\ThisStyle{
          \SavedStyle . }}}}}}}
  }}
  \end{document}

pdflatexまたは を使用すると、15 秒かかりますlatex。ネスト レベルを 1 つ減らすと 2 秒に短縮され、例よりも 1 レベル追加すると 269 秒になります。

明らかに、指数関数的な何かが起こっている。スケールレル、 のコード\SavedStyle\ThisStyle次のとおりです。

\def\SavedStyle{\csname @mstyle\m@switch\endcsname}


\newcommand\ThisStyle[1]{%
  \ifmmode%
    \def\@mmode{T}\mathchoice%
      {\edef\m@switch{D}\LMex=1ex\relax\LMpt=1pt\relax#1}%
      {\edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1}%
      {\edef\m@switch{S}\LMex=\scriptstyleScaleFactor ex\relax%
                        \LMpt=\scriptstyleScaleFactor pt\relax#1}%
      {\edef\m@switch{s}\LMex=\scriptscriptstyleScaleFactor ex\relax%
                        \LMpt=\scriptscriptstyleScaleFactor pt\relax#1}%
  \else%
    \def\@mmode{F}%
    \edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1%
  \fi%
}

私の推測では、引数は\ThisStyle各レベルで 4 回拡張されます。言い換えると、\mathchoiceは怠惰ではありません。

#1これらの引数の外側を取り\mathchoice、同じ動作を維持する方法はありますか? これら\m@switch\LMex定義は次の「}」を超えて存続しますか?

そうでない場合、同等のことを実行する他の方法はありますか\ThisStyle?\SavedStyleネストの深さに関して線形時間で動作し、再入可能性が存在する場合でも正しく動作するものは思いつきません。

答え1

短い答え: いいえ — すべての状況で、または 1 回の LaTeX パスでこれを正しく実行する方法はありません。


多くの学習と実験を経て、これを回避する唯一の方法は次のようなものであるようですマヌエルの回答とコメントはこちら\whatIsTheMathStyleHere(というものは存在しない)LuaTeXを使用しない限り)。\mathchoiceコマンドはTeXプリミティブです4つのオプションから選択する遅い「遅い」の意味を理解するには、TeXがいくつかの消化段階: 目、口、食道、胃があり、それぞれが意味的に意味のあるトークンのサブセットを処理して、論理ドキュメントを最終的な視覚ドキュメントに近い形式に変換します。時々前の段階に戻ってしまうこともあります。(しかし、私たちが期待するその信じられないほど優れた組版の知能は、ある程度の複雑さを正当化するのではないでしょうか?)\mathchoice そして引数 の内部は、\mathchoiceそれ自身が適用される前にマクロ展開されます。実際、私が知る限り、展開だけでなく、 などの他の TeX コマンドも の\ifx前に処理される\mathchoiceため、処理の各段階内には複数の階層化されたサブ段階がある可能性があります。

Manuel の代替手段である は\mathcase、巧妙なトリックを使用して、ナノスケールのスペースを挿入します。このスペースのサイズは、数式スタイルによって異なります。次に、スペースのサイズをチェックしてスタイルを決定します。最終的な数式スタイルは、ドキュメントが完全に解決された構造になった後にのみ決定されるはずなのに、これはどのように機能するのでしょうか。これは、パッケージを使用して行われますzref-savepos。 のドキュメントを読むとzref、次の注記があります。

ページの位置はすぐにはわかりません。まず、TEX の非同期出力ルーチンによってページを構築する必要があります。したがって、位置がわかるのは、ページが出荷される時間です。したがって、最初の実行時に情報が記録され、2 回目の実行で使用できるようになる参照システムが役立ちます。

言い換えれば、正しい数学のスタイルは出荷この時点では、いかなる意思決定構造でも使用できません\ifが、AUX ファイルに保存され (以下の例の AUX ファイルを調べるとわかるように)、2 回目のパスで使用できるようになります。

残念ながら、これにより、カスケード式の数式スタイルがネストされた一連の s に伝播する次のような問題が発生します\mathcase。ネストが N レベルの深さの場合、ドキュメントは N 回コンパイルされるまで安定しているとは保証されません。次に例を示します。

(これはマヌエルの答え(ここではドキュメントの本文を変更しました。)

\documentclass{scrartcl}

\usepackage{mathtools}


\usepackage{zref-savepos}
\newcount\mmstynum
\newcount\tmpnum
\protected\def\getmsty
 {\global\advance\mmstynum1 %
  \expandafter\getstyA\expandafter{\number\mmstynum}}
\protected\def\getstyA#1%
 {\zsaveposx{mmsty-#1-a}%
  \mathchoice{\kern4sp}{\kern3sp}{\kern2sp}{\kern1sp}%
  \zsaveposx{mmsty-#1-b}
  \tmpnum=\numexpr
            \zposx{mmsty-#1-b} - \zposx{mmsty-#1-a}
          \relax
   \ifcase\tmpnum\or\kern-1sp \or\kern-2sp \or\kern-3sp \or\kern-4sp \fi}
\protected\def\mstycase
 {\ifcase\tmpnum\expandafter\gobblefour\or\expandafter\usefourth\or
   \expandafter\usethird\or\expandafter\usesecond\or
   \expandafter\usefirst\else\expandafter\gobblefour\fi}
\protected\def\mathcase{\getmsty\mstycase}

\long\def\gobblefour#1#2#3#4{}
\long\def\usefourth#1#2#3#4{#4}
\long\def\usethird#1#2#3#4{#3}
\long\def\usesecond#1#2#3#4{#2}
\long\def\usefirst#1#2#3#4{#1}


\def\tmpa{If this prints it means it doesn't work}
\newcommand*\foo
 {\mathcase % compare with \mathchoice
   {\def\tmpa{displaystyle}}
   {\def\tmpa{textstyle}}
   {\def\tmpa{scriptstyle}}
   {\def\tmpa{scriptscriptstyle}}
  \text\tmpa}

\let\savedstyle\displaystyle

\def\thisstyle#1{\begingroup\mathcase{\let\savedstyle\displaystyle}{\let\savedstyle\textstyle}{\let\savedstyle\scriptstyle}{\let\savedstyle\scriptscriptstyle}#1\endgroup}

\begin{document}

\[
\sum \scriptstyle \sum \thisstyle{%
    \fbox{\( \sum \savedstyle \sum \thisstyle{%
    \fbox{\( \sum \savedstyle \sum \thisstyle{%
    \fbox{\( \sum \savedstyle \sum \)}%
    }\)}%
    }\)}%
}
\]

\end{document}

コンパイル中に TeXworks ビューアで PDF を見ると、次のようになります。

最初のパスの後:

1位

2回目のパス後:

2番目

3回目のパス後:

3位

4回目のパス後:

4番目

したがって、このソリューションでは、パスの数を減らして各パスの速度を向上させます。(ただし、ドキュメントがまだ安定していない場合に警告も表示されると便利です。) 完璧なソリューションではありませんが、TeX の性質を考慮すると、これが可能な限り最良の代替手段であると確信しています (また、TeX 自体は、近い将来にこの点で変更される可能性は低いです)。

パッケージもありますmathstyle議論はここで参照)、これは\mathchoiceすべての数式モード区切り文字を利用することで回避します(ただし\(どうやらそうではない!)、そしてTeXの帯域外で、現在の数式スタイルがどうなるかを追跡するためのロジックを挿入します。しかし、アディティアのコメントはこちら\over、TeX の動作を予測できない場合があります。たとえば、TeX プリミティブの使用などです\atop。(ただし、このコメントは 5 年前のものです。その間に改善されたのでしょうか?)

したがって、最善の答えは、可能な限りネストのレベル数を減らすことです(a は、、、など\mathchoiceに含まれていることに注意してください)\mathchoice。 (例:\ThisStyle\text\mathpalette\TextStyle前提となる質問でいくつかの冗長なsを削除しました)、または常識的な推論を使用して数学のスタイルを推測できる場合は、\mathchoiceそれを短絡させるためにローカルで再定義する

全体的に、これは驚くべき結果です。LaTeX で何かやりたいと思ったのはこれが初めてでしたが、非現実的であることがわかりました。また、ハッキングを試みるうちに\mathchoice、マクロ言語の恐ろしさに遭遇しました。マクロ言語では、何がどのような順序で展開されるのかまったくわかりません。(「古典的な」方法\expandafter\expandafter\expandafter\expandafter\expandafter...この解決策、何かがおかしいと分かります。) 最後に、70 年代のソフトウェアの場合、 のセマンティクスは\mathchoice、その本来の目的が単一のカスタム シンボルをタイプセットすることだけであったとしても、いくぶん非効率に思えます...

関連情報