diff options
author | Norbert Preining <norbert@preining.info> | 2021-03-30 03:00:56 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-03-30 03:00:56 +0000 |
commit | 93809c868bf15852ddc7b50542713131a5d8c05f (patch) | |
tree | 3c741be9d43fdee2f3ecdb17d463deb188d881a8 /macros/generic/polexpr/polexprexpr.tex | |
parent | 3c5dd0d2f091e5e866af1de0327171b253ec9178 (diff) |
CTAN sync 202103300300
Diffstat (limited to 'macros/generic/polexpr/polexprexpr.tex')
-rw-r--r-- | macros/generic/polexpr/polexprexpr.tex | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/macros/generic/polexpr/polexprexpr.tex b/macros/generic/polexpr/polexprexpr.tex new file mode 100644 index 0000000000..9b60e7bab0 --- /dev/null +++ b/macros/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 |