1 from compiler.ast import *
2 import os
3
4 import AST
5
6
7
8 _EMPTY_MUL = Mul((None, None))
9
10 -def dict2TeX(d, name_dict, lhs_form='%s', split_terms=False, simpleTeX=False):
11 lines = []
12 for lhs, rhs in d.items():
13 if split_terms:
14 ast = AST.strip_parse(rhs)
15 pos, neg = [], []
16 AST._collect_pos_neg(ast, pos, neg)
17 try:
18 lhsTeX = lhs_form % expr2TeX(lhs, name_dict=name_dict)
19 except TypeError:
20 lhsTeX = lhs_form
21 rhsTeX = _ast2TeX(pos[0], name_dict=name_dict)
22 lines.append(r'$ %s $ &=& $ %s $\\' % (lhsTeX, rhsTeX))
23
24 for term in pos[1:]:
25 TeXed = _ast2TeX(term, name_dict=name_dict)
26 lines.append(r' & & $ + \, %s $\\' % TeXed)
27 for term in neg:
28 TeXed = _ast2TeX(term, name_dict=name_dict)
29 lines.append(r' & & $ - \, %s $\\' % TeXed)
30 else:
31 lhsTeX = lhs_form % expr2TeX(lhs, name_dict=name_dict)
32 rhsTeX = expr2TeX(rhs, name_dict=name_dict)
33 lines.append(r'$ %s $ & = & $ %s $\\' % (lhsTeX, rhsTeX))
34
35 if not simpleTeX:
36
37 lines[-1] = '%s[5mm]' % lines[-1]
38
39 all = os.linesep.join(lines)
40
41 if not simpleTeX:
42 all = all.replace(r'\frac{', r'\tabfrac{')
43
44
45 lines = [r'\providecommand{\tabfrac}[2]{%',
46 r' \setlength{\fboxrule}{0pt}%',
47 r' \fbox{$\frac{#1}{#2}$}}',
48 r'\begin{longtable}{lll}'] + [all] + [r'\end{longtable}']
49 all = os.linesep.join(lines)
50
51 return all
52
54 """
55 Return a TeX version of a python math expression.
56
57 name_dict: A dictionary mapping variable names used in the expression to
58 preferred TeX expressions.
59 """
60 ast = AST.strip_parse(expr)
61 return _ast2TeX(ast, name_dict=name_dict)
62
65 """
66 Return a TeX version of an AST.
67
68 outer: The AST's 'parent' node, used to determine whether or not to
69 enclose the result in parentheses. The default of _FARTHEST_OUT will
70 never enclose the result in parentheses.
71
72 name_dict: A dictionary mapping variable names used in the expression to
73 preferred TeX expressions.
74
75 adjust: A numerical value to adjust the priority of this ast for
76 particular cases. For example, the denominator of a '/' needs
77 parentheses in more cases than does the numerator.
78 """
79 if isinstance(ast, Name):
80
81
82 out = name_dict.get(ast.name, ast.name)
83 elif isinstance(ast, Const):
84 out = str(ast.value)
85 elif isinstance(ast, Add):
86 out = '%s + %s' % (_ast2TeX(ast.left, ast, name_dict),
87 _ast2TeX(ast.right, ast, name_dict))
88 elif isinstance(ast, Sub):
89 out = '%s - %s' % (_ast2TeX(ast.left, ast, name_dict),
90 _ast2TeX(ast.right, ast, name_dict, adjust = 1))
91 elif isinstance(ast, Mul) or isinstance(ast, Div):
92
93 nums, denoms = [], []
94 AST._collect_num_denom(ast, nums, denoms)
95
96
97 lam_func = lambda arg: _ast2TeX(arg, _EMPTY_MUL, name_dict)
98 nums = [lam_func(term) for term in nums]
99 if denoms:
100 denoms = [lam_func(term) for term in denoms]
101 out = r'\frac{%s}{%s}' % (r' \cdot '.join(nums),
102 r' \cdot '.join(denoms))
103 else:
104 out = r' \cdot '.join(nums)
105 elif isinstance(ast, Power):
106 out = '{%s}^{%s}' % (_ast2TeX(ast.left, ast, name_dict, adjust = 1),
107 _ast2TeX(ast.right, ast, name_dict))
108 elif isinstance(ast, UnarySub):
109 out = '-%s' % _ast2TeX(ast.expr, ast, name_dict)
110 elif isinstance(ast, UnaryAdd):
111 out = '+%s' % _ast2TeX(ast.expr, ast, name_dict)
112 elif isinstance(ast, CallFunc):
113 lam_func = lambda arg: _ast2TeX(arg, name_dict=name_dict)
114 name = lam_func(ast.node)
115 args = [lam_func(arg) for arg in ast.args]
116 if name == 'sqrt' and len(args) == 1:
117
118 out = r'\sqrt{%s}' % args[0]
119 else:
120 out = r'\operatorname{%s}\left(%s\right)' % (name, r',\,'.join(args))
121 elif isinstance(ast, Or) or isinstance(ast, And):
122 out = r'\operatorname{%s}' % (str(ast))
123
124 if AST._need_parens(outer, ast, adjust):
125 return out
126 else:
127 return r'\left(%s\right)' % out
128