summaryrefslogtreecommitdiff
path: root/macros/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-10-28 03:01:16 +0000
committerNorbert Preining <norbert@preining.info>2023-10-28 03:01:16 +0000
commit27f547140ee908fb4ce9e4b8297af7d5bf8d7ff9 (patch)
treee369cbac6d7ab890e1139cd73f5034e45af74b8b /macros/generic
parente7c703c953f148411c70d5ca86dc1c1023d73806 (diff)
CTAN sync 202310280301
Diffstat (limited to 'macros/generic')
-rw-r--r--macros/generic/calcfrac/README61
-rw-r--r--macros/generic/calcfrac/calcfrac.sty13
-rw-r--r--macros/generic/calcfrac/calcfrac.tex246
3 files changed, 320 insertions, 0 deletions
diff --git a/macros/generic/calcfrac/README b/macros/generic/calcfrac/README
new file mode 100644
index 0000000000..9beec979d5
--- /dev/null
+++ b/macros/generic/calcfrac/README
@@ -0,0 +1,61 @@
+____________________________________
+
+ calcfrac
+ v0.1
+ 26/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
+
+************************ LISEZ-MOI FRANÇAIS ************************
+Ce package a des intentions pédagogiques. Les vidéos montrant la
+totalité de son écriture à partir de rien sont disponibles sur
+youtube à partir de l'épisode 24 :
+
+ https://youtu.be/6lF4P6B3msw
+
+C'est pourquoi il est livré sans aucune documentation autre que
+la brève description ci-dessous.
+
+ Ce package met à disposition la macro \calcfrac qui admet comme
+ argument obligatoire une expression numérique contenant des
+ fractions. Par exemple
+ \calcfrac{1/2-2/3+3/4-2}
+ \calcfrac{2/(1/2-1/3)-2/3}
+ \calcfrac{1-(2-(3-(4-2/3)))/5}
+
+ Elle renvoie 3 arguments qui sont le signe, le numérateur et
+ le dénominateur du résultat.
+ Ces 3 arguments sont passés à une macro publique \cfdisp que
+ l'utilisateur peut programmer à sa guise (une version générique
+ qui devrait convenir au plus grand nombre est fournie)
+
+
+************************** README ENGLISH **************************
+This package is intended for educational purposes. The videos
+showing its writing from scratch are available on youtube from
+episode 24:
+
+ https://youtu.be/6lF4P6B3msw
+
+This is why it is delivered without any documentation other than
+the brief description below.
+
+ This package provides the \calcfrac macro, which accepts one
+ mandatory argument being a numerical expression containing
+ fractions. For example
+ \calcfrac{1/2-2/3+3/4-2}
+ \calcfrac{2/(1/2-1/3)-2/3}
+ \calcfrac{1-(2-(3-(4-2/3)))/5}
+
+ It returns 3 arguments which are the sign, the numerator
+ and the denominator of the result.
+ These 3 arguments are passed to a public macro \cfdisp
+ which the users can program as they wish (a generic version
+ which should be suitable for most users is provided)
diff --git a/macros/generic/calcfrac/calcfrac.sty b/macros/generic/calcfrac/calcfrac.sty
new file mode 100644
index 0000000000..0951215197
--- /dev/null
+++ b/macros/generic/calcfrac/calcfrac.sty
@@ -0,0 +1,13 @@
+\input calcfrac.tex
+\ProvidesPackage{\calcfracname}[\calcfracver\space Calcul d'expressions avec fractions]
+\def\cfdisp#1#2#3{%
+ \ensuremath
+ {\ifnum#11=-1 -\fi
+ {\ifnum#3=1
+ #2%
+ \else
+ \frac{#2}{#3}%
+ \fi
+ }%
+ }%
+} \ No newline at end of file
diff --git a/macros/generic/calcfrac/calcfrac.tex b/macros/generic/calcfrac/calcfrac.tex
new file mode 100644
index 0000000000..7d46762f95
--- /dev/null
+++ b/macros/generic/calcfrac/calcfrac.tex
@@ -0,0 +1,246 @@
+% ____________________________________
+
+% calcfrac
+% v0.1
+% 26/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{0.1}
+\def\calcfracdate{2023/10/26}
+
+\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#1#2\relax{%
+ \errmessage{Illegal char "#1", "#2" ignored}%
+}
+\def\calcfrac{%
+ \begingroup
+ \catcode32=9 % espaces ignorés
+ \calcfrac@a
+}
+\def\calcfrac@a#1{%
+ \endgroup
+ \ifcat\relax\detokenize{#1}\relax
+ \else
+ \cf@frac@cnt=0
+ \@inparenfalse
+ \expandafter\cf@read@frac\detokenize{#1}\relax
+ \fi
+}
+\def\cf@read@frac{% [1 signe optionnel + ou-]<entier non signé>[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%
+ }
+ {% TODO : 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 <inparen=vrai ET #1=")">
+ {%
+ \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\cfdisp\expanded{{\cf@result@sign}{\cf@result@numer}{\cf@result@denom}}%
+ }%
+}
+\def\cfdisp#1#2#3{%
+ \ifmmode\expandafter\cf@execfirst\else\expandafter\cf@execsecond\fi
+ {\cf@execarg}
+ {\cf@matharg}
+ {\ifnum#11=-1 -\fi
+ {\ifnum#3=1
+ #2%
+ \else
+ #2\over#3%
+ \fi
+ }%
+ }%
+}
+\catcode`\@12
+\endinput
+
+VERSIONS :
+v0.1 : version initiale \ No newline at end of file