1 | /* File: latex.c |
---|
2 | * Author: Paul S. Wang |
---|
3 | * Date: 9/19/96 |
---|
4 | */ |
---|
5 | |
---|
6 | /* Can do the following now from the 4 .bin files in data/ |
---|
7 | $$ |
---|
8 | \sum_{x=1}^{10}\left(3~x + 2\right) |
---|
9 | $$ |
---|
10 | $$ |
---|
11 | factor\left(x^{4} + x^{3} - 13~x^{2} - x + 12\right) |
---|
12 | $$ |
---|
13 | $$ |
---|
14 | expand\left(\left(x + 1\right)~\left(x + 2\right)\right) |
---|
15 | $$ |
---|
16 | $$ |
---|
17 | \int~{\cos{x}^{2}}\,d\,x |
---|
18 | $$ |
---|
19 | */ |
---|
20 | |
---|
21 | #include "MP.h" |
---|
22 | #include "node.h" |
---|
23 | #include "label.h" |
---|
24 | #include "leaf.h" |
---|
25 | #include "latex.h" |
---|
26 | |
---|
27 | static void get_op_string(/* node_t dnp, char buf[] */); |
---|
28 | static int latex_tag(/* char* op, node_t **args */); |
---|
29 | static int latex_diff(/* char* op, node_t **args */); |
---|
30 | static int latex_int(/* char* op, node_t **args */); |
---|
31 | static int latex_sum(/* char* op, node_t **args */); |
---|
32 | static int latex_cir(/* char* op, node_t **args */); |
---|
33 | |
---|
34 | /****************************************************************** |
---|
35 | * FUNCTION: display_node_latex |
---|
36 | * ARGUMENT: dnp - a pointer to the root of a subtree. |
---|
37 | * RETURN: none |
---|
38 | * PURPOSE: Output the node dnp, not including annotations, |
---|
39 | * to stdout in latex format. |
---|
40 | ******************************************************************/ |
---|
41 | |
---|
42 | void display_node_latex(dnp, p_op) |
---|
43 | node_t *dnp; |
---|
44 | char p_op; /* op of parent node */ |
---|
45 | { node_t **p; |
---|
46 | int i; |
---|
47 | char op[16]; |
---|
48 | /* display simple data node */ |
---|
49 | if ( display_data_node(dnp) ) return; |
---|
50 | |
---|
51 | /* get operator */ |
---|
52 | get_op_string(dnp, op); /* sets op to string */ |
---|
53 | |
---|
54 | /* display latex exprssion */ |
---|
55 | if ((dnp->num_children > 0) && (dnp->type != MP_RawType)) |
---|
56 | p = dnp->child_list; |
---|
57 | else return; |
---|
58 | |
---|
59 | /* arithemetic ops with more than 1 oprands */ |
---|
60 | if ( (dnp->num_children > 1) |
---|
61 | && (*(op) == '+' || *(op) == '-' |
---|
62 | || *(op) == '*' || *(op) == '/' || *(op) == '^') |
---|
63 | ) |
---|
64 | { switch(*op) |
---|
65 | { case '+': |
---|
66 | if ( p_op != '+' ) printf("\\left("); |
---|
67 | for (i = 0; i < dnp->num_children; i++, p++) |
---|
68 | { if ( i > 0 ) |
---|
69 | { if ( is_neg(*p) ) |
---|
70 | { printf(" - "); |
---|
71 | display_node_latex(*((*p)->child_list), *op); |
---|
72 | } |
---|
73 | else |
---|
74 | { printf(" + "); |
---|
75 | display_node_latex(*p, *op); |
---|
76 | } |
---|
77 | } |
---|
78 | else |
---|
79 | display_node_latex(*p, *op); |
---|
80 | } |
---|
81 | if ( p_op != '+' ) printf("\\right)"); |
---|
82 | break; |
---|
83 | case '-': |
---|
84 | if ( p_op != '+' ) printf("\\left("); |
---|
85 | display_node_latex(p[0], '+'); |
---|
86 | printf(" - "); |
---|
87 | display_node_latex(p[1], '-'); |
---|
88 | if ( p_op != '+' ) printf("\\right)"); |
---|
89 | break; |
---|
90 | case '*': |
---|
91 | if ( p_op == '/' || p_op == '^') printf("\\left("); |
---|
92 | for (i = 0; i < dnp->num_children-1; i++, p++) |
---|
93 | { display_node_latex(*p, '*'); |
---|
94 | printf("~", op); |
---|
95 | } |
---|
96 | display_node_latex(*p, '*'); |
---|
97 | if ( p_op == '/' || p_op == '^') printf("\\right)"); |
---|
98 | break; |
---|
99 | case '/': |
---|
100 | /* if ( p_op == '^' || p_op == '/') printf("\\left("); */ |
---|
101 | printf("\\frac{"); |
---|
102 | display_node_latex(p[0], '*'); |
---|
103 | printf("}{"); |
---|
104 | display_node_latex(p[1], '/'); |
---|
105 | printf("}"); |
---|
106 | /* if ( p_op == '^' || p_op == '/') printf("\\right)"); */ |
---|
107 | break; |
---|
108 | case '^': |
---|
109 | /* if ( p_op == '^') printf("\\left("); */ |
---|
110 | display_node_latex(p[0], '^'); |
---|
111 | printf("^{"); |
---|
112 | display_node_latex(p[1], '^'); |
---|
113 | printf("}"); |
---|
114 | /* if ( p_op == '^') printf("\\right)"); */ |
---|
115 | break; |
---|
116 | } |
---|
117 | } |
---|
118 | /* basically the -x case */ |
---|
119 | else if ( (dnp->num_children == 1) |
---|
120 | && (*(op) == '-' || *(op) == '+') |
---|
121 | && is_data_node(p[0]) |
---|
122 | ) |
---|
123 | { printf(op); |
---|
124 | display_data_node(p[0]); |
---|
125 | } |
---|
126 | /* arithemetic ops with 1 expressin oprand, or other oprators */ |
---|
127 | else |
---|
128 | { if ( latex_tag(op, p, dnp->num_children)) return; |
---|
129 | printf(op); printf("\\left("); |
---|
130 | for (i = 0; i < dnp->num_children; i++, p++) |
---|
131 | { display_node_latex(*p, '+'); |
---|
132 | if ( i < dnp->num_children - 1) printf(", "); |
---|
133 | } |
---|
134 | printf("\\right)"); |
---|
135 | } |
---|
136 | } |
---|
137 | |
---|
138 | |
---|
139 | static int latex_tag(op, args, n) |
---|
140 | char* op; node_t **args; int n; |
---|
141 | { if (latex_cir(op, args, n) || |
---|
142 | latex_diff(op, args, n) || |
---|
143 | latex_sum(op, args, n) || |
---|
144 | latex_int(op, args, n) /* ... */ |
---|
145 | ) return 1; |
---|
146 | return 0; |
---|
147 | } |
---|
148 | |
---|
149 | static int latex_cir(op, args, n) |
---|
150 | char* op; node_t **args; int n; |
---|
151 | { if ( strcmp(op,"sin")==0 || strcmp(op,"cos")==0 || strcmp(op,"tan")==0 || |
---|
152 | strcmp(op,"cot")==0 || strcmp(op,"sec")==0 || strcmp(op,"csc")==0 || |
---|
153 | strcmp(op,"arcsin")==0 || strcmp(op,"arccos")==0 || |
---|
154 | strcmp(op,"arctan")==0 || strcmp(op,"sinh")==0 || |
---|
155 | strcmp(op,"cosh")==0 ||strcmp(op,"tanh")==0 || strcmp(op,"coth")==0 || |
---|
156 | strcmp(op,"log")==0 ||strcmp(op,"lg")==0 ||strcmp(op,"ln")==0 |
---|
157 | ) |
---|
158 | { printf("\\%s{", op); |
---|
159 | display_node_latex(args[0], '+'); |
---|
160 | printf("}"); |
---|
161 | return 1; |
---|
162 | } |
---|
163 | return 0; |
---|
164 | } |
---|
165 | |
---|
166 | |
---|
167 | static int latex_diff(op, args, n) |
---|
168 | char* op; node_t **args; int n; |
---|
169 | { if (strcmp(op,"diff")==0 || strcmp(op, "derivative")==0) |
---|
170 | { if (n == 2) /* first derivative */ |
---|
171 | { printf("\\frac{d\\,"); |
---|
172 | display_node_latex(args[0], '+'); |
---|
173 | printf("}{d\\,"); |
---|
174 | display_node_latex(args[1], '+'); |
---|
175 | printf("}"); |
---|
176 | return 1; |
---|
177 | } |
---|
178 | if (n == 3) /* higher derivative */ |
---|
179 | { printf("\\frac{d^{"); |
---|
180 | display_node_latex(args[2], '+'); |
---|
181 | printf("}"); |
---|
182 | display_node_latex(args[0], '+'); |
---|
183 | printf("}{d\\,"); |
---|
184 | display_node_latex(args[1], '+'); |
---|
185 | printf("}^{"); |
---|
186 | display_node_latex(args[2], '+'); |
---|
187 | printf("}"); |
---|
188 | return 1; |
---|
189 | } |
---|
190 | } |
---|
191 | return(0); |
---|
192 | } |
---|
193 | |
---|
194 | static int latex_sum(op, args, n) |
---|
195 | char* op; node_t **args; int n; |
---|
196 | { if (strcmp(op,"sum")==0 && n == 4) |
---|
197 | { printf("\\sum_{"); |
---|
198 | display_node_latex(args[1], '+'); |
---|
199 | printf("="); |
---|
200 | display_node_latex(args[2], '+'); |
---|
201 | printf("}^{"); |
---|
202 | display_node_latex(args[3], '+'); |
---|
203 | printf("}\\left("); |
---|
204 | display_node_latex(args[0], '+'); |
---|
205 | printf("\\right)"); |
---|
206 | return 1; |
---|
207 | } |
---|
208 | return 0; |
---|
209 | } |
---|
210 | |
---|
211 | static int latex_int(op, args, n) |
---|
212 | char* op; node_t **args; int n; |
---|
213 | { if (strcmp(op,"integral")==0 || strcmp(op, "integrate")==0) |
---|
214 | { if (n == 2) /* indefinite integral */ |
---|
215 | { printf("\\int~{"); |
---|
216 | display_node_latex(args[0], '+'); |
---|
217 | printf("}\\,d\\,"); |
---|
218 | display_node_latex(args[1], '+'); |
---|
219 | return 1; |
---|
220 | } |
---|
221 | if (n == 4) /* definite integral */ |
---|
222 | { printf("\\int_{"); |
---|
223 | display_node_latex(args[2], '+'); |
---|
224 | printf("}^{"); |
---|
225 | display_node_latex(args[3], '+'); |
---|
226 | printf("}"); |
---|
227 | display_node_latex(args[0], '+'); |
---|
228 | printf("\\,d\\,"); |
---|
229 | display_node_latex(args[1], '+'); |
---|
230 | return 1; |
---|
231 | } |
---|
232 | } |
---|
233 | return(0); |
---|
234 | } |
---|
235 | |
---|
236 | static void get_op_string(dnp, buf) |
---|
237 | node_t *dnp; |
---|
238 | char buf[]; |
---|
239 | { switch(dnp->type) |
---|
240 | { case MP_OperatorType: |
---|
241 | strcpy(buf, dnp->data); |
---|
242 | return; |
---|
243 | case MP_CommonOperatorType: |
---|
244 | sprintf(buf, "MPop%d ",*((MP_Common_t *)dnp->data)); |
---|
245 | return; |
---|
246 | default : fprintf(stderr, "Unknown type %d\n", dnp->type); |
---|
247 | exit(1); |
---|
248 | } |
---|
249 | /* printing operator annotation as an op-list */ |
---|
250 | /* hard to handle for latex |
---|
251 | if (dnp->annot_list != NULL) |
---|
252 | print_annot(dnp->annot_list, stdout); |
---|
253 | */ |
---|
254 | } |
---|