(math-possible-signs): Added checks to intervals.
[bpt/emacs.git] / lisp / calc / calccomp.el
CommitLineData
3132f345
CW
1;;; calccomp.el --- composition functions for Calc
2
bf77c646 3;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
3132f345
CW
4
5;; Author: David Gillespie <daveg@synaptics.com>
fdcf8e2b 6;; Maintainer: Jay Belanger <belanger@truman.edu>
136211a9
EZ
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY. No author or distributor
12;; accepts responsibility to anyone for the consequences of using it
13;; or for whether it serves any particular purpose or works at all,
14;; unless he says so in writing. Refer to the GNU Emacs General Public
15;; License for full details.
16
17;; Everyone is granted permission to copy, modify and redistribute
18;; GNU Emacs, but only under the conditions described in the
19;; GNU Emacs General Public License. A copy of this license is
20;; supposed to have been given to you along with GNU Emacs so you
21;; can know your rights and responsibilities. It should be in a
22;; file named COPYING. Among other things, the copyright notice
23;; and this notice must be preserved on all copies.
24
3132f345 25;;; Commentary:
136211a9 26
3132f345 27;;; Code:
136211a9
EZ
28
29;; This file is autoloaded from calc-ext.el.
136211a9 30
cfd31ee4 31(require 'calc-ext)
136211a9
EZ
32(require 'calc-macs)
33
3132f345
CW
34(defconst math-eqn-special-funcs
35 '( calcFunc-log
36 calcFunc-ln calcFunc-exp
37 calcFunc-sin calcFunc-cos calcFunc-tan
38 calcFunc-sinh calcFunc-cosh calcFunc-tanh
39 calcFunc-arcsin calcFunc-arccos calcFunc-arctan
40 calcFunc-arcsinh calcFunc-arccosh calcFunc-arctanh))
136211a9
EZ
41
42;;; A "composition" has one of the following forms:
43;;;
44;;; "string" A literal string
45;;;
46;;; (horiz C1 C2 ...) Horizontally abutted sub-compositions
47;;;
48;;; (set LEVEL OFF) Set left margin + offset for line-break level
49;;; (break LEVEL) A potential line-break point
50;;;
51;;; (vleft N C1 C2 ...) Vertically stacked, left-justified sub-comps
52;;; (vcent N C1 C2 ...) Vertically stacked, centered sub-comps
53;;; (vright N C1 C2 ...) Vertically stacked, right-justified sub-comps
54;;; N specifies baseline of the stack, 0=top line.
55;;;
56;;; (supscr C1 C2) Composition C1 with superscript C2
57;;; (subscr C1 C2) Composition C1 with subscript C2
58;;; (rule X) Horizontal line of X, full width of enclosing comp
59;;;
60;;; (tag X C) Composition C corresponds to sub-expression X
61
fdcf8e2b
JB
62;; math-comp-just and math-comp-comma-spc are local to
63;; math-compose-expr, but are used by math-compose-matrix, which is
64;; called by math-compose-expr
65(defvar math-comp-just)
66(defvar math-comp-comma-spc)
67
68;; math-comp-vector-prec is local to math-compose-expr, but is used by
69;; math-compose-matrix and math-compose-rows, which are called by
70;; math-compose-expr.
71(defvar math-comp-vector-prec)
72
73;; math-comp-left-bracket, math-comp-right-bracket and math-comp-comma are
74;; local to math-compose-expr, but are used by math-compose-rows, which is
75;; called by math-compose-expr.
76(defvar math-comp-left-bracket)
77(defvar math-comp-right-bracket)
78(defvar math-comp-comma)
79
80
136211a9
EZ
81(defun math-compose-expr (a prec)
82 (let ((math-compose-level (1+ math-compose-level)))
83 (cond
84 ((or (and (eq a math-comp-selected) a)
85 (and math-comp-tagged
86 (not (eq math-comp-tagged a))))
87 (let ((math-comp-selected nil))
88 (and math-comp-tagged (setq math-comp-tagged a))
89 (list 'tag a (math-compose-expr a prec))))
90 ((and (not (consp a)) (not (integerp a)))
91 (concat "'" (prin1-to-string a)))
92 ((math-scalarp a)
93 (if (or (eq (car-safe a) 'frac)
94 (and (nth 1 calc-frac-format) (Math-integerp a)))
95 (if (memq calc-language '(tex eqn math maple c fortran pascal))
96 (let ((aa (math-adjust-fraction a))
97 (calc-frac-format nil))
98 (math-compose-expr (list '/
99 (if (memq calc-language '(c fortran))
100 (math-float (nth 1 aa))
101 (nth 1 aa))
102 (nth 2 aa)) prec))
103 (if (and (eq calc-language 'big)
104 (= (length (car calc-frac-format)) 1))
105 (let* ((aa (math-adjust-fraction a))
106 (calc-frac-format nil)
107 (math-radix-explicit-format nil)
108 (c (list 'horiz
109 (if (math-negp (nth 1 aa))
110 "- " "")
111 (list 'vcent 1
112 (math-format-number
113 (math-abs (nth 1 aa)))
114 '(rule ?-)
115 (math-format-number (nth 2 aa))))))
116 (if (= calc-number-radix 10)
117 c
118 (list 'horiz "(" c
119 (list 'subscr ")"
120 (int-to-string calc-number-radix)))))
121 (math-format-number a)))
122 (if (not (eq calc-language 'big))
123 (math-format-number a prec)
124 (if (memq (car-safe a) '(cplx polar))
125 (if (math-zerop (nth 2 a))
126 (math-compose-expr (nth 1 a) prec)
127 (list 'horiz "("
128 (math-compose-expr (nth 1 a) 0)
129 (if (eq (car a) 'cplx) ", " "; ")
130 (math-compose-expr (nth 2 a) 0) ")"))
131 (if (or (= calc-number-radix 10)
132 (not (Math-realp a))
133 (and calc-group-digits
134 (not (assoc calc-group-char '((",") (" "))))))
135 (math-format-number a prec)
136 (let ((s (math-format-number a prec))
137 (c nil))
138 (while (string-match (if (> calc-number-radix 14)
139 "\\([0-9]+\\)#\\([0-9a-zA-Z., ]+\\)"
140 "\\([0-9]+\\)#\\([0-9a-dA-D., ]+\\)")
141 s)
142 (setq c (nconc c (list (substring s 0 (match-beginning 0))
143 (list 'subscr
144 (math-match-substring s 2)
145 (math-match-substring s 1))))
146 s (substring s (match-end 0))))
147 (if (string-match
148 "\\*\\([0-9.]+\\)\\^\\(-?[0-9]+\\)\\()?\\)\\'" s)
149 (setq s (list 'horiz
150 (substring s 0 (match-beginning 0)) " "
151 (list 'supscr
152 (math-match-substring s 1)
153 (math-match-substring s 2))
154 (math-match-substring s 3))))
155 (if c (cons 'horiz (nconc c (list s))) s)))))))
156 ((and (get (car a) 'math-compose-forms)
157 (not (eq calc-language 'unform))
158 (let ((comps (get (car a) 'math-compose-forms))
159 temp temp2)
160 (or (and (setq temp (assq calc-language comps))
161 (or (and (setq temp2 (assq (1- (length a)) (cdr temp)))
162 (setq temp (apply (cdr temp2) (cdr a)))
163 (math-compose-expr temp prec))
164 (and (setq temp2 (assq nil (cdr temp)))
165 (funcall (cdr temp2) a))))
166 (and (setq temp (assq nil comps))
167 (or (and (setq temp2 (assq (1- (length a)) (cdr temp)))
168 (setq temp (apply (cdr temp2) (cdr a)))
169 (math-compose-expr temp prec))
170 (and (setq temp2 (assq nil (cdr temp)))
171 (funcall (cdr temp2) a))))))))
172 ((eq (car a) 'vec)
fdcf8e2b 173 (let* ((math-comp-left-bracket (if calc-vector-brackets
136211a9 174 (substring calc-vector-brackets 0 1) ""))
fdcf8e2b 175 (math-comp-right-bracket (if calc-vector-brackets
136211a9
EZ
176 (substring calc-vector-brackets 1 2) ""))
177 (inner-brackets (memq 'R calc-matrix-brackets))
178 (outer-brackets (memq 'O calc-matrix-brackets))
179 (row-commas (memq 'C calc-matrix-brackets))
fdcf8e2b
JB
180 (math-comp-comma-spc (or calc-vector-commas " "))
181 (math-comp-comma (or calc-vector-commas ""))
182 (math-comp-vector-prec (if (or (and calc-vector-commas
136211a9
EZ
183 (math-vector-no-parens a))
184 (memq 'P calc-matrix-brackets)) 0 1000))
fdcf8e2b
JB
185 (math-comp-just (cond ((eq calc-matrix-just 'right) 'vright)
186 ((eq calc-matrix-just 'center) 'vcent)
187 (t 'vleft)))
136211a9
EZ
188 (break calc-break-vectors))
189 (if (and (memq calc-language '(nil big))
190 (not calc-break-vectors)
191 (math-matrixp a) (not (math-matrixp (nth 1 a)))
192 (or calc-full-vectors
193 (and (< (length a) 7) (< (length (nth 1 a)) 7))
194 (progn (setq break t) nil)))
195 (if (progn
fdcf8e2b
JB
196 (setq math-comp-vector-prec (if (or (and calc-vector-commas
197 (math-vector-no-parens
198 (nth 1 a)))
199 (memq 'P calc-matrix-brackets))
200 0 1000))
136211a9
EZ
201 (= (length a) 2))
202 (list 'horiz
fdcf8e2b
JB
203 (concat math-comp-left-bracket math-comp-left-bracket " ")
204 (math-compose-vector (cdr (nth 1 a)) (concat math-comp-comma " ")
205 math-comp-vector-prec)
206 (concat " " math-comp-right-bracket math-comp-right-bracket))
136211a9
EZ
207 (let* ((rows (1- (length a)))
208 (cols (1- (length (nth 1 a))))
209 (base (/ (1- rows) 2))
210 (calc-language 'flat))
211 (append '(horiz)
212 (list (append '(vleft)
213 (list base)
214 (list (concat (and outer-brackets
fdcf8e2b 215 (concat math-comp-left-bracket
136211a9
EZ
216 " "))
217 (and inner-brackets
fdcf8e2b 218 (concat math-comp-left-bracket
136211a9
EZ
219 " "))))
220 (make-list (1- rows)
221 (concat (and outer-brackets
222 " ")
223 (and inner-brackets
224 (concat
fdcf8e2b 225 math-comp-left-bracket
136211a9
EZ
226 " "))))))
227 (math-compose-matrix (cdr a) 1 cols base)
228 (list (append '(vleft)
229 (list base)
230 (make-list (1- rows)
231 (if inner-brackets
232 (concat " "
fdcf8e2b 233 math-comp-right-bracket
136211a9 234 (and row-commas
fdcf8e2b 235 math-comp-comma))
136211a9
EZ
236 (if (and outer-brackets
237 row-commas)
238 ";" "")))
239 (list (concat
240 (and inner-brackets
241 (concat " "
fdcf8e2b 242 math-comp-right-bracket))
136211a9
EZ
243 (and outer-brackets
244 (concat
245 " "
fdcf8e2b 246 math-comp-right-bracket)))))))))
136211a9
EZ
247 (if (and calc-display-strings
248 (cdr a)
249 (math-vector-is-string a))
250 (math-vector-to-string a t)
251 (if (and break (cdr a)
252 (not (eq calc-language 'flat)))
253 (let* ((full (or calc-full-vectors (< (length a) 7)))
254 (rows (if full (1- (length a)) 5))
255 (base (/ (1- rows) 2))
136211a9
EZ
256 (calc-break-vectors nil))
257 (list 'horiz
258 (cons 'vleft (cons base
259 (math-compose-rows
260 (cdr a)
261 (if full rows 3) t)))))
262 (if (or calc-full-vectors (< (length a) 7))
263 (if (and (eq calc-language 'tex)
264 (math-matrixp a))
265 (append '(horiz "\\matrix{ ")
266 (math-compose-tex-matrix (cdr a))
267 '(" }"))
268 (if (and (eq calc-language 'eqn)
269 (math-matrixp a))
270 (append '(horiz "matrix { ")
271 (math-compose-eqn-matrix
272 (cdr (math-transpose a)))
273 '("}"))
274 (if (and (eq calc-language 'maple)
275 (math-matrixp a))
276 (list 'horiz
277 "matrix("
fdcf8e2b
JB
278 math-comp-left-bracket
279 (math-compose-vector (cdr a)
280 (concat math-comp-comma " ")
281 math-comp-vector-prec)
282 math-comp-right-bracket
136211a9
EZ
283 ")")
284 (list 'horiz
fdcf8e2b
JB
285 math-comp-left-bracket
286 (math-compose-vector (cdr a)
287 (concat math-comp-comma " ")
288 math-comp-vector-prec)
289 math-comp-right-bracket))))
136211a9 290 (list 'horiz
fdcf8e2b 291 math-comp-left-bracket
136211a9 292 (math-compose-vector (list (nth 1 a) (nth 2 a) (nth 3 a))
fdcf8e2b
JB
293 (concat math-comp-comma " ")
294 math-comp-vector-prec)
295 math-comp-comma (if (eq calc-language 'tex) " \\ldots" " ...")
296 math-comp-comma " "
136211a9
EZ
297 (list 'break math-compose-level)
298 (math-compose-expr (nth (1- (length a)) a)
fdcf8e2b
JB
299 (if (equal math-comp-comma "") 1000 0))
300 math-comp-right-bracket)))))))
136211a9
EZ
301 ((eq (car a) 'incomplete)
302 (if (cdr (cdr a))
303 (cond ((eq (nth 1 a) 'vec)
304 (list 'horiz "["
305 (math-compose-vector (cdr (cdr a)) ", " 0)
306 " ..."))
307 ((eq (nth 1 a) 'cplx)
308 (list 'horiz "("
309 (math-compose-vector (cdr (cdr a)) ", " 0)
310 ", ..."))
311 ((eq (nth 1 a) 'polar)
312 (list 'horiz "("
313 (math-compose-vector (cdr (cdr a)) "; " 0)
314 "; ..."))
315 ((eq (nth 1 a) 'intv)
316 (list 'horiz
317 (if (memq (nth 2 a) '(0 1)) "(" "[")
318 (math-compose-vector (cdr (cdr (cdr a))) " .. " 0)
319 " .. ..."))
320 (t (format "%s" a)))
321 (cond ((eq (nth 1 a) 'vec) "[ ...")
322 ((eq (nth 1 a) 'intv)
323 (if (memq (nth 2 a) '(0 1)) "( ..." "[ ..."))
324 (t "( ..."))))
325 ((eq (car a) 'var)
326 (let ((v (rassq (nth 2 a) math-expr-variable-mapping)))
327 (if v
328 (symbol-name (car v))
329 (if (and (eq calc-language 'tex)
330 calc-language-option
331 (not (= calc-language-option 0))
332 (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'"
333 (symbol-name (nth 1 a))))
334 (format "\\hbox{%s}" (symbol-name (nth 1 a)))
335 (if (and math-compose-hash-args
336 (let ((p calc-arg-values))
337 (setq v 1)
338 (while (and p (not (equal (car p) a)))
339 (setq p (and (eq math-compose-hash-args t) (cdr p))
340 v (1+ v)))
341 p))
342 (if (eq math-compose-hash-args 1)
343 "#"
344 (format "#%d" v))
345 (if (memq calc-language '(c fortran pascal maple))
346 (math-to-underscores (symbol-name (nth 1 a)))
347 (if (and (eq calc-language 'eqn)
348 (string-match ".'\\'" (symbol-name (nth 2 a))))
349 (math-compose-expr
350 (list 'calcFunc-Prime
351 (list
352 'var
353 (intern (substring (symbol-name (nth 1 a)) 0 -1))
354 (intern (substring (symbol-name (nth 2 a)) 0 -1))))
355 prec)
356 (symbol-name (nth 1 a)))))))))
357 ((eq (car a) 'intv)
358 (list 'horiz
359 (if (eq calc-language 'maple) ""
360 (if (memq (nth 1 a) '(0 1)) "(" "["))
361 (math-compose-expr (nth 2 a) 0)
362 (if (eq calc-language 'tex) " \\ldots "
363 (if (eq calc-language 'eqn) " ... " " .. "))
364 (math-compose-expr (nth 3 a) 0)
365 (if (eq calc-language 'maple) ""
366 (if (memq (nth 1 a) '(0 2)) ")" "]"))))
367 ((eq (car a) 'date)
368 (if (eq (car calc-date-format) 'X)
369 (math-format-date a)
370 (concat "<" (math-format-date a) ">")))
371 ((and (eq (car a) 'calcFunc-subscr) (cdr (cdr a))
372 (memq calc-language '(c pascal fortran maple)))
373 (let ((args (cdr (cdr a))))
374 (while (and (memq calc-language '(pascal fortran))
375 (eq (car-safe (nth 1 a)) 'calcFunc-subscr))
376 (setq args (append (cdr (cdr (nth 1 a))) args)
377 a (nth 1 a)))
378 (list 'horiz
379 (math-compose-expr (nth 1 a) 1000)
380 (if (eq calc-language 'fortran) "(" "[")
381 (math-compose-vector args ", " 0)
382 (if (eq calc-language 'fortran) ")" "]"))))
383 ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3)
384 (eq calc-language 'big))
385 (let* ((a1 (math-compose-expr (nth 1 a) 1000))
386 (calc-language 'flat)
387 (a2 (math-compose-expr (nth 2 a) 0)))
388 (if (or (eq (car-safe a1) 'subscr)
389 (and (eq (car-safe a1) 'tag)
390 (eq (car-safe (nth 2 a1)) 'subscr)
391 (setq a1 (nth 2 a1))))
392 (list 'subscr
393 (nth 1 a1)
394 (list 'horiz
395 (nth 2 a1)
396 ", "
397 a2))
398 (list 'subscr a1 a2))))
399 ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3)
400 (eq calc-language 'math))
401 (list 'horiz
402 (math-compose-expr (nth 1 a) 1000)
403 "[["
404 (math-compose-expr (nth 2 a) 0)
405 "]]"))
406 ((and (eq (car a) 'calcFunc-sqrt)
407 (eq calc-language 'tex))
408 (list 'horiz
409 "\\sqrt{"
410 (math-compose-expr (nth 1 a) 0)
411 "}"))
412 ((and nil (eq (car a) 'calcFunc-sqrt)
413 (eq calc-language 'eqn))
414 (list 'horiz
415 "sqrt {"
416 (math-compose-expr (nth 1 a) -1)
417 "}"))
418 ((and (eq (car a) '^)
419 (eq calc-language 'big))
420 (list 'supscr
421 (if (or (math-looks-negp (nth 1 a))
422 (memq (car-safe (nth 1 a)) '(^ / frac calcFunc-sqrt))
423 (and (eq (car-safe (nth 1 a)) 'cplx)
424 (math-negp (nth 1 (nth 1 a)))
425 (eq (nth 2 (nth 1 a)) 0)))
426 (list 'horiz "(" (math-compose-expr (nth 1 a) 0) ")")
427 (math-compose-expr (nth 1 a) 201))
428 (let ((calc-language 'flat)
429 (calc-number-radix 10))
430 (math-compose-expr (nth 2 a) 0))))
431 ((and (eq (car a) '/)
432 (eq calc-language 'big))
433 (let ((a1 (let ((calc-language (if (memq (car-safe (nth 1 a)) '(/ frac))
434 'flat 'big)))
435 (math-compose-expr (nth 1 a) 0)))
436 (a2 (let ((calc-language (if (memq (car-safe (nth 2 a)) '(/ frac))
437 'flat 'big)))
438 (math-compose-expr (nth 2 a) 0))))
439 (list 'vcent
440 (math-comp-height a1)
441 a1 '(rule ?-) a2)))
442 ((and (memq (car a) '(calcFunc-sum calcFunc-prod))
443 (eq calc-language 'tex)
444 (= (length a) 5))
445 (list 'horiz (if (eq (car a) 'calcFunc-sum) "\\sum" "\\prod")
446 "_{" (math-compose-expr (nth 2 a) 0)
447 "=" (math-compose-expr (nth 3 a) 0)
448 "}^{" (math-compose-expr (nth 4 a) 0)
449 "}{" (math-compose-expr (nth 1 a) 0) "}"))
450 ((and (eq (car a) 'calcFunc-lambda)
451 (> (length a) 2)
452 (memq calc-language '(nil flat big)))
453 (let ((p (cdr a))
454 (ap calc-arg-values)
455 (math-compose-hash-args (if (= (length a) 3) 1 t)))
456 (while (and (cdr p) (equal (car p) (car ap)))
457 (setq p (cdr p) ap (cdr ap)))
458 (append '(horiz "<")
459 (if (cdr p)
460 (list (math-compose-vector
461 (nreverse (cdr (reverse (cdr a)))) ", " 0)
462 " : ")
463 nil)
464 (list (math-compose-expr (nth (1- (length a)) a) 0)
465 ">"))))
466 ((and (eq (car a) 'calcFunc-string)
467 (= (length a) 2)
468 (math-vectorp (nth 1 a))
469 (math-vector-is-string (nth 1 a)))
470 (if (eq calc-language 'unform)
471 (concat "string(" (math-vector-to-string (nth 1 a) t) ")")
472 (math-vector-to-string (nth 1 a) nil)))
473 ((and (eq (car a) 'calcFunc-bstring)
474 (= (length a) 2)
475 (math-vectorp (nth 1 a))
476 (math-vector-is-string (nth 1 a)))
477 (if (eq calc-language 'unform)
478 (concat "bstring(" (math-vector-to-string (nth 1 a) t) ")")
479 (let ((c nil)
480 (s (math-vector-to-string (nth 1 a) nil))
481 p)
482 (while (string-match "[^ ] +[^ ]" s)
483 (setq p (1- (match-end 0))
484 c (cons (list 'break math-compose-level)
485 (cons (substring s 0 p)
486 c))
487 s (substring s p)))
488 (setq c (nreverse (cons s c)))
489 (or (= prec -123)
490 (setq c (cons (list 'set math-compose-level 2) c)))
491 (cons 'horiz c))))
492 ((and (eq (car a) 'calcFunc-cprec)
493 (not (eq calc-language 'unform))
494 (= (length a) 3)
495 (integerp (nth 2 a)))
496 (let ((c (math-compose-expr (nth 1 a) -1)))
497 (if (> prec (nth 2 a))
498 (if (eq calc-language 'tex)
499 (list 'horiz "\\left( " c " \\right)")
500 (if (eq calc-language 'eqn)
501 (list 'horiz "{left ( " c " right )}")
502 (list 'horiz "(" c ")")))
503 c)))
504 ((and (eq (car a) 'calcFunc-choriz)
505 (not (eq calc-language 'unform))
506 (memq (length a) '(2 3 4))
507 (math-vectorp (nth 1 a))
508 (if (integerp (nth 2 a))
509 (or (null (nth 3 a))
510 (and (math-vectorp (nth 3 a))
511 (math-vector-is-string (nth 3 a))))
512 (or (null (nth 2 a))
513 (and (math-vectorp (nth 2 a))
514 (math-vector-is-string (nth 2 a))))))
515 (let* ((cprec (and (integerp (nth 2 a)) (nth 2 a)))
516 (sep (nth (if cprec 3 2) a))
517 (bprec nil))
518 (if sep
519 (math-compose-vector (cdr (nth 1 a))
520 (math-vector-to-string sep nil)
521 (or cprec prec))
522 (cons 'horiz (mapcar (function
523 (lambda (x)
524 (if (eq (car-safe x) 'calcFunc-bstring)
525 (prog1
526 (math-compose-expr
527 x (or bprec cprec prec))
528 (setq bprec -123))
529 (math-compose-expr x (or cprec prec)))))
530 (cdr (nth 1 a)))))))
531 ((and (memq (car a) '(calcFunc-cvert calcFunc-clvert calcFunc-crvert))
532 (not (eq calc-language 'unform))
533 (memq (length a) '(2 3))
534 (math-vectorp (nth 1 a))
535 (or (null (nth 2 a))
536 (integerp (nth 2 a))))
537 (let* ((base 0)
538 (v 0)
539 (prec (or (nth 2 a) prec))
540 (c (mapcar (function
541 (lambda (x)
542 (let ((b nil) (cc nil) a d)
543 (if (and (memq (car-safe x) '(calcFunc-cbase
544 calcFunc-ctbase
545 calcFunc-cbbase))
546 (memq (length x) '(1 2)))
547 (setq b (car x)
548 x (nth 1 x)))
549 (if (and (eq (car-safe x) 'calcFunc-crule)
550 (memq (length x) '(1 2))
551 (or (null (nth 1 x))
552 (and (math-vectorp (nth 1 x))
553 (= (length (nth 1 x)) 2)
554 (math-vector-is-string
555 (nth 1 x)))
556 (and (natnump (nth 1 x))
557 (<= (nth 1 x) 255))))
558 (setq cc (list
559 'rule
560 (if (math-vectorp (nth 1 x))
561 (aref (math-vector-to-string
562 (nth 1 x) nil) 0)
563 (or (nth 1 x) ?-))))
564 (or (and (memq (car-safe x) '(calcFunc-cvspace
565 calcFunc-ctspace
566 calcFunc-cbspace))
567 (memq (length x) '(2 3))
568 (eq (nth 1 x) 0))
569 (null x)
570 (setq cc (math-compose-expr x prec))))
571 (setq a (if cc (math-comp-ascent cc) 0)
572 d (if cc (math-comp-descent cc) 0))
573 (if (eq b 'calcFunc-cbase)
574 (setq base (+ v a -1))
575 (if (eq b 'calcFunc-ctbase)
576 (setq base v)
577 (if (eq b 'calcFunc-cbbase)
578 (setq base (+ v a d -1)))))
579 (setq v (+ v a d))
580 cc)))
581 (cdr (nth 1 a)))))
582 (setq c (delq nil c))
583 (if c
584 (cons (if (eq (car a) 'calcFunc-cvert) 'vcent
585 (if (eq (car a) 'calcFunc-clvert) 'vleft 'vright))
586 (cons base c))
587 " ")))
588 ((and (memq (car a) '(calcFunc-csup calcFunc-csub))
589 (not (eq calc-language 'unform))
590 (memq (length a) '(3 4))
591 (or (null (nth 3 a))
592 (integerp (nth 3 a))))
593 (list (if (eq (car a) 'calcFunc-csup) 'supscr 'subscr)
594 (math-compose-expr (nth 1 a) (or (nth 3 a) 0))
595 (math-compose-expr (nth 2 a) 0)))
596 ((and (eq (car a) 'calcFunc-cflat)
597 (not (eq calc-language 'unform))
598 (memq (length a) '(2 3))
599 (or (null (nth 2 a))
600 (integerp (nth 2 a))))
601 (let ((calc-language (if (memq calc-language '(nil big))
602 'flat calc-language)))
603 (math-compose-expr (nth 1 a) (or (nth 2 a) 0))))
604 ((and (eq (car a) 'calcFunc-cspace)
605 (memq (length a) '(2 3))
606 (natnump (nth 1 a)))
607 (if (nth 2 a)
608 (cons 'horiz (make-list (nth 1 a)
609 (if (and (math-vectorp (nth 2 a))
610 (math-vector-is-string (nth 2 a)))
611 (math-vector-to-string (nth 2 a) nil)
612 (math-compose-expr (nth 2 a) 0))))
613 (make-string (nth 1 a) ?\ )))
614 ((and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
615 (memq (length a) '(2 3))
616 (natnump (nth 1 a)))
617 (if (= (nth 1 a) 0)
618 ""
619 (let* ((c (if (nth 2 a)
620 (if (and (math-vectorp (nth 2 a))
621 (math-vector-is-string (nth 2 a)))
622 (math-vector-to-string (nth 2 a) nil)
623 (math-compose-expr (nth 2 a) 0))
624 " "))
625 (ca (math-comp-ascent c))
626 (cd (math-comp-descent c)))
627 (cons 'vleft
628 (cons (if (eq (car a) 'calcFunc-ctspace)
629 (1- ca)
630 (if (eq (car a) 'calcFunc-cbspace)
631 (+ (* (1- (nth 1 a)) (+ ca cd)) (1- ca))
632 (/ (1- (* (nth 1 a) (+ ca cd))) 2)))
633 (make-list (nth 1 a) c))))))
634 ((and (eq (car a) 'calcFunc-evalto)
635 (setq calc-any-evaltos t)
636 (memq calc-language '(tex eqn))
637 (= math-compose-level (if math-comp-tagged 2 1))
638 (= (length a) 3))
639 (list 'horiz
640 (if (eq calc-language 'tex) "\\evalto " "evalto ")
641 (math-compose-expr (nth 1 a) 0)
642 (if (eq calc-language 'tex) " \\to " " -> ")
643 (math-compose-expr (nth 2 a) 0)))
644 (t
645 (let ((op (and (not (eq calc-language 'unform))
646 (if (and (eq (car a) 'calcFunc-if) (= (length a) 4))
647 (assoc "?" math-expr-opers)
648 (math-assq2 (car a) math-expr-opers)))))
649 (cond ((and op
650 (or (= (length a) 3) (eq (car a) 'calcFunc-if))
651 (/= (nth 3 op) -1))
652 (cond
653 ((> prec (or (nth 4 op) (min (nth 2 op) (nth 3 op))))
654 (if (and (eq calc-language 'tex)
655 (not (math-tex-expr-is-flat a)))
656 (if (eq (car-safe a) '/)
657 (list 'horiz "{" (math-compose-expr a -1) "}")
658 (list 'horiz "\\left( "
659 (math-compose-expr a -1)
660 " \\right)"))
661 (if (eq calc-language 'eqn)
662 (if (or (eq (car-safe a) '/)
663 (= (/ prec 100) 9))
664 (list 'horiz "{" (math-compose-expr a -1) "}")
665 (if (math-tex-expr-is-flat a)
666 (list 'horiz "( " (math-compose-expr a -1) " )")
667 (list 'horiz "{left ( "
668 (math-compose-expr a -1)
669 " right )}")))
670 (list 'horiz "(" (math-compose-expr a 0) ")"))))
671 ((and (eq calc-language 'tex)
672 (memq (car a) '(/ calcFunc-choose calcFunc-evalto))
673 (>= prec 0))
674 (list 'horiz "{" (math-compose-expr a -1) "}"))
675 ((eq (car a) 'calcFunc-if)
676 (list 'horiz
677 (math-compose-expr (nth 1 a) (nth 2 op))
678 " ? "
679 (math-compose-expr (nth 2 a) 0)
680 " : "
681 (math-compose-expr (nth 3 a) (nth 3 op))))
682 (t
683 (let* ((math-comp-tagged (and math-comp-tagged
684 (not (math-primp a))
685 math-comp-tagged))
686 (setlev (if (= prec (min (nth 2 op) (nth 3 op)))
687 (progn
688 (setq math-compose-level
689 (1- math-compose-level))
690 nil)
691 math-compose-level))
692 (lhs (math-compose-expr (nth 1 a) (nth 2 op)))
693 (rhs (math-compose-expr (nth 2 a) (nth 3 op))))
694 (and (equal (car op) "^")
695 (eq (math-comp-first-char lhs) ?-)
696 (setq lhs (list 'horiz "(" lhs ")")))
697 (and (eq calc-language 'tex)
698 (or (equal (car op) "^") (equal (car op) "_"))
699 (not (and (stringp rhs) (= (length rhs) 1)))
700 (setq rhs (list 'horiz "{" rhs "}")))
701 (or (and (eq (car a) '*)
702 (or (null calc-language)
703 (assoc "2x" math-expr-opers))
704 (let* ((prevt (math-prod-last-term (nth 1 a)))
705 (nextt (math-prod-first-term (nth 2 a)))
706 (prevc (or (math-comp-last-char lhs)
707 (and (memq (car-safe prevt)
708 '(^ calcFunc-subscr
709 calcFunc-sqrt
710 frac))
711 (eq calc-language 'big)
712 ?0)))
713 (nextc (or (math-comp-first-char rhs)
714 (and (memq (car-safe nextt)
715 '(calcFunc-sqrt
716 calcFunc-sum
717 calcFunc-prod
718 calcFunc-integ))
719 (eq calc-language 'big)
720 ?0))))
721 (and prevc nextc
722 (or (and (>= nextc ?a) (<= nextc ?z))
723 (and (>= nextc ?A) (<= nextc ?Z))
724 (and (>= nextc ?0) (<= nextc ?9))
725 (memq nextc '(?. ?_ ?#
726 ?\( ?\[ ?\{))
727 (and (eq nextc ?\\)
728 (not (string-match
729 "\\`\\\\left("
730 (math-comp-first-string
731 rhs)))))
732 (not (and (eq (car-safe prevt) 'var)
733 (eq nextc ?\()))
734 (list 'horiz
735 (list 'set setlev 1)
736 lhs
737 (list 'break math-compose-level)
738 " "
739 rhs))))
740 (list 'horiz
741 (list 'set setlev 1)
742 lhs
743 (list 'break math-compose-level)
744 (if (or (equal (car op) "^")
745 (equal (car op) "_")
746 (equal (car op) "**")
747 (and (equal (car op) "*")
748 (math-comp-last-char lhs)
749 (math-comp-first-char rhs))
750 (and (equal (car op) "/")
751 (math-num-integerp (nth 1 a))
752 (math-integerp (nth 2 a))))
753 (car op)
754 (if (and (eq calc-language 'big)
755 (equal (car op) "=>"))
756 " => "
757 (concat " " (car op) " ")))
758 rhs))))))
759 ((and op (= (length a) 2) (= (nth 3 op) -1))
760 (cond
761 ((or (> prec (or (nth 4 op) (nth 2 op)))
762 (and (not (eq (assoc (car op) math-expr-opers) op))
763 (> prec 0))) ; don't write x% + y
764 (if (and (eq calc-language 'tex)
765 (not (math-tex-expr-is-flat a)))
766 (list 'horiz "\\left( "
767 (math-compose-expr a -1)
768 " \\right)")
769 (if (eq calc-language 'eqn)
770 (if (= (/ prec 100) 9)
771 (list 'horiz "{" (math-compose-expr a -1) "}")
772 (if (math-tex-expr-is-flat a)
773 (list 'horiz "{( " (math-compose-expr a -1) " )}")
774 (list 'horiz "{left ( "
775 (math-compose-expr a -1)
776 " right )}")))
777 (list 'horiz "(" (math-compose-expr a 0) ")"))))
778 (t
779 (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op))))
780 (list 'horiz
781 lhs
782 (if (or (> (length (car op)) 1)
783 (not (math-comp-is-flat lhs)))
784 (concat " " (car op))
785 (car op)))))))
786 ((and op (= (length a) 2) (= (nth 2 op) -1))
787 (cond
788 ((eq (nth 3 op) 0)
789 (let ((lr (and (eq calc-language 'tex)
790 (not (math-tex-expr-is-flat (nth 1 a))))))
791 (list 'horiz
792 (if lr "\\left" "")
793 (if (string-match "\\`u\\([^a-zA-Z]\\)\\'" (car op))
794 (substring (car op) 1)
795 (car op))
796 (if (or lr (> (length (car op)) 2)) " " "")
797 (math-compose-expr (nth 1 a) -1)
798 (if (or lr (> (length (car op)) 2)) " " "")
799 (if lr "\\right" "")
800 (car (nth 1 (memq op math-expr-opers))))))
801 ((> prec (or (nth 4 op) (nth 3 op)))
802 (if (and (eq calc-language 'tex)
803 (not (math-tex-expr-is-flat a)))
804 (list 'horiz "\\left( "
805 (math-compose-expr a -1)
806 " \\right)")
807 (if (eq calc-language 'eqn)
808 (if (= (/ prec 100) 9)
809 (list 'horiz "{" (math-compose-expr a -1) "}")
810 (if (math-tex-expr-is-flat a)
811 (list 'horiz "{( " (math-compose-expr a -1) " )}")
812 (list 'horiz "{left ( "
813 (math-compose-expr a -1)
814 " right )}")))
815 (list 'horiz "(" (math-compose-expr a 0) ")"))))
816 (t
817 (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op))))
818 (list 'horiz
819 (let ((ops (if (string-match "\\`u\\([^a-zA-Z]\\)\\'"
820 (car op))
821 (substring (car op) 1)
822 (car op))))
823 (if (or (> (length ops) 1)
824 (not (math-comp-is-flat rhs)))
825 (concat ops " ")
826 ops))
827 rhs)))))
828 ((and (eq calc-language 'big)
829 (setq op (get (car a) 'math-compose-big))
830 (funcall op a prec)))
831 ((and (setq op (assq calc-language
832 '( ( nil . math-compose-normal )
833 ( flat . math-compose-normal )
834 ( big . math-compose-normal )
835 ( c . math-compose-c )
836 ( pascal . math-compose-pascal )
837 ( fortran . math-compose-fortran )
838 ( tex . math-compose-tex )
839 ( eqn . math-compose-eqn )
840 ( math . math-compose-math )
841 ( maple . math-compose-maple ))))
842 (setq op (get (car a) (cdr op)))
843 (funcall op a prec)))
844 (t
845 (let* ((func (car a))
846 (func2 (assq func '(( mod . calcFunc-makemod )
847 ( sdev . calcFunc-sdev )
848 ( + . calcFunc-add )
849 ( - . calcFunc-sub )
850 ( * . calcFunc-mul )
851 ( / . calcFunc-div )
852 ( % . calcFunc-mod )
853 ( ^ . calcFunc-pow )
854 ( neg . calcFunc-neg )
855 ( | . calcFunc-vconcat ))))
856 left right args)
857 (if func2
858 (setq func (cdr func2)))
859 (if (setq func2 (rassq func math-expr-function-mapping))
860 (setq func (car func2)))
861 (setq func (math-remove-dashes
862 (if (string-match
863 "\\`calcFunc-\\([a-zA-Z0-9']+\\)\\'"
864 (symbol-name func))
865 (math-match-substring (symbol-name func) 1)
866 (symbol-name func))))
867 (if (memq calc-language '(c fortran pascal maple))
868 (setq func (math-to-underscores func)))
869 (if (and (eq calc-language 'tex)
870 calc-language-option
871 (not (= calc-language-option 0))
872 (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'" func))
873 (if (< (prefix-numeric-value calc-language-option) 0)
874 (setq func (format "\\%s" func))
875 (setq func (format "\\hbox{%s}" func))))
876 (if (and (eq calc-language 'eqn)
877 (string-match "[^']'+\\'" func))
878 (let ((n (- (length func) (match-beginning 0) 1)))
879 (setq func (substring func 0 (- n)))
880 (while (>= (setq n (1- n)) 0)
881 (setq func (concat func " prime")))))
882 (cond ((and (eq calc-language 'tex)
883 (or (> (length a) 2)
884 (not (math-tex-expr-is-flat (nth 1 a)))))
885 (setq left "\\left( "
886 right " \\right)"))
887 ((and (eq calc-language 'eqn)
888 (or (> (length a) 2)
889 (not (math-tex-expr-is-flat (nth 1 a)))))
890 (setq left "{left ( "
891 right " right )}"))
892 ((and (or (and (eq calc-language 'tex)
893 (eq (aref func 0) ?\\))
894 (and (eq calc-language 'eqn)
895 (memq (car a) math-eqn-special-funcs)))
896 (not (string-match "\\hbox{" func))
897 (= (length a) 2)
898 (or (Math-realp (nth 1 a))
899 (memq (car (nth 1 a)) '(var *))))
900 (setq left (if (eq calc-language 'eqn) "~{" "{")
901 right "}"))
902 ((eq calc-language 'eqn)
903 (setq left " ( "
904 right " )"))
905 (t (setq left calc-function-open
906 right calc-function-close)))
907 (list 'horiz func left
908 (math-compose-vector (cdr a)
909 (if (eq calc-language 'eqn)
910 " , " ", ")
911 0)
bf77c646 912 right)))))))))
136211a9 913
136211a9
EZ
914
915(defun math-prod-first-term (x)
916 (while (eq (car-safe x) '*)
917 (setq x (nth 1 x)))
bf77c646 918 x)
136211a9
EZ
919
920(defun math-prod-last-term (x)
921 (while (eq (car-safe x) '*)
922 (setq x (nth 2 x)))
bf77c646 923 x)
136211a9
EZ
924
925(defun math-compose-vector (a sep prec)
926 (if a
927 (cons 'horiz
928 (cons (list 'set math-compose-level)
929 (let ((c (list (math-compose-expr (car a) prec))))
930 (while (setq a (cdr a))
931 (setq c (cons (if (eq (car-safe (car a))
932 'calcFunc-bstring)
933 (let ((math-compose-level
934 (1- math-compose-level)))
935 (math-compose-expr (car a) -123))
936 (math-compose-expr (car a) prec))
937 (cons (list 'break math-compose-level)
938 (cons sep c)))))
939 (nreverse c))))
bf77c646 940 ""))
136211a9
EZ
941
942(defun math-vector-no-parens (a)
943 (or (cdr (cdr a))
bf77c646 944 (not (eq (car-safe (nth 1 a)) '*))))
136211a9
EZ
945
946(defun math-compose-matrix (a col cols base)
947 (let ((col 0)
948 (res nil))
949 (while (<= (setq col (1+ col)) cols)
fdcf8e2b 950 (setq res (cons (cons math-comp-just
136211a9
EZ
951 (cons base
952 (mapcar (function
953 (lambda (r)
954 (list 'horiz
955 (math-compose-expr
956 (nth col r)
fdcf8e2b 957 math-comp-vector-prec)
136211a9
EZ
958 (if (= col cols)
959 ""
fdcf8e2b
JB
960 (concat
961 math-comp-comma-spc " ")))))
136211a9
EZ
962 a)))
963 res)))
bf77c646 964 (nreverse res)))
136211a9
EZ
965
966(defun math-compose-rows (a count first)
967 (if (cdr a)
968 (if (<= count 0)
969 (if (< count 0)
970 (math-compose-rows (cdr a) -1 nil)
971 (cons (concat (if (eq calc-language 'tex) " \\ldots" " ...")
fdcf8e2b 972 math-comp-comma)
136211a9
EZ
973 (math-compose-rows (cdr a) -1 nil)))
974 (cons (list 'horiz
fdcf8e2b
JB
975 (if first (concat math-comp-left-bracket " ") " ")
976 (math-compose-expr (car a) math-comp-vector-prec)
977 math-comp-comma)
136211a9
EZ
978 (math-compose-rows (cdr a) (1- count) nil)))
979 (list (list 'horiz
fdcf8e2b
JB
980 (if first (concat math-comp-left-bracket " ") " ")
981 (math-compose-expr (car a) math-comp-vector-prec)
982 (concat " " math-comp-right-bracket)))))
136211a9
EZ
983
984(defun math-compose-tex-matrix (a)
985 (if (cdr a)
986 (cons (math-compose-vector (cdr (car a)) " & " 0)
987 (cons " \\\\ "
988 (math-compose-tex-matrix (cdr a))))
bf77c646 989 (list (math-compose-vector (cdr (car a)) " & " 0))))
136211a9
EZ
990
991(defun math-compose-eqn-matrix (a)
992 (if a
993 (cons
994 (cond ((eq calc-matrix-just 'right) "rcol ")
995 ((eq calc-matrix-just 'center) "ccol ")
996 (t "lcol "))
997 (cons
998 (list 'break math-compose-level)
999 (cons
1000 "{ "
1001 (cons
1002 (let ((math-compose-level (1+ math-compose-level)))
1003 (math-compose-vector (cdr (car a)) " above " 1000))
1004 (cons
1005 " } "
1006 (math-compose-eqn-matrix (cdr a)))))))
bf77c646 1007 nil))
136211a9
EZ
1008
1009(defun math-vector-is-string (a)
1010 (while (and (setq a (cdr a))
1011 (or (and (natnump (car a))
1012 (<= (car a) 255))
1013 (and (eq (car-safe (car a)) 'cplx)
1014 (natnump (nth 1 (car a)))
1015 (eq (nth 2 (car a)) 0)
1016 (<= (nth 1 (car a)) 255)))))
bf77c646 1017 (null a))
136211a9 1018
3132f345
CW
1019(defconst math-vector-to-string-chars '( ( ?\" . "\\\"" )
1020 ( ?\\ . "\\\\" )
1021 ( ?\a . "\\a" )
1022 ( ?\b . "\\b" )
1023 ( ?\e . "\\e" )
1024 ( ?\f . "\\f" )
1025 ( ?\n . "\\n" )
1026 ( ?\r . "\\r" )
1027 ( ?\t . "\\t" )
1028 ( ?\^? . "\\^?" )))
1029
136211a9
EZ
1030(defun math-vector-to-string (a &optional quoted)
1031 (setq a (concat (mapcar (function (lambda (x) (if (consp x) (nth 1 x) x)))
1032 (cdr a))))
1033 (if (string-match "[\000-\037\177\\\"]" a)
1034 (let ((p 0)
1035 (pat (if quoted "[\000-\037\177\\\"]" "[\000-\037\177]"))
1036 (codes (if quoted math-vector-to-string-chars '((?\^? . "^?"))))
1037 (fmt (if quoted "\\^%c" "^%c"))
1038 new)
1039 (while (setq p (string-match pat a p))
1040 (if (setq new (assq (aref a p) codes))
1041 (setq a (concat (substring a 0 p)
1042 (cdr new)
1043 (substring a (1+ p)))
1044 p (+ p (length (cdr new))))
1045 (setq a (concat (substring a 0 p)
1046 (format fmt (+ (aref a p) 64))
1047 (substring a (1+ p)))
1048 p (+ p 2))))))
1049 (if quoted
1050 (concat "\"" a "\"")
bf77c646 1051 a))
3132f345 1052
136211a9
EZ
1053
1054(defun math-to-underscores (x)
1055 (if (string-match "\\`\\(.*\\)#\\(.*\\)\\'" x)
1056 (math-to-underscores
1057 (concat (math-match-substring x 1) "_" (math-match-substring x 2)))
bf77c646 1058 x))
136211a9
EZ
1059
1060(defun math-tex-expr-is-flat (a)
1061 (or (Math-integerp a)
1062 (memq (car a) '(float var))
1063 (and (memq (car a) '(+ - * neg))
1064 (progn
1065 (while (and (setq a (cdr a))
1066 (math-tex-expr-is-flat (car a))))
1067 (null a)))
1068 (and (memq (car a) '(^ calcFunc-subscr))
bf77c646 1069 (math-tex-expr-is-flat (nth 1 a)))))
136211a9
EZ
1070
1071(put 'calcFunc-log 'math-compose-big 'math-compose-log)
1072(defun math-compose-log (a prec)
1073 (and (= (length a) 3)
1074 (list 'horiz
1075 (list 'subscr "log"
1076 (let ((calc-language 'flat))
1077 (math-compose-expr (nth 2 a) 1000)))
1078 "("
1079 (math-compose-expr (nth 1 a) 1000)
bf77c646 1080 ")")))
136211a9
EZ
1081
1082(put 'calcFunc-log10 'math-compose-big 'math-compose-log10)
1083(defun math-compose-log10 (a prec)
1084 (and (= (length a) 2)
1085 (list 'horiz
1086 (list 'subscr "log" "10")
1087 "("
1088 (math-compose-expr (nth 1 a) 1000)
bf77c646 1089 ")")))
136211a9
EZ
1090
1091(put 'calcFunc-deriv 'math-compose-big 'math-compose-deriv)
1092(put 'calcFunc-tderiv 'math-compose-big 'math-compose-deriv)
1093(defun math-compose-deriv (a prec)
3132f345
CW
1094 (when (= (length a) 3)
1095 (math-compose-expr (list '/
1096 (list 'calcFunc-choriz
1097 (list 'vec
1098 '(calcFunc-string (vec ?d))
1099 (nth 1 a)))
1100 (list 'calcFunc-choriz
1101 (list 'vec
1102 '(calcFunc-string (vec ?d))
1103 (nth 2 a))))
1104 prec)))
136211a9
EZ
1105
1106(put 'calcFunc-sqrt 'math-compose-big 'math-compose-sqrt)
1107(defun math-compose-sqrt (a prec)
3132f345
CW
1108 (when (= (length a) 2)
1109 (let* ((c (math-compose-expr (nth 1 a) 0))
1110 (a (math-comp-ascent c))
1111 (d (math-comp-descent c))
1112 (h (+ a d))
1113 (w (math-comp-width c)))
1114 (list 'vleft
1115 a
1116 (concat (if (= h 1) " " " ")
1117 (make-string (+ w 2) ?\_))
1118 (list 'horiz
1119 (if (= h 1)
1120 "V"
1121 (append (list 'vleft (1- a))
1122 (make-list (1- h) " |")
1123 '("\\|")))
1124 " "
1125 c)))))
136211a9
EZ
1126
1127(put 'calcFunc-choose 'math-compose-big 'math-compose-choose)
1128(defun math-compose-choose (a prec)
1129 (let ((a1 (math-compose-expr (nth 1 a) 0))
1130 (a2 (math-compose-expr (nth 2 a) 0)))
1131 (list 'horiz
1132 "("
1133 (list 'vcent
1134 (math-comp-height a1)
1135 a1 " " a2)
bf77c646 1136 ")")))
136211a9
EZ
1137
1138(put 'calcFunc-integ 'math-compose-big 'math-compose-integ)
1139(defun math-compose-integ (a prec)
1140 (and (memq (length a) '(3 5))
1141 (eq (car-safe (nth 2 a)) 'var)
1142 (let* ((parens (and (>= prec 196) (/= prec 1000)))
1143 (var (math-compose-expr (nth 2 a) 0))
1144 (over (and (eq (car-safe (nth 2 a)) 'var)
1145 (or (and (eq (car-safe (nth 1 a)) '/)
1146 (math-numberp (nth 1 (nth 1 a))))
1147 (and (eq (car-safe (nth 1 a)) '^)
1148 (math-looks-negp (nth 2 (nth 1 a)))))))
1149 (expr (math-compose-expr (if over
1150 (math-mul (nth 1 a)
1151 (math-build-var-name
1152 (format
1153 "d%s"
1154 (nth 1 (nth 2 a)))))
1155 (nth 1 a)) 185))
1156 (calc-language 'flat)
1157 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
1158 (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0))))
1159 (list 'horiz
1160 (if parens "(" "")
1161 (append (list 'vcent (if high 3 2))
1162 (and high (list (list 'horiz " " high)))
1163 '(" /"
1164 " | "
1165 " | "
1166 " | "
1167 "/ ")
1168 (and low (list (list 'horiz low " "))))
1169 expr
1170 (if over
1171 ""
1172 (list 'horiz " d" var))
bf77c646 1173 (if parens ")" "")))))
136211a9
EZ
1174
1175(put 'calcFunc-sum 'math-compose-big 'math-compose-sum)
1176(defun math-compose-sum (a prec)
1177 (and (memq (length a) '(3 5 6))
1178 (let* ((expr (math-compose-expr (nth 1 a) 185))
1179 (calc-language 'flat)
1180 (var (math-compose-expr (nth 2 a) 0))
1181 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
1182 (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
1183 (list 'horiz
1184 (if (memq prec '(180 201)) "(" "")
1185 (append (list 'vcent (if high 3 2))
1186 (and high (list high))
1187 '("---- "
1188 "\\ "
1189 " > "
1190 "/ "
1191 "---- ")
1192 (if low
1193 (list (list 'horiz var " = " low))
1194 (list var)))
1195 (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
1196 " " "")
1197 expr
bf77c646 1198 (if (memq prec '(180 201)) ")" "")))))
136211a9
EZ
1199
1200(put 'calcFunc-prod 'math-compose-big 'math-compose-prod)
1201(defun math-compose-prod (a prec)
1202 (and (memq (length a) '(3 5 6))
1203 (let* ((expr (math-compose-expr (nth 1 a) 198))
1204 (calc-language 'flat)
1205 (var (math-compose-expr (nth 2 a) 0))
1206 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
1207 (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
1208 (list 'horiz
1209 (if (memq prec '(196 201)) "(" "")
1210 (append (list 'vcent (if high 3 2))
1211 (and high (list high))
1212 '("----- "
1213 " | | "
1214 " | | "
1215 " | | ")
1216 (if low
1217 (list (list 'horiz var " = " low))
1218 (list var)))
1219 (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
1220 " " "")
1221 expr
bf77c646 1222 (if (memq prec '(196 201)) ")" "")))))
136211a9 1223
fdcf8e2b
JB
1224;; The variables math-svo-c, math-svo-wid and math-svo-off are local
1225;; to math-stack-value-offset in calc.el, but are used by
1226;; math-stack-value-offset-fancy, which is called by math-stack-value-offset..
1227(defvar math-svo-c)
1228(defvar math-svo-wid)
1229(defvar math-svo-off)
136211a9
EZ
1230
1231(defun math-stack-value-offset-fancy ()
fdcf8e2b 1232 (let ((cwid (+ (math-comp-width math-svo-c))))
136211a9
EZ
1233 (cond ((eq calc-display-just 'right)
1234 (if calc-display-origin
fdcf8e2b 1235 (setq math-svo-wid (max calc-display-origin 5))
136211a9 1236 (if (integerp calc-line-breaking)
fdcf8e2b
JB
1237 (setq math-svo-wid calc-line-breaking)))
1238 (setq math-svo-off (- math-svo-wid cwid
136211a9
EZ
1239 (max (- (length calc-right-label)
1240 (if (and (integerp calc-line-breaking)
1241 calc-display-origin)
1242 (max (- calc-line-breaking
1243 calc-display-origin)
1244 0)
1245 0))
1246 0))))
1247 (t
1248 (if calc-display-origin
1249 (progn
fdcf8e2b 1250 (setq math-svo-off (- calc-display-origin (/ cwid 2)))
136211a9 1251 (if (integerp calc-line-breaking)
fdcf8e2b 1252 (setq math-svo-off (min math-svo-off (- calc-line-breaking cwid
136211a9 1253 (length calc-right-label)))))
fdcf8e2b
JB
1254 (if (>= math-svo-off 0)
1255 (setq math-svo-wid (max math-svo-wid (+ math-svo-off cwid)))))
136211a9 1256 (if (integerp calc-line-breaking)
fdcf8e2b
JB
1257 (setq math-svo-wid calc-line-breaking))
1258 (setq math-svo-off (/ (- math-svo-wid cwid) 2)))))
136211a9 1259 (and (integerp calc-line-breaking)
fdcf8e2b 1260 (or (< math-svo-off 0)
136211a9
EZ
1261 (and calc-display-origin
1262 (> calc-line-breaking calc-display-origin)))
fdcf8e2b 1263 (setq math-svo-wid calc-line-breaking))))
136211a9
EZ
1264
1265
1266;;; Convert a composition to string form, with embedded \n's if necessary.
1267
1268(defun math-composition-to-string (c &optional width)
1269 (or width (setq width (calc-window-width)))
1270 (if calc-display-raw
1271 (math-comp-to-string-raw c 0)
1272 (if (math-comp-is-flat c)
1273 (math-comp-to-string-flat c width)
1274 (math-vert-comp-to-string
bf77c646 1275 (math-comp-simplify c width)))))
136211a9 1276
3132f345
CW
1277(defvar math-comp-buf-string (make-vector 10 ""))
1278(defvar math-comp-buf-margin (make-vector 10 0))
1279(defvar math-comp-buf-level (make-vector 10 0))
136211a9
EZ
1280(defun math-comp-is-flat (c) ; check if c's height is 1.
1281 (cond ((not (consp c)) t)
1282 ((memq (car c) '(set break)) t)
1283 ((eq (car c) 'horiz)
1284 (while (and (setq c (cdr c))
1285 (math-comp-is-flat (car c))))
1286 (null c))
1287 ((memq (car c) '(vleft vcent vright))
1288 (and (= (length c) 3)
1289 (= (nth 1 c) 0)
1290 (math-comp-is-flat (nth 2 c))))
1291 ((eq (car c) 'tag)
1292 (math-comp-is-flat (nth 2 c)))
bf77c646 1293 (t nil)))
136211a9
EZ
1294
1295
1296;;; Convert a one-line composition to a string. Break into multiple
1297;;; lines if necessary, choosing break points according to the structure
1298;;; of the formula.
1299
fdcf8e2b
JB
1300;; The variables math-comp-full-width, math-comp-highlight, math-comp-word,
1301;; math-comp-level, math-comp-margin and math-comp-buf are local to
1302;; math-comp-to-string-flat, but are used by math-comp-to-string-flat-term,
1303;; which is called by math-comp-to-string-flat.
1304;; math-comp-highlight and math-comp-buf are also local to
1305;; math-comp-simplify-term and math-comp-simplify respectively, but are used
1306;; by math-comp-add-string.
1307(defvar math-comp-full-width)
1308(defvar math-comp-highlight)
1309(defvar math-comp-word)
1310(defvar math-comp-level)
1311(defvar math-comp-margin)
1312(defvar math-comp-buf)
1313;; The variable math-comp-pos is local to math-comp-to-string-flat, but
1314;; is used by math-comp-to-string-flat-term and math-comp-sel-first-term,
1315;; which are called by math-comp-to-string-flat.
1316(defvar math-comp-pos)
1317
1318(defun math-comp-to-string-flat (c math-comp-full-width)
136211a9 1319 (if math-comp-sel-hpos
fdcf8e2b 1320 (let ((math-comp-pos 0))
136211a9 1321 (math-comp-sel-flat-term c))
fdcf8e2b
JB
1322 (let ((math-comp-buf "")
1323 (math-comp-word "")
1324 (math-comp-pos 0)
1325 (math-comp-margin 0)
1326 (math-comp-highlight (and math-comp-selected calc-show-selections))
1327 (math-comp-level -1))
136211a9
EZ
1328 (math-comp-to-string-flat-term '(set -1 0))
1329 (math-comp-to-string-flat-term c)
1330 (math-comp-to-string-flat-term '(break -1))
1331 (let ((str (aref math-comp-buf-string 0))
1332 (prefix ""))
1333 (and (> (length str) 0) (= (aref str 0) ? )
fdcf8e2b
JB
1334 (> (length math-comp-buf) 0)
1335 (let ((k (length math-comp-buf)))
1336 (while (not (= (aref math-comp-buf (setq k (1- k))) ?\n)))
1337 (aset math-comp-buf k ? )
1338 (if (and (< (1+ k) (length math-comp-buf))
1339 (= (aref math-comp-buf (1+ k)) ? ))
136211a9 1340 (progn
fdcf8e2b 1341 (aset math-comp-buf (1+ k) ?\n)
136211a9
EZ
1342 (setq prefix " "))
1343 (setq prefix "\n"))))
fdcf8e2b 1344 (concat math-comp-buf prefix str)))))
136211a9
EZ
1345
1346(defun math-comp-to-string-flat-term (c)
1347 (cond ((not (consp c))
fdcf8e2b 1348 (if math-comp-highlight
136211a9 1349 (setq c (math-comp-highlight-string c)))
fdcf8e2b
JB
1350 (setq math-comp-word (if (= (length math-comp-word) 0) c
1351 (concat math-comp-word c))
1352 math-comp-pos (+ math-comp-pos (length c))))
136211a9
EZ
1353
1354 ((eq (car c) 'horiz)
1355 (while (setq c (cdr c))
1356 (math-comp-to-string-flat-term (car c))))
1357
1358 ((eq (car c) 'set)
1359 (if (nth 1 c)
1360 (progn
fdcf8e2b
JB
1361 (setq math-comp-level (1+ math-comp-level))
1362 (if (>= math-comp-level (length math-comp-buf-string))
136211a9
EZ
1363 (setq math-comp-buf-string (vconcat math-comp-buf-string
1364 math-comp-buf-string)
1365 math-comp-buf-margin (vconcat math-comp-buf-margin
1366 math-comp-buf-margin)
1367 math-comp-buf-level (vconcat math-comp-buf-level
1368 math-comp-buf-level)))
fdcf8e2b
JB
1369 (aset math-comp-buf-string math-comp-level "")
1370 (aset math-comp-buf-margin math-comp-level (+ math-comp-pos
136211a9 1371 (or (nth 2 c) 0)))
fdcf8e2b 1372 (aset math-comp-buf-level math-comp-level (nth 1 c)))))
136211a9
EZ
1373
1374 ((eq (car c) 'break)
1375 (if (not calc-line-breaking)
fdcf8e2b
JB
1376 (setq math-comp-buf (concat math-comp-buf math-comp-word)
1377 math-comp-word "")
136211a9 1378 (let ((i 0) str)
fdcf8e2b 1379 (if (and (> math-comp-pos math-comp-full-width)
136211a9
EZ
1380 (progn
1381 (while (progn
1382 (setq str (aref math-comp-buf-string i))
fdcf8e2b 1383 (and (= (length str) 0) (< i math-comp-level)))
136211a9 1384 (setq i (1+ i)))
fdcf8e2b 1385 (or (> (length str) 0) (> (length math-comp-buf) 0))))
136211a9
EZ
1386 (let ((prefix "") mrg wid)
1387 (setq mrg (aref math-comp-buf-margin i))
1388 (if (> mrg 12) ; indenting too far, go back to far left
1389 (let ((j i) (new (if calc-line-numbering 5 1)))
fdcf8e2b 1390 '(while (<= j math-comp-level)
136211a9
EZ
1391 (aset math-comp-buf-margin j
1392 (+ (aref math-comp-buf-margin j) (- new mrg)))
1393 (setq j (1+ j)))
1394 (setq mrg new)))
fdcf8e2b 1395 (setq wid (+ (length str) math-comp-margin))
136211a9 1396 (and (> (length str) 0) (= (aref str 0) ? )
fdcf8e2b
JB
1397 (> (length math-comp-buf) 0)
1398 (let ((k (length math-comp-buf)))
1399 (while (not (= (aref math-comp-buf (setq k (1- k))) ?\n)))
1400 (aset math-comp-buf k ? )
1401 (if (and (< (1+ k) (length math-comp-buf))
1402 (= (aref math-comp-buf (1+ k)) ? ))
136211a9 1403 (progn
fdcf8e2b 1404 (aset math-comp-buf (1+ k) ?\n)
136211a9
EZ
1405 (setq prefix " "))
1406 (setq prefix "\n"))))
fdcf8e2b 1407 (setq math-comp-buf (concat math-comp-buf prefix str "\n"
136211a9 1408 (make-string mrg ? ))
fdcf8e2b
JB
1409 math-comp-pos (+ math-comp-pos (- mrg wid))
1410 math-comp-margin mrg)
136211a9 1411 (aset math-comp-buf-string i "")
fdcf8e2b 1412 (while (<= (setq i (1+ i)) math-comp-level)
136211a9
EZ
1413 (if (> (aref math-comp-buf-margin i) wid)
1414 (aset math-comp-buf-margin i
1415 (+ (aref math-comp-buf-margin i)
1416 (- mrg wid))))))))
fdcf8e2b
JB
1417 (if (and (= (nth 1 c) (aref math-comp-buf-level math-comp-level))
1418 (< math-comp-pos (+ (aref math-comp-buf-margin math-comp-level) 2)))
136211a9 1419 () ; avoid stupid breaks, e.g., "1 +\n really_long_expr"
fdcf8e2b 1420 (let ((str (aref math-comp-buf-string math-comp-level)))
136211a9 1421 (setq str (if (= (length str) 0)
fdcf8e2b
JB
1422 math-comp-word
1423 (concat str math-comp-word))
1424 math-comp-word "")
1425 (while (< (nth 1 c) (aref math-comp-buf-level math-comp-level))
1426 (setq math-comp-level (1- math-comp-level))
1427 (or (= (length (aref math-comp-buf-string math-comp-level)) 0)
1428 (setq str (concat (aref math-comp-buf-string math-comp-level)
136211a9 1429 str))))
fdcf8e2b 1430 (aset math-comp-buf-string math-comp-level str)))))
136211a9
EZ
1431
1432 ((eq (car c) 'tag)
1433 (cond ((eq (nth 1 c) math-comp-selected)
fdcf8e2b 1434 (let ((math-comp-highlight (not calc-show-selections)))
136211a9
EZ
1435 (math-comp-to-string-flat-term (nth 2 c))))
1436 ((eq (nth 1 c) t)
fdcf8e2b 1437 (let ((math-comp-highlight nil))
136211a9
EZ
1438 (math-comp-to-string-flat-term (nth 2 c))))
1439 (t (math-comp-to-string-flat-term (nth 2 c)))))
1440
bf77c646 1441 (t (math-comp-to-string-flat-term (nth 2 c)))))
136211a9
EZ
1442
1443(defun math-comp-highlight-string (s)
1444 (setq s (copy-sequence s))
1445 (let ((i (length s)))
1446 (while (>= (setq i (1- i)) 0)
1447 (or (memq (aref s i) '(32 ?\n))
1448 (aset s i (if calc-show-selections ?\. ?\#)))))
bf77c646 1449 s)
136211a9 1450
fdcf8e2b
JB
1451
1452;; The variable math-comp-sel-tag is local to calc-find-selected-part
1453;; in calc-sel.el, but is used by math-comp-sel-flat-term and
1454;; math-comp-add-string-sel, which are called (indirectly) by
1455;; calc-find-selected-part.
1456(defvar math-comp-sel-tag)
1457
136211a9
EZ
1458(defun math-comp-sel-flat-term (c)
1459 (cond ((not (consp c))
fdcf8e2b 1460 (setq math-comp-pos (+ math-comp-pos (length c))))
136211a9
EZ
1461 ((memq (car c) '(set break)))
1462 ((eq (car c) 'horiz)
1463 (while (and (setq c (cdr c)) (< math-comp-sel-cpos 1000000))
1464 (math-comp-sel-flat-term (car c))))
1465 ((eq (car c) 'tag)
fdcf8e2b 1466 (if (<= math-comp-pos math-comp-sel-cpos)
136211a9
EZ
1467 (progn
1468 (math-comp-sel-flat-term (nth 2 c))
fdcf8e2b 1469 (if (> math-comp-pos math-comp-sel-cpos)
136211a9
EZ
1470 (setq math-comp-sel-tag c
1471 math-comp-sel-cpos 1000000)))
1472 (math-comp-sel-flat-term (nth 2 c))))
bf77c646 1473 (t (math-comp-sel-flat-term (nth 2 c)))))
136211a9
EZ
1474
1475
1476;;; Simplify a composition to a canonical form consisting of
1477;;; (vleft n "string" "string" "string" ...)
1478;;; where 0 <= n < number-of-strings.
1479
fdcf8e2b
JB
1480;; The variables math-comp-base, math-comp-hgt, math-comp-tag,
1481;; math-comp-hpos and math-comp-vpos are local to math-comp-simplify,
1482;; but are used by math-comp-add-string (math-comp-base, math-comp-hgt),
1483;; math-comp-add-string-sel (math-comp-tag) and math-comp-simplify-term
1484;; (math-comp-tag, math-comp-vpos, math-comp-hpos), which are called by
1485;; math-comp-simplify.
1486(defvar math-comp-base)
1487(defvar math-comp-hgt)
1488(defvar math-comp-tag)
1489(defvar math-comp-hpos)
1490(defvar math-comp-vpos)
1491
136211a9 1492(defun math-comp-simplify (c full-width)
fdcf8e2b
JB
1493 (let ((math-comp-buf (list ""))
1494 (math-comp-base 0)
1495 (math-comp-hgt 1)
1496 (math-comp-hpos 0)
1497 (math-comp-vpos 0)
1498 (math-comp-highlight (and math-comp-selected calc-show-selections))
1499 (math-comp-tag nil))
136211a9 1500 (math-comp-simplify-term c)
fdcf8e2b 1501 (cons 'vleft (cons math-comp-base math-comp-buf))))
136211a9
EZ
1502
1503(defun math-comp-add-string (s h v)
1504 (and (> (length s) 0)
fdcf8e2b 1505 (let ((vv (+ v math-comp-base)))
136211a9
EZ
1506 (if math-comp-sel-hpos
1507 (math-comp-add-string-sel h vv (length s) 1)
1508 (if (< vv 0)
fdcf8e2b
JB
1509 (setq math-comp-buf (nconc (make-list (- vv) "") math-comp-buf)
1510 math-comp-base (- v)
1511 math-comp-hgt (- math-comp-hgt vv)
136211a9 1512 vv 0)
fdcf8e2b
JB
1513 (if (>= vv math-comp-hgt)
1514 (setq math-comp-buf (nconc math-comp-buf
1515 (make-list (1+ (- vv math-comp-hgt)) ""))
1516 math-comp-hgt (1+ vv))))
1517 (let ((str (nthcdr vv math-comp-buf)))
136211a9
EZ
1518 (setcar str (concat (car str)
1519 (make-string (- h (length (car str))) 32)
fdcf8e2b 1520 (if math-comp-highlight
136211a9 1521 (math-comp-highlight-string s)
bf77c646 1522 s))))))))
136211a9
EZ
1523
1524(defun math-comp-add-string-sel (x y w h)
1525 (if (and (<= y math-comp-sel-vpos)
1526 (> (+ y h) math-comp-sel-vpos)
1527 (<= x math-comp-sel-hpos)
1528 (> (+ x w) math-comp-sel-hpos))
fdcf8e2b 1529 (setq math-comp-sel-tag math-comp-tag
bf77c646 1530 math-comp-sel-vpos 10000)))
136211a9
EZ
1531
1532(defun math-comp-simplify-term (c)
1533 (cond ((stringp c)
fdcf8e2b
JB
1534 (math-comp-add-string c math-comp-hpos math-comp-vpos)
1535 (setq math-comp-hpos (+ math-comp-hpos (length c))))
136211a9
EZ
1536 ((memq (car c) '(set break))
1537 nil)
1538 ((eq (car c) 'horiz)
1539 (while (setq c (cdr c))
1540 (math-comp-simplify-term (car c))))
1541 ((memq (car c) '(vleft vcent vright))
fdcf8e2b 1542 (let* ((math-comp-vpos (+ (- math-comp-vpos (nth 1 c))
136211a9
EZ
1543 (1- (math-comp-ascent (nth 2 c)))))
1544 (widths (mapcar 'math-comp-width (cdr (cdr c))))
1545 (maxwid (apply 'max widths))
1546 (bias (cond ((eq (car c) 'vleft) 0)
1547 ((eq (car c) 'vcent) 1)
1548 (t 2))))
1549 (setq c (cdr c))
1550 (while (setq c (cdr c))
1551 (if (eq (car-safe (car c)) 'rule)
1552 (math-comp-add-string (make-string maxwid (nth 1 (car c)))
fdcf8e2b
JB
1553 math-comp-hpos math-comp-vpos)
1554 (let ((math-comp-hpos (+ math-comp-hpos (/ (* bias (- maxwid
136211a9
EZ
1555 (car widths)))
1556 2))))
1557 (math-comp-simplify-term (car c))))
1558 (and (cdr c)
fdcf8e2b 1559 (setq math-comp-vpos (+ math-comp-vpos
136211a9
EZ
1560 (+ (math-comp-descent (car c))
1561 (math-comp-ascent (nth 1 c))))
1562 widths (cdr widths))))
fdcf8e2b 1563 (setq math-comp-hpos (+ math-comp-hpos maxwid))))
136211a9
EZ
1564 ((eq (car c) 'supscr)
1565 (let* ((asc (or 1 (math-comp-ascent (nth 1 c))))
1566 (desc (math-comp-descent (nth 2 c)))
1567 (oldh (prog1
fdcf8e2b 1568 math-comp-hpos
136211a9 1569 (math-comp-simplify-term (nth 1 c))))
fdcf8e2b 1570 (math-comp-vpos (- math-comp-vpos (+ asc desc))))
136211a9
EZ
1571 (math-comp-simplify-term (nth 2 c))
1572 (if math-comp-sel-hpos
1573 (math-comp-add-string-sel oldh
fdcf8e2b 1574 (- math-comp-vpos
136211a9
EZ
1575 -1
1576 (math-comp-ascent (nth 2 c)))
fdcf8e2b 1577 (- math-comp-hpos oldh)
136211a9
EZ
1578 (math-comp-height c)))))
1579 ((eq (car c) 'subscr)
1580 (let* ((asc (math-comp-ascent (nth 2 c)))
1581 (desc (math-comp-descent (nth 1 c)))
fdcf8e2b 1582 (oldv math-comp-vpos)
136211a9 1583 (oldh (prog1
fdcf8e2b 1584 math-comp-hpos
136211a9 1585 (math-comp-simplify-term (nth 1 c))))
fdcf8e2b 1586 (math-comp-vpos (+ math-comp-vpos (+ asc desc))))
136211a9
EZ
1587 (math-comp-simplify-term (nth 2 c))
1588 (if math-comp-sel-hpos
1589 (math-comp-add-string-sel oldh oldv
fdcf8e2b 1590 (- math-comp-hpos oldh)
136211a9
EZ
1591 (math-comp-height c)))))
1592 ((eq (car c) 'tag)
1593 (cond ((eq (nth 1 c) math-comp-selected)
fdcf8e2b 1594 (let ((math-comp-highlight (not calc-show-selections)))
136211a9
EZ
1595 (math-comp-simplify-term (nth 2 c))))
1596 ((eq (nth 1 c) t)
fdcf8e2b 1597 (let ((math-comp-highlight nil))
136211a9 1598 (math-comp-simplify-term (nth 2 c))))
fdcf8e2b 1599 (t (let ((math-comp-tag c))
bf77c646 1600 (math-comp-simplify-term (nth 2 c))))))))
136211a9
EZ
1601
1602
1603;;; Measuring a composition.
1604
1605(defun math-comp-first-char (c)
1606 (cond ((stringp c)
1607 (and (> (length c) 0)
1608 (elt c 0)))
1609 ((memq (car c) '(horiz subscr supscr))
1610 (while (and (setq c (cdr c))
1611 (math-comp-is-null (car c))))
1612 (and c (math-comp-first-char (car c))))
1613 ((eq (car c) 'tag)
bf77c646 1614 (math-comp-first-char (nth 2 c)))))
136211a9
EZ
1615
1616(defun math-comp-first-string (c)
1617 (cond ((stringp c)
1618 (and (> (length c) 0)
1619 c))
1620 ((eq (car c) 'horiz)
1621 (while (and (setq c (cdr c))
1622 (math-comp-is-null (car c))))
1623 (and c (math-comp-first-string (car c))))
1624 ((eq (car c) 'tag)
bf77c646 1625 (math-comp-first-string (nth 2 c)))))
136211a9
EZ
1626
1627(defun math-comp-last-char (c)
1628 (cond ((stringp c)
1629 (and (> (length c) 0)
1630 (elt c (1- (length c)))))
1631 ((eq (car c) 'horiz)
1632 (let ((c (reverse (cdr c))))
1633 (while (and c (math-comp-is-null (car c)))
1634 (setq c (cdr c)))
1635 (and c (math-comp-last-char (car c)))))
1636 ((eq (car c) 'tag)
bf77c646 1637 (math-comp-last-char (nth 2 c)))))
136211a9
EZ
1638
1639(defun math-comp-is-null (c)
1640 (cond ((stringp c) (= (length c) 0))
1641 ((memq (car c) '(horiz subscr supscr))
1642 (while (and (setq c (cdr c))
1643 (math-comp-is-null (car c))))
1644 (null c))
1645 ((eq (car c) 'tag)
1646 (math-comp-is-null (nth 2 c)))
bf77c646 1647 ((memq (car c) '(set break)) t)))
136211a9
EZ
1648
1649(defun math-comp-width (c)
1650 (cond ((not (consp c)) (length c))
1651 ((memq (car c) '(horiz subscr supscr))
1652 (let ((accum 0))
1653 (while (setq c (cdr c))
1654 (setq accum (+ accum (math-comp-width (car c)))))
1655 accum))
1656 ((memq (car c) '(vcent vleft vright))
1657 (setq c (cdr c))
1658 (let ((accum 0))
1659 (while (setq c (cdr c))
1660 (setq accum (max accum (math-comp-width (car c)))))
1661 accum))
1662 ((eq (car c) 'tag)
1663 (math-comp-width (nth 2 c)))
bf77c646 1664 (t 0)))
136211a9
EZ
1665
1666(defun math-comp-height (c)
1667 (if (stringp c)
1668 1
bf77c646 1669 (+ (math-comp-ascent c) (math-comp-descent c))))
136211a9
EZ
1670
1671(defun math-comp-ascent (c)
1672 (cond ((not (consp c)) 1)
1673 ((eq (car c) 'horiz)
1674 (let ((accum 0))
1675 (while (setq c (cdr c))
1676 (setq accum (max accum (math-comp-ascent (car c)))))
1677 accum))
1678 ((memq (car c) '(vcent vleft vright))
1679 (if (> (nth 1 c) 0) (1+ (nth 1 c)) 1))
1680 ((eq (car c) 'supscr)
1681 (max (math-comp-ascent (nth 1 c)) (1+ (math-comp-height (nth 2 c)))))
1682 ((eq (car c) 'subscr)
1683 (math-comp-ascent (nth 1 c)))
1684 ((eq (car c) 'tag)
1685 (math-comp-ascent (nth 2 c)))
bf77c646 1686 (t 1)))
136211a9
EZ
1687
1688(defun math-comp-descent (c)
1689 (cond ((not (consp c)) 0)
1690 ((eq (car c) 'horiz)
1691 (let ((accum 0))
1692 (while (setq c (cdr c))
1693 (setq accum (max accum (math-comp-descent (car c)))))
1694 accum))
1695 ((memq (car c) '(vcent vleft vright))
1696 (let ((accum (- (nth 1 c))))
1697 (setq c (cdr c))
1698 (while (setq c (cdr c))
1699 (setq accum (+ accum (math-comp-height (car c)))))
1700 (max (1- accum) 0)))
1701 ((eq (car c) 'supscr)
1702 (math-comp-descent (nth 1 c)))
1703 ((eq (car c) 'subscr)
1704 (+ (math-comp-descent (nth 1 c)) (math-comp-height (nth 2 c))))
1705 ((eq (car c) 'tag)
1706 (math-comp-descent (nth 2 c)))
bf77c646 1707 (t 0)))
136211a9
EZ
1708
1709(defun calcFunc-cwidth (a &optional prec)
1710 (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
bf77c646 1711 (math-comp-width (math-compose-expr a (or prec 0))))
136211a9
EZ
1712
1713(defun calcFunc-cheight (a &optional prec)
1714 (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
1715 (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
1716 (memq (length a) '(2 3))
1717 (eq (nth 1 a) 0))
1718 0
bf77c646 1719 (math-comp-height (math-compose-expr a (or prec 0)))))
136211a9
EZ
1720
1721(defun calcFunc-cascent (a &optional prec)
1722 (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
1723 (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
1724 (memq (length a) '(2 3))
1725 (eq (nth 1 a) 0))
1726 0
bf77c646 1727 (math-comp-ascent (math-compose-expr a (or prec 0)))))
136211a9
EZ
1728
1729(defun calcFunc-cdescent (a &optional prec)
1730 (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
bf77c646 1731 (math-comp-descent (math-compose-expr a (or prec 0))))
136211a9
EZ
1732
1733
1734;;; Convert a simplified composition into string form.
1735
1736(defun math-vert-comp-to-string (c)
1737 (if (stringp c)
1738 c
bf77c646 1739 (math-vert-comp-to-string-step (cdr (cdr c)))))
136211a9
EZ
1740
1741(defun math-vert-comp-to-string-step (c)
1742 (if (cdr c)
1743 (concat (car c) "\n" (math-vert-comp-to-string-step (cdr c)))
bf77c646 1744 (car c)))
136211a9
EZ
1745
1746
1747;;; Convert a composition to a string in "raw" form (for debugging).
1748
1749(defun math-comp-to-string-raw (c indent)
1750 (cond ((or (not (consp c)) (eq (car c) 'set))
1751 (prin1-to-string c))
1752 ((null (cdr c))
1753 (concat "(" (symbol-name (car c)) ")"))
1754 (t
1755 (let ((next-indent (+ indent 2 (length (symbol-name (car c))))))
1756 (concat "("
1757 (symbol-name (car c))
1758 " "
1759 (math-comp-to-string-raw (nth 1 c) next-indent)
1760 (math-comp-to-string-raw-step (cdr (cdr c))
1761 next-indent)
bf77c646 1762 ")")))))
136211a9
EZ
1763
1764(defun math-comp-to-string-raw-step (cl indent)
1765 (if cl
1766 (concat "\n"
1767 (make-string indent 32)
1768 (math-comp-to-string-raw (car cl) indent)
1769 (math-comp-to-string-raw-step (cdr cl) indent))
bf77c646 1770 ""))
136211a9 1771
cfd31ee4
JB
1772(provide 'calccomp)
1773
ab5796a9 1774;;; arch-tag: 7c45d10a-a286-4dab-af49-7ae8989fbf78
bf77c646 1775;;; calccomp.el ends here