# Ticket #5711: enhanced-symbolic-typesetting-rebased_to_4.0.1.patch

File enhanced-symbolic-typesetting-rebased_to_4.0.1.patch, 19.9 KB (added by gmhossain, 10 years ago)
• ## sage/misc/latex.py

# HG changeset patch
# User Golam Mortuza Hossain <gmhossain@gmail.com>
# Date 1244851786 10800
# Node ID 58abaa4df2e26c9d272e262845af6e025a4d8fa0
# Parent  6c7354ace3b6e0bf4c33ddb730531bd23a9fb92c
Enhances typsetting of Symbolic functions within Sage (rebased to Sage-4.0.1)

diff -r 6c7354ace3b6 -r 58abaa4df2e2 sage/misc/latex.py
 a 'omega', 'Omega'] def latex_symbolic_function(fname, fstr, args): r""" Typeset a given symbolic function in LaTeX. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: latex_sym_fn = latex_module.latex_symbolic_function sage: var('x,a,b,t,s') (x, a, b, t, s) sage: riemann(x) = function('riemann',x) sage: latex_sym_fn("riemann","\\mathcal{R}",(x,)) '\\mathcal{R}\\left(x\\right)' sage: psi(x) = function('psi',x) sage: latex_sym_fn("psi",False,(x,)) '\\psi\\left(x\\right)' sage: latex_sym_fn("conjugate",False,(psi(x))) '\\overline{\\psi\\left(x\\right)}' sage: latex_sym_fn("limit",False,(psi(x),x,a)) '\\lim_{x \\to a}\\, \\psi\\left(x\\right)' sage: f(t) = function('f',t) sage: latex_sym_fn("laplace",False,(f(t),t,s)) '\\mathcal{L}\\left(f\\left(t\\right), t, s\\right)' sage: F(s) = function('F',s) sage: latex_sym_fn("ilt",False,(F(s),s,t)) '\\mathcal{L}^{-1}\\left(F\\left(s\\right), s, t\\right)' sage: f(x) = function('f',x) sage: latex_sym_fn("integrate",False,(f(x),x)) '\\int f\\left(x\\right)\\,{d x}' sage: latex_sym_fn("integrate",False,(f(x),x,a,b)) '\\int_{a}^{b} f\\left(x\\right)\\,{d x}' sage: var('x,y') (x, y) sage: f(x) = function('f',x) sage: latex_sym_fn("diff",False,(f(x),x,1)) '\\frac{d f\\left(x\\right)}{d x}' sage: f(x,y) = function('f',x,y) sage: latex_sym_fn("diff",False,(f(x,y),x,1)) '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' sage: myfunc(x) = function('myfunc',x) sage: latex_sym_fn("myfunc",False,(x,)) '{\\it myfunc}\\left(x\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ # Use the latex_name if defined if fstr is not False: return "%s%s"%(fstr, _args_latex_(fname, args)) # Special handling of fname where specific processing is needed if fname == "conjugate": return _conjugate_latex_(fname, args) elif fname == "limit": return _limit_latex_(fname, args) elif fname == "laplace": return _laplace_latex_(fname, args) elif fname == "ilt": return _inverse_laplace_latex_(fname, args) elif fname == "integrate": return _integrate_latex_(fname, args) elif fname == "diff": f = args[0] fstr = latex(f) nvars = len(f.variables()) return _derivative_latex_(fstr, args, nvars) # Now check whether fname is a Greek letter name = latex_function_name(fname) if name is not False: return "%s%s"%(name, _args_latex_(fname, args)) # Use default typesetting scheme return _symbolic_function_default_latex_(fname, args) def _symbolic_function_default_latex_(fname, args): r""" Return LaTeX expression of a symbolic function using default scheme. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _sym_def_latex_ = latex_module._symbolic_function_default_latex_ sage: var('x') x sage: myfunc(x) = function('myfunc',x) sage: _sym_def_latex_("myfunc",(x,)) '{\\it myfunc}\\left(x\\right)' sage: my_func(x) = function('my_func',x) sage: _sym_def_latex_("my_func",(x,)) '{\\it my\\_func}\\left(x\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ # Prepend underscore by "\\" in fname fname = fname.replace("_", "\\_") # Default typesetting scheme (similar to Maxima scheme) return "{\\it %s}%s"%(fname, _args_latex_(fname, args)) def _args_latex_(fname, args): r""" Return LaTeX expression for the arguments of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _args_latex_ = latex_module._args_latex_ sage: var('x') x sage: f(x) = function('f',x) sage: _args_latex_("f",(x,)) '\\left(x\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-06) """ # If all arguments are SymbolicVariables then the function should be # typeset as f(x) rather than f\left(x\right) use_left_right = True #from sage.calculus.calculus import SymbolicVariable #for x in self._args: #    if not isinstance(x, SymbolicVariable): #        use_left_right = True #        break if use_left_right is True: return "\\left(%s\\right)"%(', '.join([latex(x) for x in args])) else: return "(%s)"%(', '.join([latex(x) for x in args])) def latex_d_derivative(fstr, params, args): r""" Return LaTeX expression for "D" format derivatives of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: latex_d_derivative = latex_module.latex_d_derivative sage: var('x,y') (x, y) sage: f(x) = function('f',x) sage: latex_d_derivative("f\\left(x\\right)",[0],(x,)) '\\frac{d f\\left(x\\right)}{d x}' sage: latex_d_derivative("f\\left(x\\right)",[0,0],(x,)) '\\frac{d^{2} f\\left(x\\right)}{d {x}^{2}}' sage: f(x,y) = function('f',x,y) sage: latex_d_derivative("f\\left(x, y\\right)",[0],(x,y)) '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' sage: latex_d_derivative("f\\left(x, y\\right)",[0,0,0],(x,y)) '\\frac{\\partial^{3}}{\\partial {x}^{3}}f\\left(x, y\\right)' sage: latex_d_derivative("f\\left(x, y\\right)",[0,1],(x,y)) '\\frac{\\partial^{2}}{\\partial y\\partial x}f\\left(x, y\\right)' AUTHORS: - Golam Mortuza Hossain (2009-06-11) """ # Following lines convert "D" format derivative into "diff" # format and then call the "diff" typesetting function varhash = {} for x in params: if args[x] in varhash: varhash[args[x]] = varhash[args[x]] + 1 else: varhash[args[x]] = 1 newargs = [fstr] for a in args: if a in varhash: newargs.append(a) newargs.append(varhash[a]) # No of variables nvars = len(args) return _derivative_latex_(fstr, newargs, nvars) def _derivative_latex_(fstr, args, nvars): r""" Return LaTeX expression for derivatives of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _derivative_latex_ = latex_module._derivative_latex_ sage: var('x,y') (x, y) sage: f(x) = function('f',x) sage: _derivative_latex_("f\\left(x\\right)",(f(x),x,1),1) '\\frac{d f\\left(x\\right)}{d x}' sage: _derivative_latex_("f\\left(x\\right)",(f(x),x,2),1) '\\frac{d^{2} f\\left(x\\right)}{d {x}^{2}}' sage: f(x,y) = function('f',x,y) sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,1),2) '\\frac{\\partial}{\\partial x}f\\left(x, y\\right)' sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,3),2) '\\frac{\\partial^{3}}{\\partial {x}^{3}}f\\left(x, y\\right)' sage: _derivative_latex_("f\\left(x, y\\right)",(f(x,y),x,1,y,1),2) '\\frac{\\partial^{2}}{\\partial y\\partial x}f\\left(x, y\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ n = len(args) # We dont do any processing for n < 2 if n < 2: return _symbolic_function_default_latex_("diff", args) # Check whether it should be partial derivative # Logic taken from: http://trac.sagemath.org/sage_trac/ticket/4202 if nvars == 1: d_latex = "d" else: d_latex = "\\partial" # Read the variables diffstr = ""; total = 0 for i in range(1,n-1,2): x = args[i]    # variable j = args[i+1]  # no of times diff acts on f w.r.t. variable x total = total + j    # total no of times diff acts if j == 1: diffstr = "%s %s"%(d_latex, latex(x)) + diffstr else: diffstr = "%s {%s}^{%s}"%(d_latex, latex(x), latex(j)) + diffstr # Return final expression if total == 1: if d_latex == "d": return "\\frac{%s %s}{%s}"%(d_latex, fstr, diffstr) else: return "\\frac{%s}{%s}%s"%(d_latex, diffstr, fstr) if d_latex == "d": return "\\frac{%s^{%d} %s}{%s}"%(d_latex, total, fstr, diffstr) else: return "\\frac{%s^{%d}}{%s}%s"%(d_latex, total, diffstr, fstr) def _integrate_latex_(fname, args): r""" Return LaTeX expression for integration of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _integrate_latex_ = latex_module._integrate_latex_ sage: var('x,a,b') (x, a, b) sage: f(x) = function('f',x) sage: _integrate_latex_("integrate",(f(x),x)) '\\int f\\left(x\\right)\\,{d x}' sage: _integrate_latex_("integrate",(f(x),x,a,b)) '\\int_{a}^{b} f\\left(x\\right)\\,{d x}' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ n = len(args) # We dont process if number of arguments is neither 2 nor 4 if n != 2 and n != 4: # Return default typesetting return _symbolic_function_default_latex_(fname, args) f = args[0] x = args[1] # Check whether its a definite integral if n == 4: a = args[2] b = args[3] return "\\int_{%s}^{%s} %s\\,{d %s}"%(latex(a), latex(b), latex(f), latex(x)) # Typeset as indefinite integral return "\\int %s\\,{d %s}"%(latex(f), latex(x)) def _inverse_laplace_latex_(fname, args): r""" Return LaTeX expression for inverse Laplace transform of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _inverse_laplace_latex_ = latex_module._inverse_laplace_latex_ sage: var('s,t') (s, t) sage: F(s) = function('F',s) sage: _inverse_laplace_latex_("ilt",(F(s),s,t)) '\\mathcal{L}^{-1}\\left(F\\left(s\\right), s, t\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in args])) def _laplace_latex_(fname, args): r""" Return LaTeX expression for Laplace transform of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _laplace_latex_ = latex_module._laplace_latex_ sage: var('s,t') (s, t) sage: f(t) = function('f',t) sage: _laplace_latex_("laplace",(f(t),t,s)) '\\mathcal{L}\\left(f\\left(t\\right), t, s\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ return "\\mathcal{L}\\left(%s\\right)"%(', '.join([latex(x) for x in args])) def _limit_latex_(fname, args): r""" Return latex expression for limit of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _limit_latex_ = latex_module._limit_latex_ sage: var('x,a') (x, a) sage: psi(x) = function('psi',x) sage: _limit_latex_("limit",(psi(x),x,a)) '\\lim_{x \\to a}\\, \\psi\\left(x\\right)' AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ # We process only if there are precisely three arguments if len(args) == 3: # Read f,x,a from arguments f = args[0] x = args[1] a = args[2] return "\\lim_{%s \\to %s}\\, %s"%(latex(x), latex(a), latex(f)) # Return default typesetting return _symbolic_function_default_latex_(fname, args) def _conjugate_latex_(fname, args): r""" Return LaTeX expression for conjugate of a symbolic function. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: _conjugate_latex_ = latex_module._conjugate_latex_ sage: var('x') x sage: psi(x) = function('psi',x) sage: _conjugate_latex_("conjugate",psi(x)) '\\overline{\\psi\\left(x\\right)}' AUTHORS: - Golam Mortuza Hossain (2009-06-11) """ # We process only if there is only one argument if len(args) == 1: return "\\overline{%s}"%(latex(args)) # Return default typesetting return _symbolic_function_default_latex_(fname, args) def latex_function_name(x): r""" Return common function names such as alpha, beta1, psi_00, R_mn, etc. as latex symbols, else return False. EXAMPLES:: sage: import sage.misc.latex as latex_module sage: latex_function_name = latex_module.latex_function_name sage: latex_function_name('psi') '\\psi' sage: latex_function_name('psi0') '\\psi_{0}' sage: latex_function_name('f1') 'f_{1}' sage: latex_function_name('psi_mu') '\\psi_{\\mu}' sage: latex_function_name('psi_11') '\\psi_{11}' sage: latex_function_name('R_ab') 'R_{ab}' sage: latex_function_name('R_nu') 'R_{\\nu}' sage: latex_function_name('myfunc') False sage: latex_function_name('psi_') False sage: latex_function_name('abc_xyz_psi') False sage: latex_function_name('abc_beta') False NOTES: This function is based largely on latex_variable_name function. AUTHORS: - Golam Mortuza Hossain (2009-04-05) """ # For known names return them after preprending with "\\" if x in common_varnames: return "\\" + x # Look for underscrore. If found then use its postion to # find the suffix underscore = x.find("_") if underscore == -1: import re # * The "\d|[.,]" means "decimal digit" or period or comma # * The "+" means "1 or more" # * The "$" means "at the end of the line" m = re.search('(\d|[.,])+$',x) if m is None: prefix = x suffix = None else: prefix = x[:m.start()] suffix = x[m.start():] else: prefix = x[:underscore] suffix = x[underscore+1:] if len(suffix)== 0: return False # If suffix contains underscores then don't process if suffix and suffix.find("_") != -1: return False # If prefix is not a common name or a more-than-one letters word # then don't process if prefix not in common_varnames and len(prefix) != 1: return False # Check if prefix or suffix is a common name if prefix in common_varnames: prefix = "\\" + prefix if suffix and len(suffix) > 0: if suffix in common_varnames: suffix = "\\" + suffix return '%s_{%s}'%(prefix, suffix) else: return '%s'%(prefix) def latex_varify(a): if a in common_varnames: return "\\" + a
