2

How do I create macros that take + (plus) or - (minus) separated arguments as inputs and store them to variables (e.g., coefficients of polynomials)?

I want to define macros that can access and select parts of the arguments that are separated by either plus signs + or minus signs - and store them to variables.

For example, I want to create something like the following macro:

\documentclass[oneside,DIV=12]{scrbook}
\usepackage{mathtools, amssymb}
\usepackage{xparse}

\newcommand{\coeffZero}{} % variable corresponding to the coefficient of x^0, i.e., the constant term a_0 \newcommand{\coeffOne}{} % a_1 of a_1 x \newcommand{\coeffTwo}{} % a_2 of a_2 x^2 \newcommand{\coeffThree}{} % a_3 of a_3 x^3 \newcommand{\coeffFour}{} % a_4 of a_4 x^4 \newcommand{\coeffFive}{} % a_5 of a_5 x^5

\newcommand{\polycoeff}[1]{<...>} % or \NewDocumentCommand{\polycoeff}{ m }{<...>} using xparse % This macro should take a + or - separated arguments of polynomials as input (ignoring spaces) % and will store the coefficients to the corresponding variables defined above

\begin{document} \polycoeff{6x^3 + 5x^2 − 7} [a_0 = \coeffZero,, a_1 = \coeffOne,, a_2 = \coeffTwo,, a_3 = \coeffThree] \end{document}

which should typeset a_0 = -7, a_1 = 0, a_2 = 5, a_3 = 6.

How can I define such a macro?

Thank you.

  • Your exemplary input shows also the x^n terms, though your description would indicate an input such as the following: \polycoeff{-7+0+5+6} – Skillmon Jun 24 '22 at 18:12
  • Somewhat related: https://tex.stackexchange.com/questions/622275/write-a-polynomial-fraction-from-its-either-partial-fraction-or-coefficients-of and https://tex.stackexchange.com/questions/273037/expandable-quick-sort-array-macro/273476?r=SearchResults&s=1%7C26.7651#273476 – John Kormylo Jun 25 '22 at 03:29
  • How shall emptiness/blankness between signs be handled, e.g., \polycoeff{6x^3 + 5x^2 −− 7} or \polycoeff{6x^3 + 5x^2 − − 7} ? How to handle \polycoeff{2x^3 + 2x^3 +2x^3 +2x^2+2x^2+x^2 − 7} – Ulrich Diez Jun 27 '22 at 14:25

2 Answers2

4

You can read numbers to registers \coefnum and \expnum and run next macro using \afterassignment.

\newcount\coefnum  
\newcount\expnum
\def\polycoeff#1{\polyA#1\relax}
\def\polyA{\afterassignment\polyB \coefnum=}
\def\polyB#1{\ifx#1\relax \sxdef{polyco:0}{\the\coefnum}%
   \else \expandafter\polyC \fi
}
\def\polyC#1{\afterassignment\polyD \expnum=\ifx^#1\else 1 #1\fi}
\def\polyD{\sxdef{polyco:\the\expnum}{\the\coefnum}\polyA}
\def\coeff#1{\ifcsname polyco:#1\endcsname \csname polyco:#1\endcsname
   \else 0\fi
}
\def\sxdef#1{\expandafter\xdef\csname#1\endcsname}

\polycoeff{6x^3 + 5x^2 - 7}

$$ a_0 = \coeff0, a_1 = \coeff1, a_2 = \coeff2, a_3 = \coeff3. $$

\bye

wipet
  • 74,238
  • Thank you for your answer! I tried tinkering around with it and it seems to work for coefficients of terms with single digit powers which is enough for my usage but do you think there is a way to generalize this for n > 9? If you don't mind could you also recommend me resources to read more about something like this? Thank you again. – Farrel Ahmed Jun 28 '22 at 00:35
  • @FarrelAhmed \coeff{10}, \coeff{11} etc. should work. I didn't write \coeff{1} (it works too) because I am lazy. – wipet Jun 28 '22 at 19:03
  • I tried writing \polycoeff{4x^{10} - 6x^3 + 5x^2 - 7} \[a_{10} = \coeff{10}, a_3 = \coeff{3}, a_2 = \coeff{2}, a_0 = \coeff{0}.\] but it gave me an error with this output. – Farrel Ahmed Jul 31 '22 at 11:58
  • \polycoeff{x^3} \[a_3 = \coeff{3}.\] also doesn't seem to work. – Farrel Ahmed Jul 31 '22 at 12:03
