15

Is there a (hopefully simple) way to convert a mathematical TeX expression, such as \frac{\cos(x^2) - x}{x^2 + 1}, to expressions which you would use in a programming language? The outcome of the example should be (cos(x^2) - x)/(x^2 + 1).

3
  • 1
    Welcome to TeX.SE. It looks like you're aiming to perform the inverse of the operation described in Converting C-like math expressions to LaTeX. Is that right?
    – Mico
    Apr 18, 2021 at 18:14
  • 2
    Ahhh, but the inverse problem...converting expressions you would use in a programming language into LaTeX code...now that is a challenge: tex.stackexchange.com/questions/332012/… Apr 18, 2021 at 18:38
  • 1
    Also, standard math notation is notoriously bad for computation. For example (a*x+b)*x+c is both more accurate and faster than a*x^2+b*x+c.. Apr 19, 2021 at 3:10

4 Answers 4

18

It is of course possible it depends what tools you want to use and what subset of latex you want to support (you show an easy case, if the latex has fonts and colours or explicit spacing it gets harder). Wolfram alpha for example can compute with the expression exactly as given, in latex syntax.

https://www.wolframalpha.com/input/?i=%5Cfrac%7Bcos%28x%5E2%29+-+x%7D%7Bx%5E2+%2B+1%7D

enter image description here

It also works with cos corrected to \cos

https://www.wolframalpha.com/input/?i=%5Cfrac%7B%5Ccos%28x%5E2%29+-+x%7D%7Bx%5E2+%2B+1%7D

1
  • Take also a look at the Python package associated to WolframAlpha. Here is an article about it: geeksforgeeks.org/… .
    – projetmbc
    Apr 18, 2021 at 19:52
12

(augmented the Lua code so that instances of \sqrt{...} are processed as well)

Here's a LuaLaTeX-based solution. It consists of a LaTeX utility macro called \latextocmath and two Lua functions -- latex2cmath and do_frac -- which perfom most of the work with the help of Lua's built-in string functions and pattern matching capabilities.

The argument of \latextocmath may contain line breaks. However, the argument of \latextocmath is not expanded before it is passed to the Lua function latex2cmath. Hence, if you define a LaTeX macro called, say, \mymacro, via \newcommand\mymacro{1+1}, then the output of \latextocmath{\mymacro} is the string mymacro, not 1+1. I trust this restriction won't be burdensome.

enter image description here

If the numerator and denominator terms of a \frac expression consist of a single letter or a number, the terms are not encased in parentheses. This should help reduce the amount of visual clutter in continued fractions as well as in simple expressions such as \frac{u}{v}.

This approach can obviously be extended in many ways, depending on the programming code conventions you wish to adhere to and the types of math expressions that need to be fixed. Of course, converting commutative diagrams into inline C-type code will be very, very tedious, to say the least.

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath} % for \cfrac, \dfrac, and \tfrac
\usepackage{luacode} % for 'luacode*' env. and '\luastringN' macro
\begin{luacode*}
function do_frac ( s ) -- convert \\frac notation to inline-math notation
  return ( s:gsub ( "\\[cdt]?frac%s-(%b{})%s-(%b{})" , function ( x , y )
                    x = x:sub ( 2 , -2 ) -- strip off the curly braces
                    y = y:sub ( 2 , -2 )
                    if not (string.len(x)==1 or tonumber(x)) then x = "("..x..")" end
                    if not (string.len(y)==1 or tonumber(y)) then y = "("..y..")" end
                    return x.."/"..y
                 end ) )
end

function latex2cmath ( s )
   s = s:gsub ( "\\[,:;!]" , "" ) -- delete '\,' '\:' '\;' and '\!' substrings
   s = s:gsub ( "\\mkern..-mu" , "" ) -- delete math kerns
   s = s:gsub ( "\\[cl]?dots" , "..." ) --  (typographic) ellipses
   s = s:gsub ( "\\sqrt%s-(%b{})" , "sqrt(%1)" ) 
   while s:find ( "\\[cdt]?frac" ) do s = do_frac ( s ) end -- nested \frac-like terms
   s = s:gsub ( "\\(%a+)" , "%1" ) -- drop leading backslashes from \cos, \Delta, etc
   s = s:gsub ( "%^" , "\\textasciicircum " ) -- make carets visible
   tex.sprint ( ( s:gsub ( "%s" , "" ) ) ) -- omit all whitespace
