\ThisStyle \SavedStyle dolorosamente lento... ¿alternativas?

\ThisStyle \SavedStyle dolorosamente lento... ¿alternativas?

Mientras trabajaba con glifos de sombrero personalizados usando la primera versión deesta solución, pdflatexempezó a tardar mucho en compilar un documento. Esa respuesta vinculada señala que es una solución más lenta, pero inicialmente fue muy lenta, lo cual no importó. Luego se volvió tolerablemente lento después de usar dos sombreros apilados. Y después de que fui a investigar y apilé tres sombreros, todo se volvió eterno.

He aquí una razón resumida:

  \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}

Esto tarda 15 segundos con pdflatexo latex. Si eliminamos un nivel de anidamiento, se reduce a 2 segundos, y si agregamos un nivel más que en el ejemplo, obtenemos 269 segundos.

Es evidente que está sucediendo algo exponencial. Mirando haciaescalarel.sty, el código para \SavedStyley \ThisStylees el siguiente:

\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%
}

Mi conjetura es que el argumento \ThisStylese amplía cuatro veces en cada nivel. En otras palabras, \mathchoiceno es perezoso.

¿Hay alguna manera de sacar a #1relucir esos \mathchoiceargumentos y seguir manteniendo el mismo comportamiento? ¿Perduran esas \m@switchdefiniciones \LMexmás allá del siguiente " }"?

Si no es así, ¿existe algún otro método para hacer el \ThisStyleequivalente \SavedStyle? No se me ocurre nada que funcione en tiempo lineal con respecto a la profundidad de anidamiento y que siga funcionando correctamente en presencia de reentrada.

Respuesta1

Respuesta corta: no, no hay forma de hacer esto correctamente en todas las situaciones o en una sola pasada de LaTeX.


Después de mucho aprendizaje y experimentación, parece que la única forma de solucionar este problema es algo comoRespuesta y comentario de Manuel aquí.. No existe tal cosa como \whatIsTheMathStyleHere(a menos que estemos en LuaTeX). El\mathchoiceEl comando es una primitiva TeX..Se hace la elección de las cuatro opciones.tarde. Para entender lo que significa "tarde", debemos apreciar que TeX tienealgunas etapas digestivas: ojo, boca,garganta, estómago, cada uno de los cuales transforma el documento lógico en una forma más cercana al documento visual final, trabajando a través de un subconjunto de tokens semánticamente significativos.A veces se vuelve a la etapa anterior.(Pero, ¿la inteligencia tipográfica casi demasiado buena para ser verdad que esperamos no justifica cierto grado de complejidad?) Entonces, lo que rodea\mathchoice yEl interior de sus argumentos se expande macro antes de \mathchoiceaplicarse. De hecho, hasta donde yo sé, no solo la expansión, sino también otros comandos TeX, como \ifx, se procesan antes \mathchoice, por lo que dentro de cada etapa de procesamiento podría haber varias subetapas estratificadas.

La alternativa de Manuel, llamada \mathcase, utiliza un truco inteligente, donde se inserta un espacio a nanoescala, de un tamaño que depende del estilo matemático. Y luego comprueba el tamaño del espacio y determina el estilo. ¿Cómo puede funcionar eso, si se supone que el estilo matemático final en todas partes debe determinarse sólo después de que el documento se convierta en una estructura completamente resuelta? Lo hace utilizando el zref-savepospaquete. Al leer la documentación de zref, hay una nota:

La posición de la página no se conoce instantáneamente. Primero, la página debe construirse mediante la rutina de salida asincrónica de TEX. Por lo tanto, el momento en el que se conoce la posición es el tiempo de envío de la página. Por lo tanto, resulta útil un sistema de referencia en el que la información se registra en la primera ejecución y se pone a disposición para su uso en la segunda ejecución.

En otras palabras, el estilo matemático correcto se determina enenviar, momento en el que no se puede utilizar en ninguna \ifu otras estructuras de toma de decisiones, pero se almacena en el archivo AUX (como puede ver al inspeccionar el archivo AUX en el ejemplo siguiente) y queda disponible durante la segunda pasada. .

Desafortunadamente, esto causa el siguiente tipo de problema, con estilos matemáticos en cascada que se propagan a lo largo de una serie anidada de \mathcases: si el anidamiento tiene N niveles de profundidad, entonces no se garantiza que el documento sea estable hasta que se compila N veces. Por ejemplo:

(Esto es dela respuesta de manuel, donde acabo de cambiar el cuerpo del documento).

\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}

Al mirar el PDF en el visor TeXworks mientras lo compilamos, vemos:

Después del primer pase:

1er

Después del segundo pase:

2do

Después del tercer pase:

3er

Después del cuarto pase:

4to

Entonces, la solución compensa el número de pasadas para mejorar la velocidad de cada pasada. (Aunque sería bueno si también le avisara cuando el documento aún no sea estable). Si bien no es una solución perfecta, estoy convencido de que es la mejor alternativa posible, dada la naturaleza de TeX (y TeX es poco probable que cambie en este aspecto en el futuro previsible).

También está elmathstyle paquete (ver discusión aquí), que funciona alrededor\mathchoice aprovechando todos los delimitadores del modo matemático (perono\(aparentemente!), e inyectando algo de lógica para realizar un seguimiento de cuál será el estilo matemático actual, fuera de línea con TeX. Pero, como se señala enEl comentario de Aditya aquí., hay casos en los que no logra predecir el comportamiento de TeX. Por ejemplo, con el uso de \overprimitivas \atopTeX. (Sin embargo, el comentario tiene 5 años. ¿Quizás haya mejorado mientras tanto?)

Entonces, la mejor respuesta es reducir el número de \mathchoiceniveles de anidamiento (tenga en cuenta que a \mathchoiceestá contenido en \ThisStyle, \text,\mathpalette , etc.) cuando sea posible (p. ej.Eliminé algunos redundantes\TextStyle mensajes redundantes en la pregunta precursora.), o si puedes inferir el estilo matemático usando un razonamiento de sentido común, podríasredefinir\mathchoice localmente para cortocircuitarlo.

Considerándolo todo, es un resultado sorprendente. Esta es la primera vez que quise hacer algo con LaTeX y resultó poco práctico. Además, mientras intentaba hackear \mathchoice, me encontré con todos los horrores de los lenguajes macro, donde nunca se sabe qué se expandirá y en qué orden. (Basta con echar un vistazo a la forma "clásica" de ser\expandafter\expandafter\expandafter\expandafter\expandafter... enesta solución, y sabes que algo anda mal.) Finalmente, para el software de los años setenta, la semántica de \mathchoiceparece algo ineficiente, incluso si su propósito es simplemente componer un único símbolo personalizado...

información relacionada