summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-04-10 21:13:16 +0000
committerKarl Berry <karl@freefriends.org>2021-04-10 21:13:16 +0000
commitf83ae24524b685073a4bd225d9a814e1b5850daf (patch)
treeb75236a60f69657356a312a2cb911cce756819ee /Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
parent89f4f0573f09dfd63100d90c8d80d1da160e3550 (diff)
polexpr (now generic)
git-svn-id: svn://tug.org/texlive/trunk@58821 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex')
-rw-r--r--Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex179
1 files changed, 179 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex b/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
new file mode 100644
index 00000000000..9b60e7bab00
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
@@ -0,0 +1,179 @@
+%% This file polexprexpr.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Extending \xintexpr syntax:
+%%
+%% 1. Authorize ' in variable and function names
+%% This currently breaks infix operators 'and', 'or', 'xor', 'mod'
+%% hence forces usage everywhere of &&, ||, /: and xor() syntax
+%% (if : is active then use /\string : input syntax!)
+%%
+%% 2. Map infix operators to the polexprcore macros
+%%
+%% Overloading of infix operators must be done even outside of \poldef's
+%% scope else functions declared via \xintdeffunc would not be usable in
+%% \poldef as they would be using the xintfrac macros unaware of polynomials
+%%
+%% The overloading of // and /: is experimental.
+%%
+%% 3. Support for the polynomial functions to work in \xintdeffunc
+%%
+%% 4. Support macros for the new functions acting on polynomial variables
+%
+% 1.
+\def\XINT_expr_scanfunc_b #1%
+{%
+ \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi
+ \if (#1\xint_dothis{\iffalse{\fi}(`}\fi
+ \if 1\ifcat a#10\fi
+ \ifnum\xint_c_ix<1\string#1 0\fi
+ \if @#10\fi
+ \if _#10\fi
+ \if '#10\fi
+ 1%
+ \xint_dothis{\iffalse{\fi}(_#1}\fi
+ \xint_orthat {#1\XINT_expr_scanfunc_a}%
+}%
+% 2.
+% the minus sign as prefix
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3% \XINT_expr_exec_<op><level>
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:one{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\POL_tmp{-xii} \xintPolOpp
+\POL_tmp{-xiv} \xintPolOpp
+\POL_tmp{-xvi} \xintPolOpp
+\POL_tmp{-xviii}\xintPolOpp
+% infix operators
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3##4% \XINT_expr_exec_<op>
+ {%
+ \expandafter##2\expandafter##3\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:two{\romannumeral`&&@#2##1##4}}%
+ }%
+}%
+\POL_tmp + \xintPolAdd
+\POL_tmp - \xintPolSub
+\POL_tmp * \xintPolMul
+\POL_tmp / \xintPolQuo
+% there is no infix operator mapped to \xintPolRem
+% for lack of notation: perhaps /; ? advices welcome
+\POL_tmp{//}\xintPolDivModQ
+\POL_tmp{/:}\xintPolDivModR
+\POL_tmp ^ \xintPolPow
+\expandafter\let\csname XINT_expr_op_**\expandafter\endcsname
+ \csname XINT_expr_op_^\endcsname
+% 3.
+% Matches with "mysterious stuff" section of xintexpr source code
+\let\POL:NEhook:polfunc\expandafter
+\toks0\expandafter{\XINT_expr_redefinemacros}%
+\toks2 {\let\POL:NEhook:polfunc\POL:NE:polfunc}%
+\edef\XINT_expr_redefinemacros{\the\toks0 \the\toks2}%
+\catcode`~ 12
+\def\POL@defpolfunc #1#2%
+{%
+ \expandafter\POL@defpolfunc_a
+ \csname XINT_#2_func_#1\expandafter\endcsname
+ \csname XINT_#2_polfunc_#1\endcsname
+}%
+\def\POL@defpolfunc_a #1#2%
+{%
+ \XINT_global
+ \def#1##1##2##3%
+ {%
+ \expandafter##1\expandafter##2\expandafter{%
+ \romannumeral`&&@\POL:NEhook:polfunc{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\def\POL:NE:polfunc #1{%
+\def\POL:NE:polfunc ##1%
+{%
+ \if0\XINT:NE:hastilde ##1~!\relax % this ! of catcode 11
+ \XINT:NE:hashash ##1#1!\relax 0\else
+ \xint_dothis\POL:NE:polfunc_a\fi
+ \xint_orthat\POL:NE:polfunc_b
+ ##1&&A%
+}}\expandafter\POL:NE:polfunc\string#%
+\def\POL:NE:polfunc_a\romannumeral`&&@#1#2&&A%
+{%
+% If we are here #2 was not braced; \string is done with \escapechar126
+ \expandafter{\expanded{~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#1}}#2}%
+}%
+\def\POL:NE:polfunc_b#1{%
+\def\POL:NE:polfunc_b\romannumeral`&&@##1##2&&A%
+{%
+ \expandafter{%
+ \romannumeral`&&@%
+ \if0\XINT:NE:hastilde ##2~!\relax
+ \XINT:NE:hashash ##2#1!\relax 0\else
+ \POL:NE:polfunc_c\fi
+ ##1{##2}}%
+}}\expandafter\POL:NE:polfunc_b\string#%
+% In this case the \expandafter inserted by \POL:NE:usepolfunc
+% expansion will be superfluous
+\def\POL:NE:polfunc_c#1#2% #1=\fi
+{%
+ \expanded{#1~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#2}}%
+}%
+% This \expandafter is in case there is an \expanded after that due
+% to some slicing constructs
+% Call: \romannumeral\POL:NE:usepolfunc
+\def\POL:NE:usepolfunc#1{`&&@\csname#1\expandafter\endcsname}%
+\catcode`~ 3 % its normal catcode in xint bundle
+% 4.
+\def\POL_tmp #1#2#3%
+{%
+ \expandafter\def\csname XINT_expr_func_#1\endcsname##1##2##3%
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {%
+ \romannumeral`&&@#2{\romannumeral`&&@#3##3}%
+ }%
+ }%
+}%
+\POL_tmp {sqr} \XINT:NEhook:f:one:from:one \xintPolSqr
+\POL_tmp {pol} \XINT:NEhook:f:one:from:one \xintPolPol
+\POL_tmp {deg} \XINT:NEhook:f:one:from:one \xintPolDeg
+\POL_tmp {coeffs} \XINT:NEhook:f:one:from:one \xintPolCoeffs
+\POL_tmp {coeff} \XINT:NEhook:f:one:from:two \xintPolCoeff
+\POL_tmp {lcoeff} \XINT:NEhook:f:one:from:one \xintPolLCoeff
+\POL_tmp {monicpart} \XINT:NEhook:f:one:from:one \xintPolMonicPart
+\POL_tmp {icontent} \XINT:NEhook:f:one:from:one \xintPolIContent
+\POL_tmp {primpart} \XINT:NEhook:f:one:from:one \xintPolPrimPart
+\POL_tmp {rdcoeffs} \XINT:NEhook:f:one:from:one \xintPolRedCoeffs
+\POL_tmp {rdzcoeffs} \XINT:NEhook:f:one:from:one \xintPolSRedCoeffs
+\POL_tmp {diff1} \XINT:NEhook:f:one:from:one \xintPolDiffOne
+\POL_tmp {diff2} \XINT:NEhook:f:one:from:one \xintPolDiffTwo
+\POL_tmp {diffn} \XINT:NEhook:f:one:from:two \xintPolDiffN
+\POL_tmp {antider} \XINT:NEhook:f:one:from:one \xintPolAntiOne
+\POL_tmp {integral} \XINT:NEhook:f:one:from:two \xintPolIntegral
+\POL_tmp {quorem} \XINT:NEhook:f:one:from:two \xintPolQuoRem
+\POL_tmp {quo} \XINT:NEhook:f:one:from:two \xintPolQuo
+\POL_tmp {rem} \XINT:NEhook:f:one:from:two \xintPolRem
+\POL_tmp {prem} \XINT:NEhook:f:one:from:two \xintPolPRem
+\POL_tmp {divmod} \XINT:NEhook:f:one:from:two \xintPolDivMod
+\POL_tmp {mod} \XINT:NEhook:f:one:from:two \xintPolDivModR
+\POL_tmp {evalp} \XINT:NEhook:f:one:from:two \xintPolEvalAt
+\def\XINT_expr_func_polgcd #1#2#3%
+{%
+ \expandafter #1\expandafter #2\expandafter{\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:from:delim:u\XINT_PolGCDof#3^}}%
+}%
+% this is provisory
+\xintdeffunc polpowmod_(P, m, Q) :=
+ isone(m)?
+ % m=1: return P modulo Q
+ { mod(P,Q) }
+ % m > 1: test if odd or even and do recursive call
+ { odd(m)? { mod(P*sqr(polpowmod_(P, m//2, Q)), Q) }
+ { mod( sqr(polpowmod_(P, m//2, Q)), Q) }
+ }
+ ;%
+\xintdeffunc polpowmod(P, m, Q) := (m)?{polpowmod_(P, m, Q)}{1};%
+%
+\endinput