end
\end{luacode*}
%% The LaTeX utility macro:
\newcommand\latextocmath[1]{\texttt{\directlua{ latex2cmath ( \luastringN{#1} ) }}}

\begin{document}
\[
\frac {u}{v} \quad
\frac{ \sqrt { 2 } } {2} \quad
\frac {\cos (x^2) - x} {x^2 + 1} \quad 
\dfrac{\dfrac{\alpha+\beta}{\Gamma+\Delta}}{\tfrac{3+4}{5+6}} \quad
1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{ 1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cdots}}}}}}}}
\]
\obeylines
\latextocmath{ \frac {u}{v} }
\latextocmath{ \frac{ \sqrt { 2 } } {2} }
\latextocmath{\frac {\cos (x^2) - x} {x^2 + 1}}
\latextocmath{ \dfrac{\dfrac{\alpha+\beta}{\Gamma+\Delta}}{\tfrac{3+4}{5+6}} }
\latextocmath{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{ 1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cdots}}}}}}}}}
\end{document}
6
  • The for loop could be replaced by a while one that calls dofrac while a new string is obtained.
    – projetmbc
    Apr 18, 2021 at 22:21
  • @projetmbc - Many thanks for the suggestion to replace the for loop (with a predetermined number of repetitions) with a while loop that operates as long as \\[cdt]?frac is found in the input string s. Will implement the idea right away.
    – Mico
    Apr 19, 2021 at 0:34
  • {a \over b} does not work. What gsub command we have to add?
    – wipet
    Apr 19, 2021 at 17:09
  • @wipet -- Just insert the following line right before the while ... line: s = s:gsub ( "{(.-)\\over%s*(.-)}" , "\\frac{%1}{%2}" ). That, or feel free to replicate the do_frac function with do_over...
    – Mico
    Apr 19, 2021 at 17:35
  • Thanks for quick reply. But \textocmath{ {{ 2 \over 2+1 }\over 3 } } hangs.
    – wipet
    Apr 19, 2021 at 17:44
10

The Emacs calc-embedded mode can do the trick. assuming you are editing a LaTeX file containing

 $ \frac {\cos (x ^ 2) - x} {x ^ 2 + 1} $ 

and the point (the cursor) on it, just type C-x * e to enter calc-embedded mode. Then type d N (display normal ) to display

$ (cos (x ^ 2) - x) / (x ^ 2 + 1) $

d L (displays LaTeX) to return to LaTeX syntax.

C-x * e to exit the calc-embedded mode and continue the LaTeX file editing.

Bonus

Note that calc-embedded is a nice feature for language syntaxes. Possible syntaxes include C, Fortran, Pascal, TeX, LaTeX, Yacas, Maxima, Giac, Maple, Mathematica, etc ...

calc-embedded also allows rapid entry of matrices in TeX or LaTeX syntax: you enter the matrix online in normal mode $[[a b c] [d e f]]$ and calc-embedded instantly converts to TeX or LaTeX mode active for the document (commas optional). For example $ \ begin {pmatrix} a & b & c \\ d & e & f \ end {pmatrix} $ in LaTeX mode.

1
  • Interesting! I tried to find the source code of where this parsing from TeX syntax is done, and some of it seems to be in this file. Apr 19, 2021 at 1:14
8

I use Sympy for phrasing (and generating) Latex.

from sympy.parsing.latex import parse_latex
expr = parse_latex(r"\frac{\cos(x^2) - x}{x^2 + 1}")
print(expr) # Prints "(-x + cos(x**2))/(x**2 + 1)"

# Bonus
from sympy import latex
print(latex(expr)) # Prints "\frac{- x + \cos{\left(x^{2} \right)}}{x^{2} + 1}"

Sympy has code generators that you can use to generate code in, C, Fortran, Javascript, Julia, Mathematica, Octave/Matlab, and Python (which it, unsurprisingly, has rich support for).

 from sympy import ccode, fcode, jscode, julia_code, mathematica_code, octave_code
# C code
print(ccode(expr)) # (-x + cos(pow(x, 2)))/(pow(x, 2) + 1)
# Fortran
print(fcode(expr)) # (-x + cos(x**2))/(x**2 + 1)
# Javascript
print(jscode(expr)) # (-x + Math.cos(Math.pow(x, 2)))/(Math.pow(x, 2) + 1)
# Julia
print(julia_code(expr)) # (-x + cos(x.^2))./(x.^2 + 1)
# Mathematica
print(mathematica_code(expr)) # (-x + Cos[x^2])/(x^2 + 1)
# Octave/Matlab
print(octave_code(expr)) # (-x + cos(x.^2))./(x.^2 + 1)
# Python
print(expr) # (-x + cos(x**2))/(x**2 + 1)
# Or use lambdify to directly make a Numpy accelerated callable python function

Some notes on getting this setup, you need the antlr4-python3-runtime to use this feature. If you get an error like; ANTLR runtime and generated code versions disagree: 4.9.2!=4.7.2, you need to install the version of the ANTLR runtime that matches the version that Sympy expects, i.e. pip install antlr4-python3-runtime==4.7.2.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .