Mercurial > emacs
diff lisp/calc/calccomp.el @ 40785:2fb9d407ae73
Initial import of Calc 2.02f.
author | Eli Zaretskii <eliz@gnu.org> |
---|---|
date | Tue, 06 Nov 2001 18:59:06 +0000 |
parents | |
children | 73f364fd8aaa |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/calc/calccomp.el Tue Nov 06 18:59:06 2001 +0000 @@ -0,0 +1,1755 @@ +;; Calculator for GNU Emacs, part II [calc-comp.el] +;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. +;; Written by Dave Gillespie, daveg@synaptics.com. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY. No author or distributor +;; accepts responsibility to anyone for the consequences of using it +;; or for whether it serves any particular purpose or works at all, +;; unless he says so in writing. Refer to the GNU Emacs General Public +;; License for full details. + +;; Everyone is granted permission to copy, modify and redistribute +;; GNU Emacs, but only under the conditions described in the +;; GNU Emacs General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. + + + +;; This file is autoloaded from calc-ext.el. +(require 'calc-ext) + +(require 'calc-macs) + +(defun calc-Need-calc-comp () nil) + + +;;; A "composition" has one of the following forms: +;;; +;;; "string" A literal string +;;; +;;; (horiz C1 C2 ...) Horizontally abutted sub-compositions +;;; +;;; (set LEVEL OFF) Set left margin + offset for line-break level +;;; (break LEVEL) A potential line-break point +;;; +;;; (vleft N C1 C2 ...) Vertically stacked, left-justified sub-comps +;;; (vcent N C1 C2 ...) Vertically stacked, centered sub-comps +;;; (vright N C1 C2 ...) Vertically stacked, right-justified sub-comps +;;; N specifies baseline of the stack, 0=top line. +;;; +;;; (supscr C1 C2) Composition C1 with superscript C2 +;;; (subscr C1 C2) Composition C1 with subscript C2 +;;; (rule X) Horizontal line of X, full width of enclosing comp +;;; +;;; (tag X C) Composition C corresponds to sub-expression X + +(defun math-compose-expr (a prec) + (let ((math-compose-level (1+ math-compose-level))) + (cond + ((or (and (eq a math-comp-selected) a) + (and math-comp-tagged + (not (eq math-comp-tagged a)))) + (let ((math-comp-selected nil)) + (and math-comp-tagged (setq math-comp-tagged a)) + (list 'tag a (math-compose-expr a prec)))) + ((and (not (consp a)) (not (integerp a))) + (concat "'" (prin1-to-string a))) + ((math-scalarp a) + (if (or (eq (car-safe a) 'frac) + (and (nth 1 calc-frac-format) (Math-integerp a))) + (if (memq calc-language '(tex eqn math maple c fortran pascal)) + (let ((aa (math-adjust-fraction a)) + (calc-frac-format nil)) + (math-compose-expr (list '/ + (if (memq calc-language '(c fortran)) + (math-float (nth 1 aa)) + (nth 1 aa)) + (nth 2 aa)) prec)) + (if (and (eq calc-language 'big) + (= (length (car calc-frac-format)) 1)) + (let* ((aa (math-adjust-fraction a)) + (calc-frac-format nil) + (math-radix-explicit-format nil) + (c (list 'horiz + (if (math-negp (nth 1 aa)) + "- " "") + (list 'vcent 1 + (math-format-number + (math-abs (nth 1 aa))) + '(rule ?-) + (math-format-number (nth 2 aa)))))) + (if (= calc-number-radix 10) + c + (list 'horiz "(" c + (list 'subscr ")" + (int-to-string calc-number-radix))))) + (math-format-number a))) + (if (not (eq calc-language 'big)) + (math-format-number a prec) + (if (memq (car-safe a) '(cplx polar)) + (if (math-zerop (nth 2 a)) + (math-compose-expr (nth 1 a) prec) + (list 'horiz "(" + (math-compose-expr (nth 1 a) 0) + (if (eq (car a) 'cplx) ", " "; ") + (math-compose-expr (nth 2 a) 0) ")")) + (if (or (= calc-number-radix 10) + (not (Math-realp a)) + (and calc-group-digits + (not (assoc calc-group-char '((",") (" ")))))) + (math-format-number a prec) + (let ((s (math-format-number a prec)) + (c nil)) + (while (string-match (if (> calc-number-radix 14) + "\\([0-9]+\\)#\\([0-9a-zA-Z., ]+\\)" + "\\([0-9]+\\)#\\([0-9a-dA-D., ]+\\)") + s) + (setq c (nconc c (list (substring s 0 (match-beginning 0)) + (list 'subscr + (math-match-substring s 2) + (math-match-substring s 1)))) + s (substring s (match-end 0)))) + (if (string-match + "\\*\\([0-9.]+\\)\\^\\(-?[0-9]+\\)\\()?\\)\\'" s) + (setq s (list 'horiz + (substring s 0 (match-beginning 0)) " " + (list 'supscr + (math-match-substring s 1) + (math-match-substring s 2)) + (math-match-substring s 3)))) + (if c (cons 'horiz (nconc c (list s))) s))))))) + ((and (get (car a) 'math-compose-forms) + (not (eq calc-language 'unform)) + (let ((comps (get (car a) 'math-compose-forms)) + temp temp2) + (or (and (setq temp (assq calc-language comps)) + (or (and (setq temp2 (assq (1- (length a)) (cdr temp))) + (setq temp (apply (cdr temp2) (cdr a))) + (math-compose-expr temp prec)) + (and (setq temp2 (assq nil (cdr temp))) + (funcall (cdr temp2) a)))) + (and (setq temp (assq nil comps)) + (or (and (setq temp2 (assq (1- (length a)) (cdr temp))) + (setq temp (apply (cdr temp2) (cdr a))) + (math-compose-expr temp prec)) + (and (setq temp2 (assq nil (cdr temp))) + (funcall (cdr temp2) a)))))))) + ((eq (car a) 'vec) + (let* ((left-bracket (if calc-vector-brackets + (substring calc-vector-brackets 0 1) "")) + (right-bracket (if calc-vector-brackets + (substring calc-vector-brackets 1 2) "")) + (inner-brackets (memq 'R calc-matrix-brackets)) + (outer-brackets (memq 'O calc-matrix-brackets)) + (row-commas (memq 'C calc-matrix-brackets)) + (comma-spc (or calc-vector-commas " ")) + (comma (or calc-vector-commas "")) + (vector-prec (if (or (and calc-vector-commas + (math-vector-no-parens a)) + (memq 'P calc-matrix-brackets)) 0 1000)) + (just (cond ((eq calc-matrix-just 'right) 'vright) + ((eq calc-matrix-just 'center) 'vcent) + (t 'vleft))) + (break calc-break-vectors)) + (if (and (memq calc-language '(nil big)) + (not calc-break-vectors) + (math-matrixp a) (not (math-matrixp (nth 1 a))) + (or calc-full-vectors + (and (< (length a) 7) (< (length (nth 1 a)) 7)) + (progn (setq break t) nil))) + (if (progn + (setq vector-prec (if (or (and calc-vector-commas + (math-vector-no-parens + (nth 1 a))) + (memq 'P calc-matrix-brackets)) + 0 1000)) + (= (length a) 2)) + (list 'horiz + (concat left-bracket left-bracket " ") + (math-compose-vector (cdr (nth 1 a)) (concat comma " ") + vector-prec) + (concat " " right-bracket right-bracket)) + (let* ((rows (1- (length a))) + (cols (1- (length (nth 1 a)))) + (base (/ (1- rows) 2)) + (calc-language 'flat)) + (append '(horiz) + (list (append '(vleft) + (list base) + (list (concat (and outer-brackets + (concat left-bracket + " ")) + (and inner-brackets + (concat left-bracket + " ")))) + (make-list (1- rows) + (concat (and outer-brackets + " ") + (and inner-brackets + (concat + left-bracket + " ")))))) + (math-compose-matrix (cdr a) 1 cols base) + (list (append '(vleft) + (list base) + (make-list (1- rows) + (if inner-brackets + (concat " " + right-bracket + (and row-commas + comma)) + (if (and outer-brackets + row-commas) + ";" ""))) + (list (concat + (and inner-brackets + (concat " " + right-bracket)) + (and outer-brackets + (concat + " " + right-bracket))))))))) + (if (and calc-display-strings + (cdr a) + (math-vector-is-string a)) + (math-vector-to-string a t) + (if (and break (cdr a) + (not (eq calc-language 'flat))) + (let* ((full (or calc-full-vectors (< (length a) 7))) + (rows (if full (1- (length a)) 5)) + (base (/ (1- rows) 2)) + (just 'vleft) + (calc-break-vectors nil)) + (list 'horiz + (cons 'vleft (cons base + (math-compose-rows + (cdr a) + (if full rows 3) t))))) + (if (or calc-full-vectors (< (length a) 7)) + (if (and (eq calc-language 'tex) + (math-matrixp a)) + (append '(horiz "\\matrix{ ") + (math-compose-tex-matrix (cdr a)) + '(" }")) + (if (and (eq calc-language 'eqn) + (math-matrixp a)) + (append '(horiz "matrix { ") + (math-compose-eqn-matrix + (cdr (math-transpose a))) + '("}")) + (if (and (eq calc-language 'maple) + (math-matrixp a)) + (list 'horiz + "matrix(" + left-bracket + (math-compose-vector (cdr a) (concat comma " ") + vector-prec) + right-bracket + ")") + (list 'horiz + left-bracket + (math-compose-vector (cdr a) (concat comma " ") + vector-prec) + right-bracket)))) + (list 'horiz + left-bracket + (math-compose-vector (list (nth 1 a) (nth 2 a) (nth 3 a)) + (concat comma " ") vector-prec) + comma (if (eq calc-language 'tex) " \\ldots" " ...") + comma " " + (list 'break math-compose-level) + (math-compose-expr (nth (1- (length a)) a) + (if (equal comma "") 1000 0)) + right-bracket))))))) + ((eq (car a) 'incomplete) + (if (cdr (cdr a)) + (cond ((eq (nth 1 a) 'vec) + (list 'horiz "[" + (math-compose-vector (cdr (cdr a)) ", " 0) + " ...")) + ((eq (nth 1 a) 'cplx) + (list 'horiz "(" + (math-compose-vector (cdr (cdr a)) ", " 0) + ", ...")) + ((eq (nth 1 a) 'polar) + (list 'horiz "(" + (math-compose-vector (cdr (cdr a)) "; " 0) + "; ...")) + ((eq (nth 1 a) 'intv) + (list 'horiz + (if (memq (nth 2 a) '(0 1)) "(" "[") + (math-compose-vector (cdr (cdr (cdr a))) " .. " 0) + " .. ...")) + (t (format "%s" a))) + (cond ((eq (nth 1 a) 'vec) "[ ...") + ((eq (nth 1 a) 'intv) + (if (memq (nth 2 a) '(0 1)) "( ..." "[ ...")) + (t "( ...")))) + ((eq (car a) 'var) + (let ((v (rassq (nth 2 a) math-expr-variable-mapping))) + (if v + (symbol-name (car v)) + (if (and (eq calc-language 'tex) + calc-language-option + (not (= calc-language-option 0)) + (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'" + (symbol-name (nth 1 a)))) + (format "\\hbox{%s}" (symbol-name (nth 1 a))) + (if (and math-compose-hash-args + (let ((p calc-arg-values)) + (setq v 1) + (while (and p (not (equal (car p) a))) + (setq p (and (eq math-compose-hash-args t) (cdr p)) + v (1+ v))) + p)) + (if (eq math-compose-hash-args 1) + "#" + (format "#%d" v)) + (if (memq calc-language '(c fortran pascal maple)) + (math-to-underscores (symbol-name (nth 1 a))) + (if (and (eq calc-language 'eqn) + (string-match ".'\\'" (symbol-name (nth 2 a)))) + (math-compose-expr + (list 'calcFunc-Prime + (list + 'var + (intern (substring (symbol-name (nth 1 a)) 0 -1)) + (intern (substring (symbol-name (nth 2 a)) 0 -1)))) + prec) + (symbol-name (nth 1 a))))))))) + ((eq (car a) 'intv) + (list 'horiz + (if (eq calc-language 'maple) "" + (if (memq (nth 1 a) '(0 1)) "(" "[")) + (math-compose-expr (nth 2 a) 0) + (if (eq calc-language 'tex) " \\ldots " + (if (eq calc-language 'eqn) " ... " " .. ")) + (math-compose-expr (nth 3 a) 0) + (if (eq calc-language 'maple) "" + (if (memq (nth 1 a) '(0 2)) ")" "]")))) + ((eq (car a) 'date) + (if (eq (car calc-date-format) 'X) + (math-format-date a) + (concat "<" (math-format-date a) ">"))) + ((and (eq (car a) 'calcFunc-subscr) (cdr (cdr a)) + (memq calc-language '(c pascal fortran maple))) + (let ((args (cdr (cdr a)))) + (while (and (memq calc-language '(pascal fortran)) + (eq (car-safe (nth 1 a)) 'calcFunc-subscr)) + (setq args (append (cdr (cdr (nth 1 a))) args) + a (nth 1 a))) + (list 'horiz + (math-compose-expr (nth 1 a) 1000) + (if (eq calc-language 'fortran) "(" "[") + (math-compose-vector args ", " 0) + (if (eq calc-language 'fortran) ")" "]")))) + ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3) + (eq calc-language 'big)) + (let* ((a1 (math-compose-expr (nth 1 a) 1000)) + (calc-language 'flat) + (a2 (math-compose-expr (nth 2 a) 0))) + (if (or (eq (car-safe a1) 'subscr) + (and (eq (car-safe a1) 'tag) + (eq (car-safe (nth 2 a1)) 'subscr) + (setq a1 (nth 2 a1)))) + (list 'subscr + (nth 1 a1) + (list 'horiz + (nth 2 a1) + ", " + a2)) + (list 'subscr a1 a2)))) + ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3) + (eq calc-language 'math)) + (list 'horiz + (math-compose-expr (nth 1 a) 1000) + "[[" + (math-compose-expr (nth 2 a) 0) + "]]")) + ((and (eq (car a) 'calcFunc-sqrt) + (eq calc-language 'tex)) + (list 'horiz + "\\sqrt{" + (math-compose-expr (nth 1 a) 0) + "}")) + ((and nil (eq (car a) 'calcFunc-sqrt) + (eq calc-language 'eqn)) + (list 'horiz + "sqrt {" + (math-compose-expr (nth 1 a) -1) + "}")) + ((and (eq (car a) '^) + (eq calc-language 'big)) + (list 'supscr + (if (or (math-looks-negp (nth 1 a)) + (memq (car-safe (nth 1 a)) '(^ / frac calcFunc-sqrt)) + (and (eq (car-safe (nth 1 a)) 'cplx) + (math-negp (nth 1 (nth 1 a))) + (eq (nth 2 (nth 1 a)) 0))) + (list 'horiz "(" (math-compose-expr (nth 1 a) 0) ")") + (math-compose-expr (nth 1 a) 201)) + (let ((calc-language 'flat) + (calc-number-radix 10)) + (math-compose-expr (nth 2 a) 0)))) + ((and (eq (car a) '/) + (eq calc-language 'big)) + (let ((a1 (let ((calc-language (if (memq (car-safe (nth 1 a)) '(/ frac)) + 'flat 'big))) + (math-compose-expr (nth 1 a) 0))) + (a2 (let ((calc-language (if (memq (car-safe (nth 2 a)) '(/ frac)) + 'flat 'big))) + (math-compose-expr (nth 2 a) 0)))) + (list 'vcent + (math-comp-height a1) + a1 '(rule ?-) a2))) + ((and (memq (car a) '(calcFunc-sum calcFunc-prod)) + (eq calc-language 'tex) + (= (length a) 5)) + (list 'horiz (if (eq (car a) 'calcFunc-sum) "\\sum" "\\prod") + "_{" (math-compose-expr (nth 2 a) 0) + "=" (math-compose-expr (nth 3 a) 0) + "}^{" (math-compose-expr (nth 4 a) 0) + "}{" (math-compose-expr (nth 1 a) 0) "}")) + ((and (eq (car a) 'calcFunc-lambda) + (> (length a) 2) + (memq calc-language '(nil flat big))) + (let ((p (cdr a)) + (ap calc-arg-values) + (math-compose-hash-args (if (= (length a) 3) 1 t))) + (while (and (cdr p) (equal (car p) (car ap))) + (setq p (cdr p) ap (cdr ap))) + (append '(horiz "<") + (if (cdr p) + (list (math-compose-vector + (nreverse (cdr (reverse (cdr a)))) ", " 0) + " : ") + nil) + (list (math-compose-expr (nth (1- (length a)) a) 0) + ">")))) + ((and (eq (car a) 'calcFunc-string) + (= (length a) 2) + (math-vectorp (nth 1 a)) + (math-vector-is-string (nth 1 a))) + (if (eq calc-language 'unform) + (concat "string(" (math-vector-to-string (nth 1 a) t) ")") + (math-vector-to-string (nth 1 a) nil))) + ((and (eq (car a) 'calcFunc-bstring) + (= (length a) 2) + (math-vectorp (nth 1 a)) + (math-vector-is-string (nth 1 a))) + (if (eq calc-language 'unform) + (concat "bstring(" (math-vector-to-string (nth 1 a) t) ")") + (let ((c nil) + (s (math-vector-to-string (nth 1 a) nil)) + p) + (while (string-match "[^ ] +[^ ]" s) + (setq p (1- (match-end 0)) + c (cons (list 'break math-compose-level) + (cons (substring s 0 p) + c)) + s (substring s p))) + (setq c (nreverse (cons s c))) + (or (= prec -123) + (setq c (cons (list 'set math-compose-level 2) c))) + (cons 'horiz c)))) + ((and (eq (car a) 'calcFunc-cprec) + (not (eq calc-language 'unform)) + (= (length a) 3) + (integerp (nth 2 a))) + (let ((c (math-compose-expr (nth 1 a) -1))) + (if (> prec (nth 2 a)) + (if (eq calc-language 'tex) + (list 'horiz "\\left( " c " \\right)") + (if (eq calc-language 'eqn) + (list 'horiz "{left ( " c " right )}") + (list 'horiz "(" c ")"))) + c))) + ((and (eq (car a) 'calcFunc-choriz) + (not (eq calc-language 'unform)) + (memq (length a) '(2 3 4)) + (math-vectorp (nth 1 a)) + (if (integerp (nth 2 a)) + (or (null (nth 3 a)) + (and (math-vectorp (nth 3 a)) + (math-vector-is-string (nth 3 a)))) + (or (null (nth 2 a)) + (and (math-vectorp (nth 2 a)) + (math-vector-is-string (nth 2 a)))))) + (let* ((cprec (and (integerp (nth 2 a)) (nth 2 a))) + (sep (nth (if cprec 3 2) a)) + (bprec nil)) + (if sep + (math-compose-vector (cdr (nth 1 a)) + (math-vector-to-string sep nil) + (or cprec prec)) + (cons 'horiz (mapcar (function + (lambda (x) + (if (eq (car-safe x) 'calcFunc-bstring) + (prog1 + (math-compose-expr + x (or bprec cprec prec)) + (setq bprec -123)) + (math-compose-expr x (or cprec prec))))) + (cdr (nth 1 a))))))) + ((and (memq (car a) '(calcFunc-cvert calcFunc-clvert calcFunc-crvert)) + (not (eq calc-language 'unform)) + (memq (length a) '(2 3)) + (math-vectorp (nth 1 a)) + (or (null (nth 2 a)) + (integerp (nth 2 a)))) + (let* ((base 0) + (v 0) + (prec (or (nth 2 a) prec)) + (c (mapcar (function + (lambda (x) + (let ((b nil) (cc nil) a d) + (if (and (memq (car-safe x) '(calcFunc-cbase + calcFunc-ctbase + calcFunc-cbbase)) + (memq (length x) '(1 2))) + (setq b (car x) + x (nth 1 x))) + (if (and (eq (car-safe x) 'calcFunc-crule) + (memq (length x) '(1 2)) + (or (null (nth 1 x)) + (and (math-vectorp (nth 1 x)) + (= (length (nth 1 x)) 2) + (math-vector-is-string + (nth 1 x))) + (and (natnump (nth 1 x)) + (<= (nth 1 x) 255)))) + (setq cc (list + 'rule + (if (math-vectorp (nth 1 x)) + (aref (math-vector-to-string + (nth 1 x) nil) 0) + (or (nth 1 x) ?-)))) + (or (and (memq (car-safe x) '(calcFunc-cvspace + calcFunc-ctspace + calcFunc-cbspace)) + (memq (length x) '(2 3)) + (eq (nth 1 x) 0)) + (null x) + (setq cc (math-compose-expr x prec)))) + (setq a (if cc (math-comp-ascent cc) 0) + d (if cc (math-comp-descent cc) 0)) + (if (eq b 'calcFunc-cbase) + (setq base (+ v a -1)) + (if (eq b 'calcFunc-ctbase) + (setq base v) + (if (eq b 'calcFunc-cbbase) + (setq base (+ v a d -1))))) + (setq v (+ v a d)) + cc))) + (cdr (nth 1 a))))) + (setq c (delq nil c)) + (if c + (cons (if (eq (car a) 'calcFunc-cvert) 'vcent + (if (eq (car a) 'calcFunc-clvert) 'vleft 'vright)) + (cons base c)) + " "))) + ((and (memq (car a) '(calcFunc-csup calcFunc-csub)) + (not (eq calc-language 'unform)) + (memq (length a) '(3 4)) + (or (null (nth 3 a)) + (integerp (nth 3 a)))) + (list (if (eq (car a) 'calcFunc-csup) 'supscr 'subscr) + (math-compose-expr (nth 1 a) (or (nth 3 a) 0)) + (math-compose-expr (nth 2 a) 0))) + ((and (eq (car a) 'calcFunc-cflat) + (not (eq calc-language 'unform)) + (memq (length a) '(2 3)) + (or (null (nth 2 a)) + (integerp (nth 2 a)))) + (let ((calc-language (if (memq calc-language '(nil big)) + 'flat calc-language))) + (math-compose-expr (nth 1 a) (or (nth 2 a) 0)))) + ((and (eq (car a) 'calcFunc-cspace) + (memq (length a) '(2 3)) + (natnump (nth 1 a))) + (if (nth 2 a) + (cons 'horiz (make-list (nth 1 a) + (if (and (math-vectorp (nth 2 a)) + (math-vector-is-string (nth 2 a))) + (math-vector-to-string (nth 2 a) nil) + (math-compose-expr (nth 2 a) 0)))) + (make-string (nth 1 a) ?\ ))) + ((and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace)) + (memq (length a) '(2 3)) + (natnump (nth 1 a))) + (if (= (nth 1 a) 0) + "" + (let* ((c (if (nth 2 a) + (if (and (math-vectorp (nth 2 a)) + (math-vector-is-string (nth 2 a))) + (math-vector-to-string (nth 2 a) nil) + (math-compose-expr (nth 2 a) 0)) + " ")) + (ca (math-comp-ascent c)) + (cd (math-comp-descent c))) + (cons 'vleft + (cons (if (eq (car a) 'calcFunc-ctspace) + (1- ca) + (if (eq (car a) 'calcFunc-cbspace) + (+ (* (1- (nth 1 a)) (+ ca cd)) (1- ca)) + (/ (1- (* (nth 1 a) (+ ca cd))) 2))) + (make-list (nth 1 a) c)))))) + ((and (eq (car a) 'calcFunc-evalto) + (setq calc-any-evaltos t) + (memq calc-language '(tex eqn)) + (= math-compose-level (if math-comp-tagged 2 1)) + (= (length a) 3)) + (list 'horiz + (if (eq calc-language 'tex) "\\evalto " "evalto ") + (math-compose-expr (nth 1 a) 0) + (if (eq calc-language 'tex) " \\to " " -> ") + (math-compose-expr (nth 2 a) 0))) + (t + (let ((op (and (not (eq calc-language 'unform)) + (if (and (eq (car a) 'calcFunc-if) (= (length a) 4)) + (assoc "?" math-expr-opers) + (math-assq2 (car a) math-expr-opers))))) + (cond ((and op + (or (= (length a) 3) (eq (car a) 'calcFunc-if)) + (/= (nth 3 op) -1)) + (cond + ((> prec (or (nth 4 op) (min (nth 2 op) (nth 3 op)))) + (if (and (eq calc-language 'tex) + (not (math-tex-expr-is-flat a))) + (if (eq (car-safe a) '/) + (list 'horiz "{" (math-compose-expr a -1) "}") + (list 'horiz "\\left( " + (math-compose-expr a -1) + " \\right)")) + (if (eq calc-language 'eqn) + (if (or (eq (car-safe a) '/) + (= (/ prec 100) 9)) + (list 'horiz "{" (math-compose-expr a -1) "}") + (if (math-tex-expr-is-flat a) + (list 'horiz "( " (math-compose-expr a -1) " )") + (list 'horiz "{left ( " + (math-compose-expr a -1) + " right )}"))) + (list 'horiz "(" (math-compose-expr a 0) ")")))) + ((and (eq calc-language 'tex) + (memq (car a) '(/ calcFunc-choose calcFunc-evalto)) + (>= prec 0)) + (list 'horiz "{" (math-compose-expr a -1) "}")) + ((eq (car a) 'calcFunc-if) + (list 'horiz + (math-compose-expr (nth 1 a) (nth 2 op)) + " ? " + (math-compose-expr (nth 2 a) 0) + " : " + (math-compose-expr (nth 3 a) (nth 3 op)))) + (t + (let* ((math-comp-tagged (and math-comp-tagged + (not (math-primp a)) + math-comp-tagged)) + (setlev (if (= prec (min (nth 2 op) (nth 3 op))) + (progn + (setq math-compose-level + (1- math-compose-level)) + nil) + math-compose-level)) + (lhs (math-compose-expr (nth 1 a) (nth 2 op))) + (rhs (math-compose-expr (nth 2 a) (nth 3 op)))) + (and (equal (car op) "^") + (eq (math-comp-first-char lhs) ?-) + (setq lhs (list 'horiz "(" lhs ")"))) + (and (eq calc-language 'tex) + (or (equal (car op) "^") (equal (car op) "_")) + (not (and (stringp rhs) (= (length rhs) 1))) + (setq rhs (list 'horiz "{" rhs "}"))) + (or (and (eq (car a) '*) + (or (null calc-language) + (assoc "2x" math-expr-opers)) + (let* ((prevt (math-prod-last-term (nth 1 a))) + (nextt (math-prod-first-term (nth 2 a))) + (prevc (or (math-comp-last-char lhs) + (and (memq (car-safe prevt) + '(^ calcFunc-subscr + calcFunc-sqrt + frac)) + (eq calc-language 'big) + ?0))) + (nextc (or (math-comp-first-char rhs) + (and (memq (car-safe nextt) + '(calcFunc-sqrt + calcFunc-sum + calcFunc-prod + calcFunc-integ)) + (eq calc-language 'big) + ?0)))) + (and prevc nextc + (or (and (>= nextc ?a) (<= nextc ?z)) + (and (>= nextc ?A) (<= nextc ?Z)) + (and (>= nextc ?0) (<= nextc ?9)) + (memq nextc '(?. ?_ ?# + ?\( ?\[ ?\{)) + (and (eq nextc ?\\) + (not (string-match + "\\`\\\\left(" + (math-comp-first-string + rhs))))) + (not (and (eq (car-safe prevt) 'var) + (eq nextc ?\())) + (list 'horiz + (list 'set setlev 1) + lhs + (list 'break math-compose-level) + " " + rhs)))) + (list 'horiz + (list 'set setlev 1) + lhs + (list 'break math-compose-level) + (if (or (equal (car op) "^") + (equal (car op) "_") + (equal (car op) "**") + (and (equal (car op) "*") + (math-comp-last-char lhs) + (math-comp-first-char rhs)) + (and (equal (car op) "/") + (math-num-integerp (nth 1 a)) + (math-integerp (nth 2 a)))) + (car op) + (if (and (eq calc-language 'big) + (equal (car op) "=>")) + " => " + (concat " " (car op) " "))) + rhs)))))) + ((and op (= (length a) 2) (= (nth 3 op) -1)) + (cond + ((or (> prec (or (nth 4 op) (nth 2 op))) + (and (not (eq (assoc (car op) math-expr-opers) op)) + (> prec 0))) ; don't write x% + y + (if (and (eq calc-language 'tex) + (not (math-tex-expr-is-flat a))) + (list 'horiz "\\left( " + (math-compose-expr a -1) + " \\right)") + (if (eq calc-language 'eqn) + (if (= (/ prec 100) 9) + (list 'horiz "{" (math-compose-expr a -1) "}") + (if (math-tex-expr-is-flat a) + (list 'horiz "{( " (math-compose-expr a -1) " )}") + (list 'horiz "{left ( " + (math-compose-expr a -1) + " right )}"))) + (list 'horiz "(" (math-compose-expr a 0) ")")))) + (t + (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op)))) + (list 'horiz + lhs + (if (or (> (length (car op)) 1) + (not (math-comp-is-flat lhs))) + (concat " " (car op)) + (car op))))))) + ((and op (= (length a) 2) (= (nth 2 op) -1)) + (cond + ((eq (nth 3 op) 0) + (let ((lr (and (eq calc-language 'tex) + (not (math-tex-expr-is-flat (nth 1 a)))))) + (list 'horiz + (if lr "\\left" "") + (if (string-match "\\`u\\([^a-zA-Z]\\)\\'" (car op)) + (substring (car op) 1) + (car op)) + (if (or lr (> (length (car op)) 2)) " " "") + (math-compose-expr (nth 1 a) -1) + (if (or lr (> (length (car op)) 2)) " " "") + (if lr "\\right" "") + (car (nth 1 (memq op math-expr-opers)))))) + ((> prec (or (nth 4 op) (nth 3 op))) + (if (and (eq calc-language 'tex) + (not (math-tex-expr-is-flat a))) + (list 'horiz "\\left( " + (math-compose-expr a -1) + " \\right)") + (if (eq calc-language 'eqn) + (if (= (/ prec 100) 9) + (list 'horiz "{" (math-compose-expr a -1) "}") + (if (math-tex-expr-is-flat a) + (list 'horiz "{( " (math-compose-expr a -1) " )}") + (list 'horiz "{left ( " + (math-compose-expr a -1) + " right )}"))) + (list 'horiz "(" (math-compose-expr a 0) ")")))) + (t + (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op)))) + (list 'horiz + (let ((ops (if (string-match "\\`u\\([^a-zA-Z]\\)\\'" + (car op)) + (substring (car op) 1) + (car op)))) + (if (or (> (length ops) 1) + (not (math-comp-is-flat rhs))) + (concat ops " ") + ops)) + rhs))))) + ((and (eq calc-language 'big) + (setq op (get (car a) 'math-compose-big)) + (funcall op a prec))) + ((and (setq op (assq calc-language + '( ( nil . math-compose-normal ) + ( flat . math-compose-normal ) + ( big . math-compose-normal ) + ( c . math-compose-c ) + ( pascal . math-compose-pascal ) + ( fortran . math-compose-fortran ) + ( tex . math-compose-tex ) + ( eqn . math-compose-eqn ) + ( math . math-compose-math ) + ( maple . math-compose-maple )))) + (setq op (get (car a) (cdr op))) + (funcall op a prec))) + (t + (let* ((func (car a)) + (func2 (assq func '(( mod . calcFunc-makemod ) + ( sdev . calcFunc-sdev ) + ( + . calcFunc-add ) + ( - . calcFunc-sub ) + ( * . calcFunc-mul ) + ( / . calcFunc-div ) + ( % . calcFunc-mod ) + ( ^ . calcFunc-pow ) + ( neg . calcFunc-neg ) + ( | . calcFunc-vconcat )))) + left right args) + (if func2 + (setq func (cdr func2))) + (if (setq func2 (rassq func math-expr-function-mapping)) + (setq func (car func2))) + (setq func (math-remove-dashes + (if (string-match + "\\`calcFunc-\\([a-zA-Z0-9']+\\)\\'" + (symbol-name func)) + (math-match-substring (symbol-name func) 1) + (symbol-name func)))) + (if (memq calc-language '(c fortran pascal maple)) + (setq func (math-to-underscores func))) + (if (and (eq calc-language 'tex) + calc-language-option + (not (= calc-language-option 0)) + (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'" func)) + (if (< (prefix-numeric-value calc-language-option) 0) + (setq func (format "\\%s" func)) + (setq func (format "\\hbox{%s}" func)))) + (if (and (eq calc-language 'eqn) + (string-match "[^']'+\\'" func)) + (let ((n (- (length func) (match-beginning 0) 1))) + (setq func (substring func 0 (- n))) + (while (>= (setq n (1- n)) 0) + (setq func (concat func " prime"))))) + (cond ((and (eq calc-language 'tex) + (or (> (length a) 2) + (not (math-tex-expr-is-flat (nth 1 a))))) + (setq left "\\left( " + right " \\right)")) + ((and (eq calc-language 'eqn) + (or (> (length a) 2) + (not (math-tex-expr-is-flat (nth 1 a))))) + (setq left "{left ( " + right " right )}")) + ((and (or (and (eq calc-language 'tex) + (eq (aref func 0) ?\\)) + (and (eq calc-language 'eqn) + (memq (car a) math-eqn-special-funcs))) + (not (string-match "\\hbox{" func)) + (= (length a) 2) + (or (Math-realp (nth 1 a)) + (memq (car (nth 1 a)) '(var *)))) + (setq left (if (eq calc-language 'eqn) "~{" "{") + right "}")) + ((eq calc-language 'eqn) + (setq left " ( " + right " )")) + (t (setq left calc-function-open + right calc-function-close))) + (list 'horiz func left + (math-compose-vector (cdr a) + (if (eq calc-language 'eqn) + " , " ", ") + 0) + right)))))))) +) + +(defconst math-eqn-special-funcs + '( calcFunc-log + calcFunc-ln calcFunc-exp + calcFunc-sin calcFunc-cos calcFunc-tan + calcFunc-sinh calcFunc-cosh calcFunc-tanh + calcFunc-arcsin calcFunc-arccos calcFunc-arctan + calcFunc-arcsinh calcFunc-arccosh calcFunc-arctanh +)) + + +(defun math-prod-first-term (x) + (while (eq (car-safe x) '*) + (setq x (nth 1 x))) + x +) + +(defun math-prod-last-term (x) + (while (eq (car-safe x) '*) + (setq x (nth 2 x))) + x +) + +(defun math-compose-vector (a sep prec) + (if a + (cons 'horiz + (cons (list 'set math-compose-level) + (let ((c (list (math-compose-expr (car a) prec)))) + (while (setq a (cdr a)) + (setq c (cons (if (eq (car-safe (car a)) + 'calcFunc-bstring) + (let ((math-compose-level + (1- math-compose-level))) + (math-compose-expr (car a) -123)) + (math-compose-expr (car a) prec)) + (cons (list 'break math-compose-level) + (cons sep c))))) + (nreverse c)))) + "") +) + +(defun math-vector-no-parens (a) + (or (cdr (cdr a)) + (not (eq (car-safe (nth 1 a)) '*))) +) + +(defun math-compose-matrix (a col cols base) + (let ((col 0) + (res nil)) + (while (<= (setq col (1+ col)) cols) + (setq res (cons (cons just + (cons base + (mapcar (function + (lambda (r) + (list 'horiz + (math-compose-expr + (nth col r) + vector-prec) + (if (= col cols) + "" + (concat comma-spc " "))))) + a))) + res))) + (nreverse res)) +) + +(defun math-compose-rows (a count first) + (if (cdr a) + (if (<= count 0) + (if (< count 0) + (math-compose-rows (cdr a) -1 nil) + (cons (concat (if (eq calc-language 'tex) " \\ldots" " ...") + comma) + (math-compose-rows (cdr a) -1 nil))) + (cons (list 'horiz + (if first (concat left-bracket " ") " ") + (math-compose-expr (car a) vector-prec) + comma) + (math-compose-rows (cdr a) (1- count) nil))) + (list (list 'horiz + (if first (concat left-bracket " ") " ") + (math-compose-expr (car a) vector-prec) + (concat " " right-bracket)))) +) + +(defun math-compose-tex-matrix (a) + (if (cdr a) + (cons (math-compose-vector (cdr (car a)) " & " 0) + (cons " \\\\ " + (math-compose-tex-matrix (cdr a)))) + (list (math-compose-vector (cdr (car a)) " & " 0))) +) + +(defun math-compose-eqn-matrix (a) + (if a + (cons + (cond ((eq calc-matrix-just 'right) "rcol ") + ((eq calc-matrix-just 'center) "ccol ") + (t "lcol ")) + (cons + (list 'break math-compose-level) + (cons + "{ " + (cons + (let ((math-compose-level (1+ math-compose-level))) + (math-compose-vector (cdr (car a)) " above " 1000)) + (cons + " } " + (math-compose-eqn-matrix (cdr a))))))) + nil) +) + +(defun math-vector-is-string (a) + (while (and (setq a (cdr a)) + (or (and (natnump (car a)) + (<= (car a) 255)) + (and (eq (car-safe (car a)) 'cplx) + (natnump (nth 1 (car a))) + (eq (nth 2 (car a)) 0) + (<= (nth 1 (car a)) 255))))) + (null a) +) + +(defun math-vector-to-string (a &optional quoted) + (setq a (concat (mapcar (function (lambda (x) (if (consp x) (nth 1 x) x))) + (cdr a)))) + (if (string-match "[\000-\037\177\\\"]" a) + (let ((p 0) + (pat (if quoted "[\000-\037\177\\\"]" "[\000-\037\177]")) + (codes (if quoted math-vector-to-string-chars '((?\^? . "^?")))) + (fmt (if quoted "\\^%c" "^%c")) + new) + (while (setq p (string-match pat a p)) + (if (setq new (assq (aref a p) codes)) + (setq a (concat (substring a 0 p) + (cdr new) + (substring a (1+ p))) + p (+ p (length (cdr new)))) + (setq a (concat (substring a 0 p) + (format fmt (+ (aref a p) 64)) + (substring a (1+ p))) + p (+ p 2)))))) + (if quoted + (concat "\"" a "\"") + a) +) +(defconst math-vector-to-string-chars '( ( ?\" . "\\\"" ) + ( ?\\ . "\\\\" ) + ( ?\a . "\\a" ) + ( ?\b . "\\b" ) + ( ?\e . "\\e" ) + ( ?\f . "\\f" ) + ( ?\n . "\\n" ) + ( ?\r . "\\r" ) + ( ?\t . "\\t" ) + ( ?\^? . "\\^?" ) +)) + +(defun math-to-underscores (x) + (if (string-match "\\`\\(.*\\)#\\(.*\\)\\'" x) + (math-to-underscores + (concat (math-match-substring x 1) "_" (math-match-substring x 2))) + x) +) + +(defun math-tex-expr-is-flat (a) + (or (Math-integerp a) + (memq (car a) '(float var)) + (and (memq (car a) '(+ - * neg)) + (progn + (while (and (setq a (cdr a)) + (math-tex-expr-is-flat (car a)))) + (null a))) + (and (memq (car a) '(^ calcFunc-subscr)) + (math-tex-expr-is-flat (nth 1 a)))) +) + +(put 'calcFunc-log 'math-compose-big 'math-compose-log) +(defun math-compose-log (a prec) + (and (= (length a) 3) + (list 'horiz + (list 'subscr "log" + (let ((calc-language 'flat)) + (math-compose-expr (nth 2 a) 1000))) + "(" + (math-compose-expr (nth 1 a) 1000) + ")")) +) + +(put 'calcFunc-log10 'math-compose-big 'math-compose-log10) +(defun math-compose-log10 (a prec) + (and (= (length a) 2) + (list 'horiz + (list 'subscr "log" "10") + "(" + (math-compose-expr (nth 1 a) 1000) + ")")) +) + +(put 'calcFunc-deriv 'math-compose-big 'math-compose-deriv) +(put 'calcFunc-tderiv 'math-compose-big 'math-compose-deriv) +(defun math-compose-deriv (a prec) + (and (= (length a) 3) + (math-compose-expr (list '/ + (list 'calcFunc-choriz + (list 'vec + '(calcFunc-string (vec ?d)) + (nth 1 a))) + (list 'calcFunc-choriz + (list 'vec + '(calcFunc-string (vec ?d)) + (nth 2 a)))) + prec)) +) + +(put 'calcFunc-sqrt 'math-compose-big 'math-compose-sqrt) +(defun math-compose-sqrt (a prec) + (and (= (length a) 2) + (let* ((c (math-compose-expr (nth 1 a) 0)) + (a (math-comp-ascent c)) + (d (math-comp-descent c)) + (h (+ a d)) + (w (math-comp-width c))) + (list 'vleft + a + (concat (if (= h 1) " " " ") + (make-string (+ w 2) ?\_)) + (list 'horiz + (if (= h 1) + "V" + (append (list 'vleft (1- a)) + (make-list (1- h) " |") + '("\\|"))) + " " + c)))) +) + +(put 'calcFunc-choose 'math-compose-big 'math-compose-choose) +(defun math-compose-choose (a prec) + (let ((a1 (math-compose-expr (nth 1 a) 0)) + (a2 (math-compose-expr (nth 2 a) 0))) + (list 'horiz + "(" + (list 'vcent + (math-comp-height a1) + a1 " " a2) + ")")) +) + +(put 'calcFunc-integ 'math-compose-big 'math-compose-integ) +(defun math-compose-integ (a prec) + (and (memq (length a) '(3 5)) + (eq (car-safe (nth 2 a)) 'var) + (let* ((parens (and (>= prec 196) (/= prec 1000))) + (var (math-compose-expr (nth 2 a) 0)) + (over (and (eq (car-safe (nth 2 a)) 'var) + (or (and (eq (car-safe (nth 1 a)) '/) + (math-numberp (nth 1 (nth 1 a)))) + (and (eq (car-safe (nth 1 a)) '^) + (math-looks-negp (nth 2 (nth 1 a))))))) + (expr (math-compose-expr (if over + (math-mul (nth 1 a) + (math-build-var-name + (format + "d%s" + (nth 1 (nth 2 a))))) + (nth 1 a)) 185)) + (calc-language 'flat) + (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) + (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0)))) + (list 'horiz + (if parens "(" "") + (append (list 'vcent (if high 3 2)) + (and high (list (list 'horiz " " high))) + '(" /" + " | " + " | " + " | " + "/ ") + (and low (list (list 'horiz low " ")))) + expr + (if over + "" + (list 'horiz " d" var)) + (if parens ")" "")))) +) + +(put 'calcFunc-sum 'math-compose-big 'math-compose-sum) +(defun math-compose-sum (a prec) + (and (memq (length a) '(3 5 6)) + (let* ((expr (math-compose-expr (nth 1 a) 185)) + (calc-language 'flat) + (var (math-compose-expr (nth 2 a) 0)) + (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) + (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0)))) + (list 'horiz + (if (memq prec '(180 201)) "(" "") + (append (list 'vcent (if high 3 2)) + (and high (list high)) + '("---- " + "\\ " + " > " + "/ " + "---- ") + (if low + (list (list 'horiz var " = " low)) + (list var))) + (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod)) + " " "") + expr + (if (memq prec '(180 201)) ")" "")))) +) + +(put 'calcFunc-prod 'math-compose-big 'math-compose-prod) +(defun math-compose-prod (a prec) + (and (memq (length a) '(3 5 6)) + (let* ((expr (math-compose-expr (nth 1 a) 198)) + (calc-language 'flat) + (var (math-compose-expr (nth 2 a) 0)) + (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) + (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0)))) + (list 'horiz + (if (memq prec '(196 201)) "(" "") + (append (list 'vcent (if high 3 2)) + (and high (list high)) + '("----- " + " | | " + " | | " + " | | ") + (if low + (list (list 'horiz var " = " low)) + (list var))) + (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod)) + " " "") + expr + (if (memq prec '(196 201)) ")" "")))) +) + + +(defun math-stack-value-offset-fancy () + (let ((cwid (+ (math-comp-width c)))) + (cond ((eq calc-display-just 'right) + (if calc-display-origin + (setq wid (max calc-display-origin 5)) + (if (integerp calc-line-breaking) + (setq wid calc-line-breaking))) + (setq off (- wid cwid + (max (- (length calc-right-label) + (if (and (integerp calc-line-breaking) + calc-display-origin) + (max (- calc-line-breaking + calc-display-origin) + 0) + 0)) + 0)))) + (t + (if calc-display-origin + (progn + (setq off (- calc-display-origin (/ cwid 2))) + (if (integerp calc-line-breaking) + (setq off (min off (- calc-line-breaking cwid + (length calc-right-label))))) + (if (>= off 0) + (setq wid (max wid (+ off cwid))))) + (if (integerp calc-line-breaking) + (setq wid calc-line-breaking)) + (setq off (/ (- wid cwid) 2))))) + (and (integerp calc-line-breaking) + (or (< off 0) + (and calc-display-origin + (> calc-line-breaking calc-display-origin))) + (setq wid calc-line-breaking))) +) + + + +;;; Convert a composition to string form, with embedded \n's if necessary. + +(defun math-composition-to-string (c &optional width) + (or width (setq width (calc-window-width))) + (if calc-display-raw + (math-comp-to-string-raw c 0) + (if (math-comp-is-flat c) + (math-comp-to-string-flat c width) + (math-vert-comp-to-string + (math-comp-simplify c width)))) +) + +(defun math-comp-is-flat (c) ; check if c's height is 1. + (cond ((not (consp c)) t) + ((memq (car c) '(set break)) t) + ((eq (car c) 'horiz) + (while (and (setq c (cdr c)) + (math-comp-is-flat (car c)))) + (null c)) + ((memq (car c) '(vleft vcent vright)) + (and (= (length c) 3) + (= (nth 1 c) 0) + (math-comp-is-flat (nth 2 c)))) + ((eq (car c) 'tag) + (math-comp-is-flat (nth 2 c))) + (t nil)) +) + + +;;; Convert a one-line composition to a string. Break into multiple +;;; lines if necessary, choosing break points according to the structure +;;; of the formula. + +(defun math-comp-to-string-flat (c full-width) + (if math-comp-sel-hpos + (let ((comp-pos 0)) + (math-comp-sel-flat-term c)) + (let ((comp-buf "") + (comp-word "") + (comp-pos 0) + (comp-margin 0) + (comp-highlight (and math-comp-selected calc-show-selections)) + (comp-level -1)) + (math-comp-to-string-flat-term '(set -1 0)) + (math-comp-to-string-flat-term c) + (math-comp-to-string-flat-term '(break -1)) + (let ((str (aref math-comp-buf-string 0)) + (prefix "")) + (and (> (length str) 0) (= (aref str 0) ? ) + (> (length comp-buf) 0) + (let ((k (length comp-buf))) + (while (not (= (aref comp-buf (setq k (1- k))) ?\n))) + (aset comp-buf k ? ) + (if (and (< (1+ k) (length comp-buf)) + (= (aref comp-buf (1+ k)) ? )) + (progn + (aset comp-buf (1+ k) ?\n) + (setq prefix " ")) + (setq prefix "\n")))) + (concat comp-buf prefix str)))) +) +(setq math-comp-buf-string (make-vector 10 "")) +(setq math-comp-buf-margin (make-vector 10 0)) +(setq math-comp-buf-level (make-vector 10 0)) + +(defun math-comp-to-string-flat-term (c) + (cond ((not (consp c)) + (if comp-highlight + (setq c (math-comp-highlight-string c))) + (setq comp-word (if (= (length comp-word) 0) c (concat comp-word c)) + comp-pos (+ comp-pos (length c)))) + + ((eq (car c) 'horiz) + (while (setq c (cdr c)) + (math-comp-to-string-flat-term (car c)))) + + ((eq (car c) 'set) + (if (nth 1 c) + (progn + (setq comp-level (1+ comp-level)) + (if (>= comp-level (length math-comp-buf-string)) + (setq math-comp-buf-string (vconcat math-comp-buf-string + math-comp-buf-string) + math-comp-buf-margin (vconcat math-comp-buf-margin + math-comp-buf-margin) + math-comp-buf-level (vconcat math-comp-buf-level + math-comp-buf-level))) + (aset math-comp-buf-string comp-level "") + (aset math-comp-buf-margin comp-level (+ comp-pos + (or (nth 2 c) 0))) + (aset math-comp-buf-level comp-level (nth 1 c))))) + + ((eq (car c) 'break) + (if (not calc-line-breaking) + (setq comp-buf (concat comp-buf comp-word) + comp-word "") + (let ((i 0) str) + (if (and (> comp-pos full-width) + (progn + (while (progn + (setq str (aref math-comp-buf-string i)) + (and (= (length str) 0) (< i comp-level))) + (setq i (1+ i))) + (or (> (length str) 0) (> (length comp-buf) 0)))) + (let ((prefix "") mrg wid) + (setq mrg (aref math-comp-buf-margin i)) + (if (> mrg 12) ; indenting too far, go back to far left + (let ((j i) (new (if calc-line-numbering 5 1))) + '(while (<= j comp-level) + (aset math-comp-buf-margin j + (+ (aref math-comp-buf-margin j) (- new mrg))) + (setq j (1+ j))) + (setq mrg new))) + (setq wid (+ (length str) comp-margin)) + (and (> (length str) 0) (= (aref str 0) ? ) + (> (length comp-buf) 0) + (let ((k (length comp-buf))) + (while (not (= (aref comp-buf (setq k (1- k))) ?\n))) + (aset comp-buf k ? ) + (if (and (< (1+ k) (length comp-buf)) + (= (aref comp-buf (1+ k)) ? )) + (progn + (aset comp-buf (1+ k) ?\n) + (setq prefix " ")) + (setq prefix "\n")))) + (setq comp-buf (concat comp-buf prefix str "\n" + (make-string mrg ? )) + comp-pos (+ comp-pos (- mrg wid)) + comp-margin mrg) + (aset math-comp-buf-string i "") + (while (<= (setq i (1+ i)) comp-level) + (if (> (aref math-comp-buf-margin i) wid) + (aset math-comp-buf-margin i + (+ (aref math-comp-buf-margin i) + (- mrg wid)))))))) + (if (and (= (nth 1 c) (aref math-comp-buf-level comp-level)) + (< comp-pos (+ (aref math-comp-buf-margin comp-level) 2))) + () ; avoid stupid breaks, e.g., "1 +\n really_long_expr" + (let ((str (aref math-comp-buf-string comp-level))) + (setq str (if (= (length str) 0) + comp-word + (concat str comp-word)) + comp-word "") + (while (< (nth 1 c) (aref math-comp-buf-level comp-level)) + (setq comp-level (1- comp-level)) + (or (= (length (aref math-comp-buf-string comp-level)) 0) + (setq str (concat (aref math-comp-buf-string comp-level) + str)))) + (aset math-comp-buf-string comp-level str))))) + + ((eq (car c) 'tag) + (cond ((eq (nth 1 c) math-comp-selected) + (let ((comp-highlight (not calc-show-selections))) + (math-comp-to-string-flat-term (nth 2 c)))) + ((eq (nth 1 c) t) + (let ((comp-highlight nil)) + (math-comp-to-string-flat-term (nth 2 c)))) + (t (math-comp-to-string-flat-term (nth 2 c))))) + + (t (math-comp-to-string-flat-term (nth 2 c)))) +) + +(defun math-comp-highlight-string (s) + (setq s (copy-sequence s)) + (let ((i (length s))) + (while (>= (setq i (1- i)) 0) + (or (memq (aref s i) '(32 ?\n)) + (aset s i (if calc-show-selections ?\. ?\#))))) + s +) + +(defun math-comp-sel-flat-term (c) + (cond ((not (consp c)) + (setq comp-pos (+ comp-pos (length c)))) + ((memq (car c) '(set break))) + ((eq (car c) 'horiz) + (while (and (setq c (cdr c)) (< math-comp-sel-cpos 1000000)) + (math-comp-sel-flat-term (car c)))) + ((eq (car c) 'tag) + (if (<= comp-pos math-comp-sel-cpos) + (progn + (math-comp-sel-flat-term (nth 2 c)) + (if (> comp-pos math-comp-sel-cpos) + (setq math-comp-sel-tag c + math-comp-sel-cpos 1000000))) + (math-comp-sel-flat-term (nth 2 c)))) + (t (math-comp-sel-flat-term (nth 2 c)))) +) + + +;;; Simplify a composition to a canonical form consisting of +;;; (vleft n "string" "string" "string" ...) +;;; where 0 <= n < number-of-strings. + +(defun math-comp-simplify (c full-width) + (let ((comp-buf (list "")) + (comp-base 0) + (comp-height 1) + (comp-hpos 0) + (comp-vpos 0) + (comp-highlight (and math-comp-selected calc-show-selections)) + (comp-tag nil)) + (math-comp-simplify-term c) + (cons 'vleft (cons comp-base comp-buf))) +) + +(defun math-comp-add-string (s h v) + (and (> (length s) 0) + (let ((vv (+ v comp-base))) + (if math-comp-sel-hpos + (math-comp-add-string-sel h vv (length s) 1) + (if (< vv 0) + (setq comp-buf (nconc (make-list (- vv) "") comp-buf) + comp-base (- v) + comp-height (- comp-height vv) + vv 0) + (if (>= vv comp-height) + (setq comp-buf (nconc comp-buf + (make-list (1+ (- vv comp-height)) "")) + comp-height (1+ vv)))) + (let ((str (nthcdr vv comp-buf))) + (setcar str (concat (car str) + (make-string (- h (length (car str))) 32) + (if comp-highlight + (math-comp-highlight-string s) + s))))))) +) + +(defun math-comp-add-string-sel (x y w h) + (if (and (<= y math-comp-sel-vpos) + (> (+ y h) math-comp-sel-vpos) + (<= x math-comp-sel-hpos) + (> (+ x w) math-comp-sel-hpos)) + (setq math-comp-sel-tag comp-tag + math-comp-sel-vpos 10000)) +) + +(defun math-comp-simplify-term (c) + (cond ((stringp c) + (math-comp-add-string c comp-hpos comp-vpos) + (setq comp-hpos (+ comp-hpos (length c)))) + ((memq (car c) '(set break)) + nil) + ((eq (car c) 'horiz) + (while (setq c (cdr c)) + (math-comp-simplify-term (car c)))) + ((memq (car c) '(vleft vcent vright)) + (let* ((comp-vpos (+ (- comp-vpos (nth 1 c)) + (1- (math-comp-ascent (nth 2 c))))) + (widths (mapcar 'math-comp-width (cdr (cdr c)))) + (maxwid (apply 'max widths)) + (bias (cond ((eq (car c) 'vleft) 0) + ((eq (car c) 'vcent) 1) + (t 2)))) + (setq c (cdr c)) + (while (setq c (cdr c)) + (if (eq (car-safe (car c)) 'rule) + (math-comp-add-string (make-string maxwid (nth 1 (car c))) + comp-hpos comp-vpos) + (let ((comp-hpos (+ comp-hpos (/ (* bias (- maxwid + (car widths))) + 2)))) + (math-comp-simplify-term (car c)))) + (and (cdr c) + (setq comp-vpos (+ comp-vpos + (+ (math-comp-descent (car c)) + (math-comp-ascent (nth 1 c)))) + widths (cdr widths)))) + (setq comp-hpos (+ comp-hpos maxwid)))) + ((eq (car c) 'supscr) + (let* ((asc (or 1 (math-comp-ascent (nth 1 c)))) + (desc (math-comp-descent (nth 2 c))) + (oldh (prog1 + comp-hpos + (math-comp-simplify-term (nth 1 c)))) + (comp-vpos (- comp-vpos (+ asc desc)))) + (math-comp-simplify-term (nth 2 c)) + (if math-comp-sel-hpos + (math-comp-add-string-sel oldh + (- comp-vpos + -1 + (math-comp-ascent (nth 2 c))) + (- comp-hpos oldh) + (math-comp-height c))))) + ((eq (car c) 'subscr) + (let* ((asc (math-comp-ascent (nth 2 c))) + (desc (math-comp-descent (nth 1 c))) + (oldv comp-vpos) + (oldh (prog1 + comp-hpos + (math-comp-simplify-term (nth 1 c)))) + (comp-vpos (+ comp-vpos (+ asc desc)))) + (math-comp-simplify-term (nth 2 c)) + (if math-comp-sel-hpos + (math-comp-add-string-sel oldh oldv + (- comp-hpos oldh) + (math-comp-height c))))) + ((eq (car c) 'tag) + (cond ((eq (nth 1 c) math-comp-selected) + (let ((comp-highlight (not calc-show-selections))) + (math-comp-simplify-term (nth 2 c)))) + ((eq (nth 1 c) t) + (let ((comp-highlight nil)) + (math-comp-simplify-term (nth 2 c)))) + (t (let ((comp-tag c)) + (math-comp-simplify-term (nth 2 c))))))) +) + + +;;; Measuring a composition. + +(defun math-comp-first-char (c) + (cond ((stringp c) + (and (> (length c) 0) + (elt c 0))) + ((memq (car c) '(horiz subscr supscr)) + (while (and (setq c (cdr c)) + (math-comp-is-null (car c)))) + (and c (math-comp-first-char (car c)))) + ((eq (car c) 'tag) + (math-comp-first-char (nth 2 c)))) +) + +(defun math-comp-first-string (c) + (cond ((stringp c) + (and (> (length c) 0) + c)) + ((eq (car c) 'horiz) + (while (and (setq c (cdr c)) + (math-comp-is-null (car c)))) + (and c (math-comp-first-string (car c)))) + ((eq (car c) 'tag) + (math-comp-first-string (nth 2 c)))) +) + +(defun math-comp-last-char (c) + (cond ((stringp c) + (and (> (length c) 0) + (elt c (1- (length c))))) + ((eq (car c) 'horiz) + (let ((c (reverse (cdr c)))) + (while (and c (math-comp-is-null (car c))) + (setq c (cdr c))) + (and c (math-comp-last-char (car c))))) + ((eq (car c) 'tag) + (math-comp-last-char (nth 2 c)))) +) + +(defun math-comp-is-null (c) + (cond ((stringp c) (= (length c) 0)) + ((memq (car c) '(horiz subscr supscr)) + (while (and (setq c (cdr c)) + (math-comp-is-null (car c)))) + (null c)) + ((eq (car c) 'tag) + (math-comp-is-null (nth 2 c))) + ((memq (car c) '(set break)) t)) +) + +(defun math-comp-width (c) + (cond ((not (consp c)) (length c)) + ((memq (car c) '(horiz subscr supscr)) + (let ((accum 0)) + (while (setq c (cdr c)) + (setq accum (+ accum (math-comp-width (car c))))) + accum)) + ((memq (car c) '(vcent vleft vright)) + (setq c (cdr c)) + (let ((accum 0)) + (while (setq c (cdr c)) + (setq accum (max accum (math-comp-width (car c))))) + accum)) + ((eq (car c) 'tag) + (math-comp-width (nth 2 c))) + (t 0)) +) + +(defun math-comp-height (c) + (if (stringp c) + 1 + (+ (math-comp-ascent c) (math-comp-descent c))) +) + +(defun math-comp-ascent (c) + (cond ((not (consp c)) 1) + ((eq (car c) 'horiz) + (let ((accum 0)) + (while (setq c (cdr c)) + (setq accum (max accum (math-comp-ascent (car c))))) + accum)) + ((memq (car c) '(vcent vleft vright)) + (if (> (nth 1 c) 0) (1+ (nth 1 c)) 1)) + ((eq (car c) 'supscr) + (max (math-comp-ascent (nth 1 c)) (1+ (math-comp-height (nth 2 c))))) + ((eq (car c) 'subscr) + (math-comp-ascent (nth 1 c))) + ((eq (car c) 'tag) + (math-comp-ascent (nth 2 c))) + (t 1)) +) + +(defun math-comp-descent (c) + (cond ((not (consp c)) 0) + ((eq (car c) 'horiz) + (let ((accum 0)) + (while (setq c (cdr c)) + (setq accum (max accum (math-comp-descent (car c))))) + accum)) + ((memq (car c) '(vcent vleft vright)) + (let ((accum (- (nth 1 c)))) + (setq c (cdr c)) + (while (setq c (cdr c)) + (setq accum (+ accum (math-comp-height (car c))))) + (max (1- accum) 0))) + ((eq (car c) 'supscr) + (math-comp-descent (nth 1 c))) + ((eq (car c) 'subscr) + (+ (math-comp-descent (nth 1 c)) (math-comp-height (nth 2 c)))) + ((eq (car c) 'tag) + (math-comp-descent (nth 2 c))) + (t 0)) +) + +(defun calcFunc-cwidth (a &optional prec) + (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump)) + (math-comp-width (math-compose-expr a (or prec 0))) +) + +(defun calcFunc-cheight (a &optional prec) + (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump)) + (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace)) + (memq (length a) '(2 3)) + (eq (nth 1 a) 0)) + 0 + (math-comp-height (math-compose-expr a (or prec 0)))) +) + +(defun calcFunc-cascent (a &optional prec) + (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump)) + (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace)) + (memq (length a) '(2 3)) + (eq (nth 1 a) 0)) + 0 + (math-comp-ascent (math-compose-expr a (or prec 0)))) +) + +(defun calcFunc-cdescent (a &optional prec) + (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump)) + (math-comp-descent (math-compose-expr a (or prec 0))) +) + + +;;; Convert a simplified composition into string form. + +(defun math-vert-comp-to-string (c) + (if (stringp c) + c + (math-vert-comp-to-string-step (cdr (cdr c)))) +) + +(defun math-vert-comp-to-string-step (c) + (if (cdr c) + (concat (car c) "\n" (math-vert-comp-to-string-step (cdr c))) + (car c)) +) + + +;;; Convert a composition to a string in "raw" form (for debugging). + +(defun math-comp-to-string-raw (c indent) + (cond ((or (not (consp c)) (eq (car c) 'set)) + (prin1-to-string c)) + ((null (cdr c)) + (concat "(" (symbol-name (car c)) ")")) + (t + (let ((next-indent (+ indent 2 (length (symbol-name (car c)))))) + (concat "(" + (symbol-name (car c)) + " " + (math-comp-to-string-raw (nth 1 c) next-indent) + (math-comp-to-string-raw-step (cdr (cdr c)) + next-indent) + ")")))) +) + +(defun math-comp-to-string-raw-step (cl indent) + (if cl + (concat "\n" + (make-string indent 32) + (math-comp-to-string-raw (car cl) indent) + (math-comp-to-string-raw-step (cdr cl) indent)) + "") +) + + + +