calccomp.el 55 KB

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