• ## sage/symbolic/function.pyx

diff -r 6c7354ace3b6 -r 58abaa4df2e2 sage/symbolic/function.pyx
 a my args are: x, y^z sage: latex(foo(x,y^z)) \mbox{t}\left(x, y^{z}\right) t\left(x, y^{z}\right) sage: foo = nfunction('t', 2, print_latex_func=my_print) sage: foo(x,y^z) t(x, y^z) my args are: x, y^z sage: foo = nfunction('t', 2, latex_name='foo') sage: latex(foo(x,y^z)) \mbox{foo}\left(x, y^{z}\right) foo\left(x, y^{z}\right) TESTS::
• ## sage/symbolic/pynac.pyx

diff -r 6c7354ace3b6 -r 58abaa4df2e2 sage/symbolic/pynac.pyx
 a sage: get_sfunction_from_serial(i) == foo True sage: py_latex_function_pystring(i, (x,y^z)) '\\mbox{foo}\\left(x, y^{z}\\right)' sage: py_latex_function_pystring(i, (x,y^z), True) '\\left(\\mbox{foo}\\right)\\left(x, y^{z}\\right)' '{\\it foo}\\left(x, y^{z}\\right)' Test latex_name:: sage: get_sfunction_from_serial(i) == foo True sage: py_latex_function_pystring(i, (x,y^z)) '\\mbox{\\mathrm{bar}}\\left(x, y^{z}\\right)' '\\mathrm{bar}\\left(x, y^{z}\\right)' Test custom func:: return str(res) return res # otherwise, use the latex name if defined # Typesetting is done by latex_symbolic_function from sage.misc.latex import latex_symbolic_function fname = func._name # Use the latex_name if defined if func._latex_name: name = func._latex_name fstr = func._latex_name else: name = func._name # if latex_name is not defined, use default name if fname_paren: olist = [r'\left(', r'\mbox{', name, '}', r'\right)'] else: olist = [r'\mbox{', name, '}'] # print the arguments olist.extend([r'\left(', ', '.join([x._latex_() for x in args]), r'\right)'] ) return ''.join(olist) fstr  = False # Call latex_symbolic_function return latex_symbolic_function (fname, fstr, args) cdef public stdstring* py_latex_function(unsigned id, object args) except +: return string_from_pystr(py_latex_function_pystring(id, args)) print(ostr.c_str()) stdstring_delete(ostr) # Whether new "D" format should be typeset in old "diff" format typeset_d_as_diff = True cdef public stdstring* py_latex_fderivative(unsigned id, object params, object args) except +: """ See documentation of py_print_fderivative for more information. """ # Check whether old "diff" format should be used if typeset_d_as_diff is True: fstr = py_latex_function_pystring(id, args, True) from sage.misc.latex import latex_d_derivative py_res = latex_d_derivative(fstr, params, args) return string_from_pystr(py_res) ostr = ''.join(['D[', ', '.join([repr(int(x)) for x in params]), ']']) fstr = py_latex_function_pystring(id, args, True) py_res = ostr + fstr EXAMPLES:: sage: from sage.symbolic.pynac import py_latex_fderivative_for_doctests as py_latex_fderivative sage: sage.symbolic.pynac.typeset_d_as_diff=False sage: var('x,y,z',ns=1) (x, y, z) sage: from sage.symbolic.function import function, get_sfunction_from_serial, get_ginac_serial sage: get_sfunction_from_serial(i) == foo True sage: py_latex_fderivative(i, (0, 1, 0, 1), (x, y^z)) D[0, 1, 0, 1]\left(\mbox{foo}\right)\left(x, y^{z}\right) D[0, 1, 0, 1]{\it foo}\left(x, y^{z}\right) Test latex_name:: sage: get_sfunction_from_serial(i) == foo True sage: py_latex_fderivative(i, (0, 1, 0, 1), (x, y^z)) D[0, 1, 0, 1]\left(\mbox{\mathrm{bar}}\right)\left(x, y^{z}\right) D[0, 1, 0, 1]\mathrm{bar}\left(x, y^{z}\right) Test custom func::