Search code examples
texmaximawxmaxima

(wx)Maxima: general roots of numbers, beyond sqrt?


I'm wondering if there are generalizations of the sqrt function in Maxima? In particular, I'd like to be able to control whether x^(a/b) displays as $x^{\frac{a}{b}}$ or $\sqrt[b]{x^{a}}$.

I searched the index of the documentation for root but didn't find anything that I could identify as relevant, and there weren't any links from the sqrtdispflag entry.


Solution

  • This is an interesting question, showing, once again, that Maxima could benefit from a more flexible TeX output system, but I digress. Here's a possible solution.

    This uses pattern matching (in defmatch) to identify something-to-a-quotient expressions for further processing, pulling out the numerator and denominator of the quotient if the match is successful. The pattern matcher fails to identify stuff like b/c^2 -- this should probably be considered a bug in the pattern matcher.

    The default TeX output function is a Lisp function named TEX-MEXPT. I wrote a line of Lisp code (admittedly obscure) to call it.

    /* tex_mexpt.mac -- look for quotient in exponent
     * copyright 2021 by Robert Dodier
     * I release this work under terms of the GNU General Public License
     */
    
    matchdeclare (aa, all);
    matchdeclare (bb, "#"(1));
    defmatch (matches_quotient, aa/bb);
    defmatch (matches_minus_quotient, -aa/bb);
    
    :lisp (defun $tex_mexpt_default (e) (let (lop rop) (apply 'concatenate 'string (tex-mexpt e nil nil))))
    
    my_tex_mexpt_quotient (base, expt_num, expt_denom) :=
      if expt_num = 1
        then printf(false, "\\sqrt[~a]{~a}", tex1 (expt_denom), tex1 (base))
        else printf(false, "\\sqrt[~a]{~a}", tex1 (expt_denom), tex_mexpt_default (base^expt_num));
    
    my_tex_mexpt_minus_quotient (base, expt_num, expt_denom) :=
      if expt_num = 1
        then printf(false, "\\sqrt[~a]{{1}\\over{~a}}", tex1 (expt_denom), tex1 (base))
        else printf(false, "\\sqrt[~a]{~a}", tex1 (expt_denom), tex_mexpt_default (base^-expt_num));
    
    my_tex_mexpt (e) :=
      if tex_mexpt_look_for_quotient
        then block ([base, expt],
                    [base, expt]: args(e),
                    if matches_quotient(expt) # false
                      then my_tex_mexpt_quotient (base, aa, bb)
                    elseif matches_minus_quotient(expt) # false
                      then my_tex_mexpt_minus_quotient (base, aa, bb)
                      else tex_mexpt_default (e))
        else tex_mexpt_default (e);
    
    /* examples */
    
    stringdisp: true $
    
    verbatim_and_equation (e) ::= printf (S, "\\begin{verbatim}~%~a~%\\end{verbatim}~%$$~a$$~%", string(e), tex1(e));
    
    S: openw ("/tmp/foo.tex");
    printf (S, "\\documentclass{article}~%\\begin{document}~%");
    
    /* first without my_tex_mexpt at all */
    
    verbatim_and_equation (a^(b/c));
    verbatim_and_equation (a^-(b/c));
    verbatim_and_equation (a^(-b/c));
    verbatim_and_equation (a^(1/c));
    verbatim_and_equation (a^-(1/c));
    verbatim_and_equation (a^(-1/c));
    verbatim_and_equation ((1 + (1 - x)^((y - z)/(y - w)))/((2*u - v)^(1/(n + 1))));
    
    /* now enable my_tex_mexpt */
    
    texput ("^", my_tex_mexpt);
    tex_mexpt_look_for_quotient:true;
    
    verbatim_and_equation (a^(b/c));
    verbatim_and_equation (a^-(b/c));
    verbatim_and_equation (a^(-b/c));
    verbatim_and_equation (a^(1/c));
    verbatim_and_equation (a^-(1/c));
    verbatim_and_equation (a^(-1/c));
    verbatim_and_equation ((1 + (1 - x)^((y - z)/(y - w)))/((2*u - v)^(1/(n + 1))));
    
    /* verify disabled produces same output as originally */
    
    tex_mexpt_look_for_quotient:false;
    
    verbatim_and_equation (a^(b/c));
    verbatim_and_equation (a^-(b/c));
    verbatim_and_equation (a^(-b/c));
    verbatim_and_equation (a^(1/c));
    verbatim_and_equation (a^-(1/c));
    verbatim_and_equation (a^(-1/c));
    verbatim_and_equation ((1 + (1 - x)^((y - z)/(y - w)))/((2*u - v)^(1/(n + 1))));
    
    printf (S, "\\end{document}~%");
    close(S);
    

    As you can see I put a number of examples in there to verify the output a little bit. You can execute it via maxima --batch=foo.mac or whatever the name of the saved file is. It generates output in /tmp/foo.tex. I processed that with latex and then viewed it with xdvi.

    For the record, here is the foo.tex output I get.

    \documentclass{article}
    \begin{document}
    \begin{verbatim}
    a^(b/c)
    \end{verbatim}
    $$a^{{{b}\over{c}}}$$
    \begin{verbatim}
    a^-(b/c)
    \end{verbatim}
    $${{1}\over{a^{{{b}\over{c}}}}}$$
    \begin{verbatim}
    a^((-b)/c)
    \end{verbatim}
    $${{1}\over{a^{{{b}\over{c}}}}}$$
    \begin{verbatim}
    a^(1/c)
    \end{verbatim}
    $$a^{{{1}\over{c}}}$$
    \begin{verbatim}
    a^-(1/c)
    \end{verbatim}
    $${{1}\over{a^{{{1}\over{c}}}}}$$
    \begin{verbatim}
    a^((-1)/c)
    \end{verbatim}
    $${{1}\over{a^{{{1}\over{c}}}}}$$
    \begin{verbatim}
    (1+(1-x)^((y-z)/(y-w)))/(2*u-v)^(1/(n+1))
    \end{verbatim}
    $${{\left(1-x\right)^{{{y-z}\over{y-w}}}+1}\over{\left(2\,u-v\right)^{{{1}\over{n+1}}}}}$$
    \begin{verbatim}
    a^(b/c)
    \end{verbatim}
    $$\sqrt[c]{a^{b}}$$
    \begin{verbatim}
    a^-(b/c)
    \end{verbatim}
    $${{1}\over{\sqrt[c]{a^{b}}}}$$
    \begin{verbatim}
    a^((-b)/c)
    \end{verbatim}
    $${{1}\over{\sqrt[c]{a^{b}}}}$$
    \begin{verbatim}
    a^(1/c)
    \end{verbatim}
    $$\sqrt[c]{a}$$
    \begin{verbatim}
    a^-(1/c)
    \end{verbatim}
    $${{1}\over{\sqrt[c]{a}}}$$
    \begin{verbatim}
    a^((-1)/c)
    \end{verbatim}
    $${{1}\over{\sqrt[c]{a}}}$$
    \begin{verbatim}
    (1+(1-x)^((y-z)/(y-w)))/(2*u-v)^(1/(n+1))
    \end{verbatim}
    $${{\sqrt[y-w]{\left(1-x\right)^{y-z}}+1}\over{\sqrt[n+1]{2\,u-v}}}$$
    \begin{verbatim}
    a^(b/c)
    \end{verbatim}
    $$a^{{{b}\over{c}}}$$
    \begin{verbatim}
    a^-(b/c)
    \end{verbatim}
    $${{1}\over{a^{{{b}\over{c}}}}}$$
    \begin{verbatim}
    a^((-b)/c)
    \end{verbatim}
    $${{1}\over{a^{{{b}\over{c}}}}}$$
    \begin{verbatim}
    a^(1/c)
    \end{verbatim}
    $$a^{{{1}\over{c}}}$$
    \begin{verbatim}
    a^-(1/c)
    \end{verbatim}
    $${{1}\over{a^{{{1}\over{c}}}}}$$
    \begin{verbatim}
    a^((-1)/c)
    \end{verbatim}
    $${{1}\over{a^{{{1}\over{c}}}}}$$
    \begin{verbatim}
    (1+(1-x)^((y-z)/(y-w)))/(2*u-v)^(1/(n+1))
    \end{verbatim}
    $${{\left(1-x\right)^{{{y-z}\over{y-w}}}+1}\over{\left(2\,u-v\right)^{{{1}\over{n+1}}}}}$$
    \end{document}