% ____________________________________ % calcfrac % v0.2 % 28/10/2023 % TeX & LaTeX package % ____________________________________ % Author : TeXpérimental % Email : texperimental@mailo.fr % Licence : Released under the LaTeX Project Public License v1.3c or % later, see http://www.latex-project.org/lppl.txt % Status : maintained \csname calcfraconce\endcsname \let\calcfraconce\endinput \def\calcfracname{calcfrac} \def\calcfracver{v0.2} \def\calcfracdate{2023/10/28} \catcode`\@11 \def\cf@test@ifx#1{% \ifx#1\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi } \def\cf@test@ifnum#1{% \ifnum#1\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi } \def\cf@execfirst#1#2{#1} \def\cf@execsecond#1#2{#2} \def\cf@execarg#1{#1} \def\cf@matharg#1{$#1$} %########################################### %############# boucle \cf@for ############## %########################################### \def\cf@for#1=#2to#3#{% \cf@for@a{#1}{#2}{#3}% } \def\cf@for@a#1#2#3#4{% \edef#1{\number\numexpr#2}% \edef\cf@maxint{\number\numexpr#3}% \def\cf@for@b{% \unless\ifnum#1>\cf@maxint\relax #4% \edef#1{\number\numexpr#1+1}% \expandafter\cf@for@b \fi }% \cf@for@b } %########################################### %########################################### %########################################### \newcount\cf@tmp@count \newcount\cf@frac@cnt \newif\if@inparen \def\calcfrac@err{% \cf@test@ifnum{\currentgrouplevel>\cf@nestparen\relax} {% \endgroup \calcfrac@err } {% \calcfrac@err@a }% } \def\calcfrac@err@a#1#2\relax{% \errmessage{Illegal char "#1", "#2" ignored}% } \def\calcfrac{% \xdef\cf@nestparen{\the\currentgrouplevel}% \begingroup \catcode32=9 % espaces ignorés \calcfrac@a } \def\calcfrac@a#1{% \ifcat\relax\detokenize{#1}\relax\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi {} {% \cf@frac@cnt=0 \@inparenfalse \expandafter\cf@read@frac\detokenize{#1}\relax }% } \def\cf@read@frac{% [1 signe optionnel + ou-][1 signe / ou * suivi d'un entier non signé]*n \advance\cf@frac@cnt1 \let\cf@current@sign\empty \def\cf@current@numer{1}% \def\cf@current@denom{1}% \def\cf@current@op{*}% \cf@read@sign } \def\cf@read@sign#1{% \cf@test@ifnum{0\ifx+#11\fi\ifx-#11\fi=1 } {% \def\cf@current@sign{#1}% \cf@read@int } {% \cf@read@int#1% }% } \def\cf@read@int#1{% \cf@test@ifnum{0\ifnum`#1<`0 1\fi\ifnum`#1>`9 1\fi=0 } {% \afterassignment\cf@update@afterint \cf@tmp@count#1% } {% si #1=parenthèse \if(#1\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi {% \begingroup \@inparentrue \cf@frac@cnt=0 \cf@read@frac } {% \calcfrac@err#1% }% }% } \def\cf@update@afterint{% \if*\cf@current@op\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi {% \edef\cf@current@numer{\cf@current@numer*\the\cf@tmp@count}% \cf@read@op } {% \if/\cf@current@op\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi {% \edef\cf@current@denom{\cf@current@denom*\the\cf@tmp@count}% \cf@read@op } {% \errmessage{This error should not occur, \string\cf@current@op=\cf@current@op}% }% }% } \def\cf@read@op#1{% \cf@test@ifnum{0\ifx*#11\fi\ifx/#11\fi=1 } {% \def\cf@current@op{#1}% \cf@read@int } {% \cf@compute@frac#1% }% } \def\cf@compute@frac#1{% \edef\cf@current@numer{\the\numexpr\cf@current@numer}% \edef\cf@current@denom{\the\numexpr\cf@current@denom}% \expandafter\cf@calc@gcd\expanded{{\cf@current@numer}{\cf@current@denom}}\cf@tem@gcd \expandafter\edef\csname sign@\the\cf@frac@cnt\endcsname{\ifnum\cf@current@sign1=1+\else-\fi}% \expandafter\edef\csname numer@\the\cf@frac@cnt\endcsname{\the\numexpr\cf@current@numer/\cf@tem@gcd}% \expandafter\edef\csname denom@\the\cf@frac@cnt\endcsname{\the\numexpr\cf@current@denom/\cf@tem@gcd}% \cf@test@ifnum{0\ifx\relax#111\fi\if@inparen1\fi\if)#11\fi=11 }% si <#1=\relax> OU {% \cf@add@allfrac } {% \cf@read@frac#1% }% } \def\cf@calc@gcd#1#2{% #1, #2=entiers \cf@test@ifnum{#1>#2\relax} {% \cf@calc@gcd@a{#2}{#1}% } {% \cf@calc@gcd@a{#1}{#2}% }% } \def\cf@calc@gcd@a#1#2{% #1=diviseur #2=dividende \cf@test@ifnum{#1>0 } {% \cf@tmp@count=#2\relax \divide\cf@tmp@count#1\relax \expandafter\cf@calc@gcd@a\expandafter{\the\numexpr#2-\cf@tmp@count*#1}{#1}% } {% \cf@calc@gcd@b{#2}% }% } \def\cf@calc@gcd@b#1#2{% #1=PGCD #2=macro qui stocke le PGCD \def#2{#1}% } \def\calc@lcm#1#2#3{% #1, #2=entiers #3=macro recevant le PPCM \cf@calc@gcd{#1}{#2}\cf@tem@gcd% \edef#3{\the\numexpr#1*#2/\cf@tem@gcd}% } \def\cf@add@allfrac{% \cf@test@ifnum{\cf@frac@cnt>1 } {% \expandafter\let\expandafter\cf@result@denom\csname denom@1\endcsname \cf@for\cf@temp@index=2 to \cf@frac@cnt{% \expandafter\calc@lcm\expanded{{\cf@result@denom}{\csname denom@\cf@temp@index\endcsname}}\cf@result@denom }% \def\cf@result@numer{0}% \cf@for\cf@temp@index=1 to \cf@frac@cnt{% \edef\cf@result@numer{% \the\numexpr \cf@result@numer \csname sign@\cf@temp@index\endcsname% <- + ou - \csname numer@\cf@temp@index\endcsname*\cf@result@denom/\csname denom@\cf@temp@index\endcsname }% }% \ifnum\cf@result@numer<0 \edef\cf@result@numer{\the\numexpr-\cf@result@numer}% \def\cf@result@sign{-}% \else \def\cf@result@sign{+}% \fi \expandafter\cf@calc@gcd\expanded{{\cf@result@numer}{\cf@result@denom}}\cf@tem@gcd \ifnum\cf@tem@gcd>1 \edef\cf@result@numer{\the\numexpr\cf@result@numer/\cf@tem@gcd}% \edef\cf@result@denom{\the\numexpr\cf@result@denom/\cf@tem@gcd}% \fi } {% \expandafter\let\expandafter\cf@result@sign\csname sign@1\endcsname \expandafter\let\expandafter\cf@result@numer\csname numer@1\endcsname \expandafter\let\expandafter\cf@result@denom\csname denom@1\endcsname }% \if@inparen\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi {% \expandafter \endgroup \expanded{% \def\noexpand\cf@paren@sign{\cf@result@sign}% \def\noexpand\cf@paren@numer{\cf@result@numer}% \def\noexpand\cf@paren@denom{\cf@result@denom}% }% \edef\cf@current@sign{\cf@current@sign\cf@paren@sign}% \expandafter\cf@read@int\expanded{\cf@paren@numer\if*\cf@current@op/\else*\fi\cf@paren@denom}% } {% \expandafter \endgroup \expandafter\cfdisp\expanded{{\cf@result@sign}{\cf@result@numer}{\cf@result@denom}}% }% } \def\cfdisp#1#2#3{% \ifmmode\expandafter\cf@execarg\else\expandafter\cf@matharg\fi {\ifnum#11=-1 -\fi {\ifnum#3=1 #2% \else #2\over#3% \fi }% }% } \catcode`\@12 \endinput VERSIONS : v0.1 26/10/2023 version initiale v0.2 28/10/2023 corrections de bugs améliorations du code ajout d'un fichier pdf (manuel succint + exemples)