calccomp.el 55 KB

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