%% filename: polexprexpr.tex %% Part of the polexpr package (0.8.7a, 2022/05/19) %% %% Polynomial extensions to the \xintexpr syntax: %% %% 1. Authorize ' in variable and function names %% This partially breaks infix operators 'and', 'or', 'xor', 'mod' %% which must be replaced by &&, ||, /: and xor() syntax %% if immediately following a variable name %% %% 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_ {% \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_ {% \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 % 0.8.1 renames 0.8.0 icontent() to cont() and lcoeff() to lc() % and adds topol() and lcoeffs() \POL_tmp {pol} \XINT:NEhook:f:one:from:one \xintPolPol \POL_tmp {lpol} \XINT:NEhook:f:one:from:one \xintPolLPol \POL_tmp {deg} \XINT:NEhook:f:one:from:one \xintPolDeg \POL_tmp {coeffs} \XINT:NEhook:f:one:from:one \xintPolCoeffs \POL_tmp {lcoeffs} \XINT:NEhook:f:one:from:one \xintPolLCoeffs \POL_tmp {coeff} \XINT:NEhook:f:one:from:two \xintPolCoeff \POL_tmp {lc} \XINT:NEhook:f:one:from:one \xintPolLC \POL_tmp {monicpart} \XINT:NEhook:f:one:from:one \xintPolMonicPart \POL_tmp {cont} \XINT:NEhook:f:one:from:one \xintPolCont \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 {intfrom} \XINT:NEhook:f:one:from:two \xintPolIntFrom \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