1

I'm trying to write a package to help setting up the multi-language configuration and to define theorem-like environments with multi-language support. The result is great but the code takes very long time to run.

Thus, I separated the most time-consuming part in the MWE below. It mainly consists of two part, one part with \UseLanguage, the other with \CreateTheorem. Due to my limited knowledge of LaTeX, these two macros are written in a very complicated manner.

My question is: is it possible to modify these two macros in some way so that they can achieve the same result, but in less time?

ADD: After some trial and error, I found that the time seems to be mainly consumed by these few lines on \crefname:

\crefname{#1#2#3}%
        {\csname#1name#2\endcsname}%
        {\csname#1name#2\endcsname}%
\Crefname{#1#2#3}%
        {\csname#1name#2\endcsname}%
        {\csname#1name#2\endcsname}%

But I can't see what can be optimized up to this point.


(The complete code can be found in: https://github.com/Jinwen-XU/ProjLib, the MWE below contains part of the code in PLlang.sty and PLthm.sty.)

Below is a MWE.

%! TEX program = xelatex
\documentclass{article}

\makeatletter

%%------------------------------------------------------- %% PART I %%------------------------------------------------------- \RequirePackage{iftex}

\newcommand\englishABBR{EN} \newcommand\frenchABBR{FR} \newcommand\ngermanABBR{DE} \newcommand\chineseABBR{CN} \newcommand\tchineseABBR{TC} \newcommand\japaneseABBR{JP} \newcommand\russianABBR{RU}

\ifPDFTeX\else \PassOptionsToPackage{japanese,russian}{babel} \fi \PassOptionsToPackage{italian,portuguese,brazilian,spanish.noquoting,ngerman,french,english,shorthands=off}{babel} \PassOptionsToPackage{italian,brazilian,spanish,ngerman,french,english}{cleveref} \RequirePackage{babel} \frenchsetup{PartNameFull=false}

\newcommand{\PLlang@langconfig@common}{} \newcommand{\PLlang@langconfig@chinese}{% \renewcommand{\languagename}{chinese}% } \newcommand{\PLlang@langconfig@tchinese}{% \renewcommand{\languagename}{tchinese}% } \newcommand{\PLlang@langconfig@japanese}{% \selectlanguage{japanese}% } \newcommand{\PLlang@langconfig@english}{% \selectlanguage{english}% } \newcommand{\PLlang@langconfig@french}{% \selectlanguage{french}% \def\frenchpartname{Partie}% } \newcommand{\PLlang@langconfig@german}{% \selectlanguage{ngerman}% } \newcommand{\PLlang@langconfig@russian}{% \selectlanguage{russian}% }

\RequirePackage{setspace} \def\PL@config@linespacing{\setstretch{1.00}} \def\PL@config@CJKlinespacing{\onehalfspacing} \newcommand{\PLsetlinespacing}[1]{\renewcommand{\PL@config@linespacing}{#1}} \newcommand{\PLsetCJKlinespacing}[1]{\renewcommand{\PL@config@CJKlinespacing}{#1}} \newcommand{\UseLanguageCORE}[1]{% \PLlang@langconfig@common% \ifstrequal{#1}{chinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{Chinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{schinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{SChinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{simplifiedchinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{SimplifiedChinese}{\PL@config@CJKlinespacing\PLlang@langconfig@chinese}{}% \ifstrequal{#1}{tchinese}{\PL@config@CJKlinespacing\PLlang@langconfig@tchinese}{}% \ifstrequal{#1}{TChinese}{\PL@config@CJKlinespacing\PLlang@langconfig@tchinese}{}% \ifstrequal{#1}{traditionalchinese}{\PL@config@CJKlinespacing\PLlang@langconfig@tchinese}{}% \ifstrequal{#1}{TraditionalChinese}{\PL@config@CJKlinespacing\PLlang@langconfig@tchinese}{}% \ifstrequal{#1}{japanese}{\PL@config@CJKlinespacing\PLlang@langconfig@japanese}{}% \ifstrequal{#1}{Japanese}{\PL@config@CJKlinespacing\PLlang@langconfig@japanese}{}% \ifstrequal{#1}{english}{\PL@config@linespacing\PLlang@langconfig@english}{}% \ifstrequal{#1}{English}{\PL@config@linespacing\PLlang@langconfig@english}{}% \ifstrequal{#1}{french}{\PL@config@linespacing\PLlang@langconfig@french}{}% \ifstrequal{#1}{French}{\PL@config@linespacing\PLlang@langconfig@french}{}% \ifstrequal{#1}{ngerman}{\PL@config@linespacing\PLlang@langconfig@german}{}% \ifstrequal{#1}{german}{\PL@config@linespacing\PLlang@langconfig@german}{}% \ifstrequal{#1}{German}{\PL@config@linespacing\PLlang@langconfig@german}{}% \ifstrequal{#1}{russian}{\PL@config@linespacing\PLlang@langconfig@russian}{}% \ifstrequal{#1}{Russian}{\PL@config@linespacing\PLlang@langconfig@russian}{}% } \newcommand{\UseLanguage}[1]{% \ifx@onlypreamble@notprerr% \UseLanguageCORE{#1}% \else% \AfterEndPreamble{\UseLanguageCORE{#1}}% \fi% }

\UseLanguage{English}

%%------------------------------------------------------- %% PART II %%-------------------------------------------------------

\RequirePackage{amsmath,amsthm} \RequirePackage{aliascnt} \PassOptionsToPackage{nameinlink}{cleveref} \RequirePackage{cleveref}

\RequirePackage{xstring} \newcommand\PassFirstToSecond[2]{#2{#1}}% \NewDocumentCommand{\CreateTheorem}{sm}{% \begingroup \protected@edef\temp{#2}% \expandafter\IfEndWith\expandafter{\temp}{}{% \expandafter\StrGobbleRight\expandafter{\temp}{1}[\temp]% \PassFirstToSecond{}% }{% \PassFirstToSecond{}% }% {\expandafter\PassFirstToSecond% \expandafter{\temp}{\endgroup\InnerCreateTheorem{#1}}}% }% \NewDocumentCommand{\InnerCreateTheorem}{mmmod<>d()}{% \IfBooleanTF{#1}{% \IfValueTF{#4} {@firstoftwo} {\IfValueTF{#5}{@firstoftwo}{@secondoftwo}}% }{% \IfValueTF{#4} {\IfValueTF{#5}{@firstoftwo}{@secondoftwo}}{ @secondoftwo} }% {% \GenericError{}% {\string\CreateTheorem\space syntax error\on@line}{% You cannot call the starred variant with optional argument,\MessageBreak nor call the unstarred variant with several optional arguments.}% {}% }{% \IfValueTF{#6}{% \IfBooleanTF{#1}{% \ifcsmacro{#2#3}% {\renewenvironment{#2#3}{\begin{#6}}{\end{#6}}}% {\newenvironment{#2#3}{\begin{#6}}{\end{#6}}}% }{% \ifcsmacro{#2#3}% {\renewenvironment{#2#3}{\begin{#6}}{\end{#6}}}% {\newenvironment{#2#3}{\begin{#6}}{\end{#6}}}% } }{% \IfBooleanTF{#1}{% \newtheorem{#2EN#3}{\csname#2nameEN\endcsname} \newtheorem{#2FR#3}{\csname#2nameFR\endcsname} \newtheorem{#2DE#3}{\csname#2nameDE\endcsname} \newtheorem{#2CN#3}{\csname#2nameCN\endcsname} \newtheorem{#2TC#3}{\csname#2nameTC\endcsname} \newtheorem{#2JP#3}{\csname#2nameJP\endcsname} \newtheorem{#2RU#3}{\csname#2nameRU\endcsname} }{% \IfValueTF{#5}{% \newcounter{#2#3}[{#5}]% \expandafter\renewcommand\expandafter% \csname the#2#3\expandafter\endcsname% \expandafter{\csname the#5\endcsname.\arabic{#2#3}}% }{% \IfValueTF{#4} {\newaliascnt{#2#3}{#4}} {\newcounter{#2#3}}% }% %--------------------------------------------------------------- \CreateTheoremNumberedLikeAliasCounter{#2}{EN}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{FR}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{DE}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{CN}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{TC}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{JP}{#3}% \CreateTheoremNumberedLikeAliasCounter{#2}{RU}{#3}% %--------------------------------------------------------------- }% \NewDocumentEnvironment{#2#3}{} {\csname#2\csname\languagename ABBR\endcsname#3\endcsname}% {\csname end#2\csname\languagename ABBR\endcsname#3\endcsname}% } }% }% \NewDocumentCommand{\CreateTheoremNumberedLikeAliasCounter}{mmm}{% \newaliascnt{#1#2#3}{#1#3}% \newtheorem{#1#2#3}[{#1#2#3}]{\csname#1name#2\endcsname}% \aliascntresetthe{#1#2#3}% \crefname{#1#2#3}% {\csname#1name#2\endcsname}% {\csname#1name#2\endcsname}% \Crefname{#1#2#3}% {\csname#1name#2\endcsname}% {\csname#1name#2\endcsname}% }%

\def\theoremnameEN{Theorem}\def\lemmanameEN{Lemma} \def\propositionnameEN{Proposition} \def\corollarynameEN{Corollary} \def\propertynameEN{Property} \def\factnameEN{Fact} \def\conjecturenameEN{Conjecture} \def\definitionnameEN{Definition} \def\axiomnameEN{Axiom} \def\assumptionnameEN{Assumption} \def\conventionnameEN{Convention} \def\hypothesisnameEN{Hypothesis} \def\notationnameEN{Notation} \def\examplenameEN{Example} \def\problemnameEN{Problem} \def\questionnameEN{Question} \def\exercisenameEN{Exercise} \def\remarknameEN{Remark} \expandafter\def\csname definition-propositionnameEN\endcsname{\definitionnameEN-\propositionnameEN} \expandafter\def\csname definition-theoremnameEN\endcsname{\definitionnameEN-\theoremnameEN}

\CreateTheorem{theorem}<section> \CreateTheorem{lemma}[theorem] \CreateTheorem{proposition}[theorem] \CreateTheorem{corollary}[theorem] \CreateTheorem{definition-proposition}[theorem] \CreateTheorem{definition-theorem}[theorem] \CreateTheorem{property}[theorem] \CreateTheorem{fact}[theorem] \CreateTheorem{conjecture}[theorem] \CreateTheorem{theorem} \CreateTheorem{lemma} \CreateTheorem{proposition} \CreateTheorem{corollary} \CreateTheorem{definition-proposition} \CreateTheorem{definition-theorem} \CreateTheorem{property} \CreateTheorem{fact} \CreateTheorem{conjecture}

\CreateTheorem{definition}[theorem] \CreateTheorem{axiom}[theorem] \CreateTheorem{assumption}[theorem] \CreateTheorem{convention}[theorem] \CreateTheorem{hypothesis}[theorem] \CreateTheorem{notation}[theorem] \CreateTheorem{example}[theorem] \CreateTheorem{problem}[theorem] \CreateTheorem{question}[theorem] \CreateTheorem{exercise}[theorem] \CreateTheorem{definition} \CreateTheorem{axiom} \CreateTheorem{assumption} \CreateTheorem{convention} \CreateTheorem{hypothesis} \CreateTheorem{notation} \CreateTheorem{example} \CreateTheorem{problem} \CreateTheorem{question} \CreateTheorem{exercise}

\CreateTheorem{remark}<section> \CreateTheorem{remark}

%%-------------------------------------------------------

\makeatother

\begin{document}

Some text

% \begin{theorem} % Some text % \end{theorem}

\end{document}

Jinwen
  • 8,518
  • How did you determine that that's where most time is spent? I'm not an expert but on the face of it, it looks unlikely. Also, how many seconds do you mean by "very long time"? – ShreevatsaR May 12 '21 at 18:50
  • @ShreevatsaR I just comment out some of the code and observe the change of the compile time. As for the MWE above, it takes about 7.5s on my PC, but without the \crefname lines it only takes about 1.8s. And if all code in the preamble is commented, it takes about 0.9s. Thus, my goal is to make the code compile in less than 3s. – Jinwen May 13 '21 at 00:36
  • You can do this much more effective if you will use only TeX primitives. If you are able to specify, what is the intend of \CreateTheorem then I can show you, hot to implement it without any xparse and similar tools, simply by TeX primitives. And you will see that the result will take only 0.1 sec or less. – wipet May 14 '21 at 19:06
  • @wipet I've just posted a question specifically on \CreateTheorem: https://tex.stackexchange.com/q/597713. Could you please kindly take a look at it? – Jinwen May 19 '21 at 14:03

1 Answers1

1

without having tested but your \UseLanguageCORE can be shortened like this

%make the line spacing language dependant (or move into language config)
\let \PL@config@chineselinespacing \PL@config@CJKlinespacing
 % more linespacing command
\let\PL@config@englishlinespacing \PL@config@linespacing

\newcommand\UseLanguageCORE[1] {% \PLlang@langconfig@common% \csname PL@config@#1linespacing\endcsname \csname PLlang@langconfig@#1\endcsname }

Ulrike Fischer
  • 327,261