1

Modifying wipet's solution to solve the first two of the following problems:

  1. \polycoeff cannot store coefficients from +x^n and-x^n as 1 -1 as it needs the input to have an explicit number behind each x^n. In other words, \polycoeff{+1x} and\polycoeff{-1x} both work while \polycoeff{+x} and \polycoeff{-x} both return errors. (Solved)

  2. \polycoeff cannot store the coefficient of the constant term as a_0 = 0 unless explicitly stated in the input. In other words, \polycoeff{2x + 0} works while \polycoeff{2x} returns an error. (Solved)

  3. \polycoeff cannot store the coefficients of terms with degrees n > 9. (Still unsolved)

Here's my final solution using the macro \PolyCoeff (that incorporates wipet's \polycoeff).

enter image description here

\documentclass[oneside,DIV=12]{scrbook}

\usepackage{scrhack} \usepackage{mathtools, amsthm, amssymb} \usepackage[warnings-off={mathtools-colon,mathtools-overbracket}]{unicode-math} \setmathfont{Latin Modern Math} \usepackage{xparse} \usepackage{xpatch} \usepackage{xstring}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% \ExpandArg (https://tex.stackexchange.com/a/515425)

\ExplSyntaxOn \cs_new_protected:Nn __user_expand_arg:n { \tl_set:No \ProcessedArgument { #1 } } \cs_set_eq:NN \ExpandArg __user_expand_arg:n \ExplSyntaxOff

% \ZapSpaces (https://tex.stackexchange.com/a/652826)

\ExplSyntaxOn \cs_new_protected:Npn __user_arg_zap_spaces:n #1 { \tl_set:Nn \ProcessedArgument {#1} \tl_remove_all:Nn \ProcessedArgument { ~ } } \cs_set_eq:NN \ZapSpaces __user_arg_zap_spaces:n \ExplSyntaxOff

% \polycoeff{&lt;polynomial&gt;} and \coeff (n &lt; 10) (https://tex.stackexchange.com/a/649027)

\newcount\coefnum
\newcount\expnum \def\polycoeff#1{\polyA#1\relax} \def\polyA{\afterassignment\polyB \coefnum=} \def\polyB#1{\ifx#1\relax \sxdef{polyco:0}{\the\coefnum}% \else \expandafter\polyC \fi } \def\polyC#1{\afterassignment\polyD \expnum=\ifx^#1\else 1 #1\fi} \def\polyD{\sxdef{polyco:\the\expnum}{\the\coefnum}\polyA} \def\coeff#1{\ifcsname polyco:#1\endcsname \csname polyco:#1\endcsname \else 0\fi } \def\sxdef#1{\expandafter\xdef\csname#1\endcsname}

% \PolyCoeff(&lt;polynomial&gt;), \Coeff (n &lt; 10), and \Coefficients

\newcommand{\Polynomial}{} \NewDocumentCommand{\PolyCoeff}{>{\ZapSpaces} >{\ExpandArg} m}{% \renewcommand{\Polynomial}{+#1.} % x^5 \IfSubStr{\Polynomial}{++x^5}{\xpatchcmd{\Polynomial}{++x^5}{1x^5}{}{}}{} \IfSubStr{\Polynomial}{+x^5}{\xpatchcmd{\Polynomial}{+x^5}{1x^5}{}{}}{} \IfSubStr{\Polynomial}{+-x^5}{\xpatchcmd{\Polynomial}{+-x^5}{-1x^5}{}{}}{} \IfSubStr{\Polynomial}{-x^5}{\xpatchcmd{\Polynomial}{-x^5}{-1x^5}{}{}}{} \IfSubStr{\Polynomial}{x^5.}{\xpatchcmd{\Polynomial}{x^5.}{1x^5+0}{}{}}{} % x^4 \IfSubStr{\Polynomial}{++x^4}{\xpatchcmd{\Polynomial}{++x^4}{1x^4}{}{}}{} \IfSubStr{\Polynomial}{+x^4}{\xpatchcmd{\Polynomial}{+x^4}{+1x^4}{}{}}{} \IfSubStr{\Polynomial}{+-x^4}{\xpatchcmd{\Polynomial}{+-x^4}{-1x^4}{}{}}{} \IfSubStr{\Polynomial}{-x^4}{\xpatchcmd{\Polynomial}{-x^4}{-1x^4}{}{}}{} \IfSubStr{\Polynomial}{x^4.}{\xpatchcmd{\Polynomial}{x^4.}{1x^4+0}{}{}}{} % x^3 \IfSubStr{\Polynomial}{++x^3}{\xpatchcmd{\Polynomial}{++x^3}{1x^3}{}{}}{} \IfSubStr{\Polynomial}{+x^3}{\xpatchcmd{\Polynomial}{+x^3}{+1x^3}{}{}}{} \IfSubStr{\Polynomial}{+-x^3}{\xpatchcmd{\Polynomial}{+-x^3}{-1x^3}{}{}}{} \IfSubStr{\Polynomial}{-x^3}{\xpatchcmd{\Polynomial}{-x^3}{-1x^3}{}{}}{} \IfSubStr{\Polynomial}{x^3.}{\xpatchcmd{\Polynomial}{x^3.}{1x^3+0}{}{}}{} % x^2 \IfSubStr{\Polynomial}{++x^2}{\xpatchcmd{\Polynomial}{++x^2}{1x^2}{}{}}{} \IfSubStr{\Polynomial}{+x^2}{\xpatchcmd{\Polynomial}{+x^2}{+1x^2}{}{}}{} \IfSubStr{\Polynomial}{+-x^2}{\xpatchcmd{\Polynomial}{+-x^2}{-1x^2}{}{}}{} \IfSubStr{\Polynomial}{-x^2}{\xpatchcmd{\Polynomial}{-x^2}{-1x^2}{}{}}{} \IfSubStr{\Polynomial}{x^2.}{\xpatchcmd{\Polynomial}{x^2.}{1x^2+0}{}{}}{} % x^1 \IfSubStr{\Polynomial}{++x+}{\xpatchcmd{\Polynomial}{++x+}{1x+}{}{}}{} \IfSubStr{\Polynomial}{++x-}{\xpatchcmd{\Polynomial}{++x-}{1x-}{}{}}{} \IfSubStr{\Polynomial}{++x.}{\xpatchcmd{\Polynomial}{++x.}{1x+0}{}{}}{} \IfSubStr{\Polynomial}{+x+}{\xpatchcmd{\Polynomial}{+x+}{+1x+}{}{}}{} \IfSubStr{\Polynomial}{+x-}{\xpatchcmd{\Polynomial}{+x-}{+1x-}{}{}}{} \IfSubStr{\Polynomial}{+x.}{\xpatchcmd{\Polynomial}{+x.}{+1x+0}{}{}}{} \IfSubStr{\Polynomial}{-x+}{\xpatchcmd{\Polynomial}{-x+}{-1x+}{}{}}{} \IfSubStr{\Polynomial}{-x-}{\xpatchcmd{\Polynomial}{-x-}{-1x-}{}{}}{} \IfSubStr{\Polynomial}{-x.}{\xpatchcmd{\Polynomial}{-x.}{-1x+0}{}{}}{} % x^0 \IfSubStr{\Polynomial}{.}{\xpatchcmd{\Polynomial}{.}{}{}{}}{} % store coefficients \polycoeff{\Polynomial} \renewcommand{\CoeffZero}{\coeff{0}} \renewcommand{\CoeffOne}{\coeff{1}} \renewcommand{\CoeffTwo}{\coeff{2}} \renewcommand{\CoeffThree}{\coeff{3}} \renewcommand{\CoeffFour}{\coeff{4}} \renewcommand{\CoeffFive}{\coeff{5}} }

\newcommand{\CoeffZero}{} % variable corresponding to the coefficient of x^0, i.e., the constant term a_0 \newcommand{\CoeffOne}{} % a_1 of a_1 x \newcommand{\CoeffTwo}{} % a_2 of a_2 x^2 \newcommand{\CoeffThree}{} % a_3 of a_3 x^3 \newcommand{\CoeffFour}{} % a_4 of a_4 x^4 \newcommand{\CoeffFive}{} % a_5 of a_5 x^5

\newcommand{\Coefficients}{a_5 = \CoeffFive,, a_4 = \CoeffFour,, a_3 = \CoeffThree,, a_2 = \CoeffTwo,, a_1 = \CoeffOne,, a_0 = \CoeffZero.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}\KOMAoptions{DIV=current}\Large% \newcommand{\quintic}{ 5x^5 - 4x^4 + 3x^3 - 2x^2 + x } [f(x) = \quintic.] \PolyCoeff{\quintic} [\Coefficients] \end{document}