calccomp.el 56 KB

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