exdisplay.scm 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. #!fold-case
  21. ;;;; DISPLAY-EXPRESSION
  22. ;;; This is a package of expression display programs for Scmutils.
  23. ;;; This printer is a modified version of code developed by Aubrey
  24. ;;; Jaffer for the JACAL symbolic mathematics system. It also uses
  25. ;;; ideas from a printer developed by Kleanthes Koniaris.
  26. ;;; SHOW-EXPRESSION uses Tex to put up a window with the displayed
  27. ;;; expression. It also pretty-prints the expression in the Scheme
  28. ;;; buffer. It also prints the tex string used togenerate the tex output.
  29. ;;; The window is displayed using xdvi. Type Q in the window to get rid
  30. ;;; of it. If you quit in other ways (e.g., quitting from Scheme) this
  31. ;;; may leave garbage temp files in your directory. The garbage files are
  32. ;;; named temp-display<n>.
  33. ;;; EXPRESSION->TEX-STRING returns the string that is input to tex
  34. ;;; 2D-SHOW-EXPRESSION is a simple 2D ASCII character printer for
  35. ;;; mathematical expressions.
  36. ;;; Example:
  37. ;;; (define test
  38. ;;; '(/
  39. ;;; (+ alpha (/ ((derivative f) b) (+ alpha beta)))
  40. ;;; (+ (/ (+ x y) 2) (expt (/ (+ a c (/ 2 x)) (* d e)) (+ f (/ g h))))))
  41. ;;; (display (expression->tex-string test))
  42. ;;; $${{\alpha + {{Df\left( b \right)}\over {\alpha + \beta}}}
  43. ;;; \over {{{x + y}\over {2}} + \left( {{a + c + {{2}\over {x}}}\over {d e}} \right)
  44. ;;; ^{f + {{g}\over {h}}}}}$$
  45. ;;; (2d-show-expression test)
  46. ;;; Df(b)
  47. ;;; alpha + ------------
  48. ;;; alpha + beta
  49. ;;; ----------------------------
  50. ;;; g
  51. ;;; f + -
  52. ;;; / 2 \ h
  53. ;;; | a + c + - |
  54. ;;; x + y | x |
  55. ;;; ----- + | --------- |
  56. ;;; 2 \ d e /
  57. ;;; Unlike Jaffer's code, this version does not handle line breaks. We
  58. ;;; can extend it some day.
  59. #|
  60. ;;; To make this stand-alone must add:
  61. (define derivative-symbol 'D)
  62. (define (up-maker? expr) (and (pair? expr) (eq? (car expr) 'up)))
  63. (define (vector-maker? expr) (and (pair? expr) (eq? (car expr) 'vector)))
  64. (define (down-maker? expr) (and (pair? expr) (eq? (car expr) 'down)))
  65. (define (matrix-by-rows-maker? expr)
  66. (and (pair? expr) (eq? (car expr) 'matrix-by-rows)))
  67. |#
  68. (declare (usual-integrations))
  69. ;;; exported functions
  70. (define internal-show-expression)
  71. (define 2d-show-expression)
  72. (define expression->tex-string)
  73. (define display-tex-string)
  74. (define last-tex-string-generated)
  75. (define enable-tex-display #t)
  76. (let () ;package all stuff internally
  77. (define display-in-screen-window
  78. (let ((count 0))
  79. (lambda (tex-string)
  80. (let* ((dirname (->namestring (user-homedir-pathname)))
  81. (file-name (string-append dirname
  82. "temp-display"
  83. (number->string count)))
  84. (complete-tex-input (string-append
  85. ;;" \\magnification=\\magstep2\n"
  86. ;;"\\hsize=48pc \\hoffset=-4pc "
  87. "\\voffset=-6pc "
  88. "\\hsize=48pc " " \\hoffset=-6pc "
  89. boxit-string "\n"
  90. tex-string
  91. "\\vfil\\bye")))
  92. (with-output-to-file
  93. (string-append file-name ".tex")
  94. (lambda () (display complete-tex-input)))
  95. #|
  96. (working-unix/system (string-append "cd " dirname ";"
  97. " tex " file-name
  98. " > //dev//null 2>&1 "))
  99. (working-unix/system
  100. (string-append "xdvi " file-name ".dvi "
  101. "-s 4 "
  102. "-yoffset 3.5 "
  103. "-geometry 900x400+1+1; "
  104. "//bin//rm " file-name ".*"
  105. ))
  106. |#
  107. (run-shell-command
  108. (string-append "cd " dirname ";"
  109. " tex " file-name
  110. " > /dev/null 2>&1 ")
  111. 'output #f
  112. 'shell-file-name "/bin/sh")
  113. (run-shell-command
  114. (string-append "xdvi " file-name ".dvi "
  115. "-s 4 "
  116. "-yoffset 3.5 "
  117. "-geometry 900x400+1+1"
  118. " > /dev/null 2>&1; "
  119. "/bin/rm " file-name ".*"
  120. )
  121. 'output #f
  122. 'shell-file-name "/bin/sh")
  123. (set! count (+ count 1))
  124. ))))
  125. (define boxit-string
  126. "\\def\\boxit#1{\\vbox{\\hrule\\hbox{\\vrule\\kern5pt
  127. \\vbox{\\kern5pt#1\\kern5pt}\\kern3pt\\vrule}\\hrule}}\n")
  128. ;;; A couple of utility procedures:
  129. #|
  130. ;;some magic from Jinx
  131. (define (working-unix/system string)
  132. (let ((old #f))
  133. (dynamic-wind
  134. (lambda ()
  135. (set! old (thread-timer-interval))
  136. (set-thread-timer-interval! #f))
  137. (lambda ()
  138. (unix/system string))
  139. (lambda ()
  140. (set-thread-timer-interval! old)))))
  141. |#
  142. (define (2d-display-box box)
  143. (newline)
  144. (newline)
  145. (for-each (lambda (line)
  146. (for-each display (line-elements line))
  147. (newline))
  148. (box-lines box))
  149. (newline))
  150. ;;; The program works by gluing together boxes, which are lists of
  151. ;;; lines, all of the same width (the box-width). A box also has a
  152. ;;; vertical offset (box-voffset), which is used to align boxes when
  153. ;;; gluing them together horizontally--the vertical offset represents
  154. ;;; the height of the top line of the box with respect to a designated
  155. ;;; "zero" line. There is also a binding power (box-binding-power)
  156. ;;; that is used in unparsing expressions from infix to prefix. The
  157. ;;; binding power represents how how tightly the box is "held together". If
  158. ;;; the binding power is less than the required binding power, the box
  159. ;;; will be enclosed in parentheses.
  160. ;;; A character string is considered to be a special kind of box with
  161. ;;; voffset 0 and binding power the maximum binding power.
  162. ;;; Data structure definitions for boxes
  163. (define (make-box voffset width binding-power lines)
  164. (append (list 'box voffset width binding-power)
  165. lines))
  166. (define (explicit-box? elt)
  167. (and (pair? elt)
  168. (eq? (car elt) 'BOX)))
  169. (define (box-voffset box)
  170. (if (explicit-box? box)
  171. (list-ref box 1)
  172. 0))
  173. (define (box-width box)
  174. (if (explicit-box? box)
  175. (list-ref box 2)
  176. (string-length box)))
  177. (define (box-binding-power box)
  178. (if (explicit-box? box)
  179. (list-ref box 3)
  180. max-bp))
  181. (define (box-lines box)
  182. (if (explicit-box? box)
  183. (list-tail box 4)
  184. (list (make-line (list box)))))
  185. (define (box-nlines box)
  186. (length (box-lines box)))
  187. ;;;make a box just like the given one, but with the designated binding
  188. ;;;power
  189. (define (make-box-with-bp bp box)
  190. (make-box (box-voffset box)
  191. (box-width box)
  192. bp
  193. (box-lines box)))
  194. (define (make-empty-box width height)
  195. (let ((lines (make-list height (make-blank-line width))))
  196. (make-box 0 ;v-offset arbitrary
  197. width
  198. max-bp ;binding power arbitrary
  199. lines)))
  200. ;;; A LINE is a list of strings (the line-elements of the line)
  201. (define (make-line elements)
  202. (cons 'line elements))
  203. (define (line-elements line)
  204. (cdr line))
  205. (define (make-blank-line width)
  206. (make-line (make-blank-line-elts width)))
  207. (define (make-blank-line-elts width)
  208. (if (= width 0)
  209. '()
  210. (list (make-string width #\SPACE))))
  211. ;;;; Operations for combining boxes
  212. ;;;Join boxes horizontally, aligned according to the vertical offsets.
  213. ;;;Resulting box will have the binding power of the first box and a
  214. ;;;v-offset equal to the max of the v-offsets
  215. (define (glue-horiz boxes)
  216. (if (null? (cdr boxes))
  217. (car boxes)
  218. (join2-right (car boxes) (glue-horiz (cdr boxes)))))
  219. (define (join2-right box1 box2)
  220. (let ((v1 (box-voffset box1))
  221. (v2 (box-voffset box2))
  222. (blank1 (make-blank-line (box-width box1)))
  223. (blank2 (make-blank-line (box-width box2))))
  224. (make-box (max v1 v2)
  225. (+ (box-width box1) (box-width box2))
  226. (box-binding-power box1)
  227. (cond ((> v1 v2)
  228. ;;must pad box2 on top to start
  229. (join-lines-horiz
  230. (box-lines box1)
  231. (append (make-list (- v1 v2) blank2)
  232. (box-lines box2))
  233. blank1
  234. blank2))
  235. ((> v2 v1)
  236. ;;must pad box1 on top
  237. (join-lines-horiz
  238. (append (make-list (- v2 v1) blank1)
  239. (box-lines box1))
  240. (box-lines box2)
  241. blank1
  242. blank2))
  243. (else (join-lines-horiz (box-lines box1)
  244. (box-lines box2)
  245. blank1
  246. blank2))))))
  247. (define (join-lines-horiz lines1 lines2 blank1 blank2)
  248. (cond ((null? lines1)
  249. (map (lambda (line2) (make-line (append (line-elements blank1)
  250. (line-elements line2))))
  251. lines2))
  252. ((null? lines2)
  253. (map (lambda (line1) (make-line (append (line-elements line1)
  254. (line-elements blank2))))
  255. lines1))
  256. (else (cons (make-line (append (line-elements (car lines1))
  257. (line-elements (car lines2))))
  258. (join-lines-horiz (cdr lines1) (cdr lines2) blank1 blank2)))))
  259. ;;; Glue boxes vertically. The boxes will all be extended to the
  260. ;;; width of the maximum width box, and centered within that width.
  261. ;;; The voffset will be the voffset of the first box. (I.e., the
  262. ;;; first box will stay at the same level, and the other boxes will be
  263. ;;; appended below it.) The binding power will be the binding power
  264. ;;; of the first box.
  265. (define (glue-vert boxes)
  266. (if (null? (cdr boxes))
  267. (car boxes)
  268. (glue-below (car boxes) (glue-vert (cdr boxes)))))
  269. (define (glue-below box1 box2)
  270. (let* ((new-width (max (box-width box1) (box-width box2)))
  271. (nbox1 (pad-box-centered-to-width new-width box1))
  272. (nbox2 (pad-box-centered-to-width new-width box2)))
  273. (make-box
  274. (box-voffset box1)
  275. new-width
  276. (box-binding-power box1)
  277. (append (box-lines nbox1) (box-lines nbox2)))))
  278. ;;; Glue-above is similar to glue-below below, except that the
  279. ;;; v-offset of the top line in box2 remains
  280. ;;; what it was, and box1 is glued in above it.
  281. (define (glue-above box1 box2)
  282. (let* ((new-width (max (box-width box1) (box-width box2)))
  283. (nbox1 (pad-box-centered-to-width new-width box1))
  284. (nbox2 (pad-box-centered-to-width new-width box2)))
  285. (make-box
  286. (+ (box-voffset box2) (length (box-lines box1)))
  287. new-width
  288. (box-binding-power box1)
  289. (append (box-lines nbox1) (box-lines nbox2)))))
  290. ;;;pad the box on both the left and the right so it is centered in a
  291. ;;;box of the given width
  292. (define (pad-box-centered-to-width width box)
  293. (let* ((extra (- width (box-width box)))
  294. (extra-left (floor->exact (/ extra 2)))
  295. (extra-right (- extra extra-left))
  296. (pad-left (make-blank-line-elts extra-left))
  297. (pad-right (make-blank-line-elts extra-right)))
  298. (make-box (box-voffset box)
  299. width
  300. (box-binding-power box)
  301. (map (lambda (line)
  302. (make-line
  303. (append pad-left
  304. (line-elements line)
  305. pad-right)))
  306. (box-lines box)))))
  307. ;;; pad the box on both the top and the bottom so it will be centeted
  308. ;;; in a box of the given height. "Centered" here means that the box
  309. ;;; will appear in the center of the expanded box, regardles of where
  310. ;;; the zero line was.
  311. (define (pad-box-centered-to-height height box)
  312. (let* ((extra (- height (box-nlines box)))
  313. (extra-top (floor->exact (/ extra 2)))
  314. (extra-bottom (- extra extra-top))
  315. (width (box-width box)))
  316. (let ((padded-box
  317. (glue-below (glue-above (make-empty-box width extra-top)
  318. box)
  319. (make-empty-box width extra-bottom))))
  320. (shift-top-to (- (box-nlines padded-box) 1)
  321. padded-box))))
  322. ;;; Offsetting boxes vertically
  323. ;;; Make the voffset of the bottom of the box be at n
  324. (define (shift-bottom-to n box)
  325. (shift-top-to (+ n -1 (box-nlines box)) box))
  326. ;;; Shift the box so that its zero line is now at n
  327. (define (shift-zero-to n box)
  328. (shift-top-to (+ n (box-voffset box)) box))
  329. ;;; Shift the box so that the top of the box is now at n
  330. (define (shift-top-to n box)
  331. (make-box n
  332. (box-width box)
  333. (box-binding-power box)
  334. (box-lines box)))
  335. ;;;Create a box from a list of strings, on string per line. The
  336. ;;;strings are padded on the right to be all the same width.
  337. (define (strings->vbox voffset strings)
  338. (let* ((width (apply max (map string-length strings)))
  339. (padded-strings
  340. (map (lambda (string)
  341. (string-append (make-string
  342. (- width (string-length string))
  343. #\SPACE)
  344. string))
  345. strings))
  346. (lines (map (lambda (string)
  347. (make-line (list string)))
  348. padded-strings)))
  349. (make-box voffset
  350. width
  351. max-bp
  352. lines)))
  353. ;;; List utility:
  354. ;;;Interpolate element between all items in the list
  355. (define (interpolate element list)
  356. (cond ((null? list) '())
  357. ((null? (cdr list)) list)
  358. (else (cons (car list)
  359. (cons element
  360. (interpolate element (cdr list)))))))
  361. ;;; Binding powers of elements, and required binding powers. An element
  362. ;;; on the left will be parenthesized if it is used in a context on the
  363. ;;; right that appears above it in the table.
  364. ;;;
  365. ;;; max-bp 200
  366. ;;; one-char symbol 200
  367. ;;; parenthesized thing 200
  368. ;;;
  369. ;;; n-char symbol 190 product set off with dots in Tex
  370. ;;;
  371. ;;; subscripted 140
  372. ;;; superscripted 140
  373. ;;; derivative 140
  374. ;;; 2nd derviv 140
  375. ;;; partial deriv 140
  376. ;;; nth deriv 140
  377. ;;; base of exponentiation 140
  378. ;;; item to be subscripted 140
  379. ;;; subscript 140
  380. ;;; item to be differentiated 140
  381. ;;; expt 130
  382. ;;; application 130
  383. ;;; operator of application 130
  384. ;;; product 120
  385. ;;; quotient 120
  386. ;;; term in product 120
  387. ;;; sum/diff 100
  388. ;;; exponent of exponentiation 100
  389. ;;; term in sum 100
  390. ;;; negation 99
  391. (define max-bp 200)
  392. ;;; Enclose the box in parentheses if its binding power is less than
  393. ;;; the required bp. Uptable is the unparsing table (needed in order
  394. ;;; to know how to parenthesize).
  395. (define (insure-bp uptable required box)
  396. (if (< (box-binding-power box) required)
  397. ((cadr (assq 'parenthesize uptable)) uptable box)
  398. box))
  399. ;;; Create a new box by enclosing the given box in vertically
  400. ;;; expanding parentheses. The binding power of the new box is the
  401. ;;; maximum binding power. The voffset will be the voffset of the
  402. ;;; original box.
  403. (define (2d:parenthesize uptable box)
  404. (let ((n (box-nlines box)))
  405. (cond ((= n 0) "()")
  406. ((<= n 2)
  407. (make-box-with-bp max-bp
  408. (glue-horiz (list "(" box ")"))))
  409. (else
  410. (let ((left-paren
  411. (strings->vbox
  412. (box-voffset box)
  413. (append '(" / ")
  414. (make-list (- n 2) "| ")
  415. '(" \\ "))))
  416. (right-paren
  417. (strings->vbox
  418. (box-voffset box)
  419. (append '(" \\ ")
  420. (make-list (- n 2) " |")
  421. '(" / ")))))
  422. (make-box-with-bp max-bp (glue-horiz (list left-paren box right-paren))))))))
  423. (define (tex:parenthesize uptable box)
  424. (make-box-with-bp max-bp (glue-horiz (list "\\left( " box " \\right)"))))
  425. ;;;; Unparsing handlers. Each handler takes the expression and the
  426. ;;;; unparsing table.
  427. ;;; Some of the handlers here work both for tex-display and for
  428. ;;; 2d-display, others are specific to one or the other.
  429. (define (unparse-default uptable args)
  430. (make-box-with-bp 130
  431. (glue-horiz
  432. (list (insure-bp uptable 130 (car args))
  433. ((cadr (assq 'parenthesize uptable))
  434. uptable
  435. (if (null? (cdr args))
  436. ""
  437. (glue-horiz (interpolate ", " (cdr args)))))))))
  438. (define (unparse-sum uptable args)
  439. (let ((args (map (lambda (a) (insure-bp uptable 100 a)) args)))
  440. (make-box-with-bp 100 (glue-horiz (interpolate " + " args)))))
  441. (define (unparse-difference uptable args)
  442. (let ((args (map (lambda (a) (insure-bp uptable 100 a)) args)))
  443. (make-box-with-bp 100 (glue-horiz (interpolate " - " args)))))
  444. (define (unparse-negation uptable args)
  445. (make-box-with-bp 99
  446. (glue-horiz
  447. (list "- " (insure-bp uptable 101 (car args))))))
  448. (define (unparse-signed-sum uptable signs terms)
  449. (let ((args (map (lambda (a) (insure-bp uptable 100 a)) terms)))
  450. (make-box-with-bp 100 (glue-horiz (interpolate-signs signs args)))))
  451. ;;number of signs should equal number of args
  452. (define (interpolate-signs signs args)
  453. (define (interp signs args)
  454. (cond ((null? args) '())
  455. ((null? (cdr args)) args)
  456. (else (cons (car args)
  457. (cons (if (eq? (car signs) '-) " - " " + ")
  458. (interp (cdr signs) (cdr args)))))))
  459. (let ((after-first-sign (interp (cdr signs) args)))
  460. (if (eq? (car signs) '-)
  461. (cons " - " after-first-sign)
  462. after-first-sign)))
  463. (define (2d:unparse-product uptable args)
  464. (let ((args (map (lambda (a) (insure-bp uptable 120 a)) args)))
  465. (make-box-with-bp 120 (glue-horiz (interpolate " " args)))))
  466. ;;; For a product, if an element is a >1-char symbol (binding power
  467. ;;; 190), we set it off from the other factors by dots
  468. (define (tex:unparse-product uptable args)
  469. (let ((args (map (lambda (a) (insure-bp uptable 120 a)) args)))
  470. (make-box-with-bp 120 (glue-horiz (interpolate-for-tex-product args)))))
  471. (define (interpolate-for-tex-product list)
  472. (define (separator a1 a2)
  473. (if (or (= (box-binding-power a1) 190)
  474. (= (box-binding-power a2) 190))
  475. " \\cdot "
  476. " "))
  477. (cond ((null? list) '())
  478. ((null? (cdr list)) list)
  479. (else (cons (car list)
  480. (cons (separator (car list) (cadr list))
  481. (interpolate-for-tex-product (cdr list)))))))
  482. (define (2d:unparse-quotient uptable args)
  483. (let* ((box1 (car args))
  484. (box2 (cadr args))
  485. (width (max (box-width box1) (box-width box2)))
  486. (rule-box (make-string width #\-)))
  487. (make-box-with-bp 120
  488. (glue-below
  489. (glue-above box1 rule-box)
  490. box2))))
  491. (define (tex:unparse-quotient uptable args)
  492. (let ((box1 (car args))
  493. (box2 (cadr args)))
  494. (make-box-with-bp 120
  495. (glue-horiz
  496. (list "{" "{" box1 "}"
  497. "\\over "
  498. "{" box2 "}" "}")))))
  499. (define (2d:unparse-expt uptable args)
  500. ;;if base is not shorter than expt, raise expt
  501. ;;so that its zero is one above the top of the base.
  502. ;;otherwise raise so that bottom of expt is one above the top of the
  503. ;;base
  504. (let* ((base (insure-bp uptable 140 (car args)))
  505. (expt (insure-bp uptable 100 (cadr args)))
  506. (shift-expt
  507. (if (>= (box-nlines base) (box-nlines expt))
  508. (shift-zero-to (+ (box-voffset base) 1)
  509. expt)
  510. (shift-bottom-to (+ (box-voffset base) 1)
  511. expt))))
  512. (make-box-with-bp
  513. 130
  514. (glue-horiz (list base shift-expt)))))
  515. (define (tex:unparse-expt uptable args)
  516. (let ((base (insure-bp uptable 140 (car args)))
  517. (expt (insure-bp uptable 100 (cadr args))))
  518. (make-box-with-bp
  519. 130
  520. (glue-horiz (list "{" base "}^{" expt "}")))))
  521. (define (2d:unparse-superscript uptable args)
  522. (let ((top (insure-bp uptable 140 (car args)))
  523. (script (insure-bp uptable 140 (cadr args))))
  524. (make-box-with-bp
  525. 140
  526. (glue-horiz
  527. (list top
  528. (shift-top-to (+ (box-voffset top) (box-nlines top))
  529. script))))))
  530. (define (tex:unparse-superscript uptable args)
  531. (let ((top (insure-bp uptable 140 (car args)))
  532. (scripts
  533. (map (lambda (ss)
  534. (insure-bp uptable 140 ss))
  535. (cdr args))))
  536. (make-box-with-bp
  537. 140
  538. (glue-horiz
  539. (append (list "{")
  540. (list top)
  541. (list "}^{")
  542. (let lp ((scripts scripts))
  543. (if (null? (cdr scripts))
  544. (list (car scripts))
  545. (append (list (car scripts))
  546. (list ", ")
  547. (lp (cdr scripts)))))
  548. (list "}"))))))
  549. (define (2d:unparse-subscript uptable args)
  550. (let ((top (insure-bp uptable 140 (car args)))
  551. (script (insure-bp uptable 140 (cadr args))))
  552. (make-box-with-bp
  553. 140
  554. (glue-horiz
  555. (list top
  556. (shift-top-to (- (box-voffset top) (box-nlines top))
  557. script))))))
  558. (define (tex:unparse-subscript uptable args)
  559. (let ((top (insure-bp uptable 140 (car args)))
  560. (scripts
  561. (map (lambda (ss)
  562. (insure-bp uptable 140 ss))
  563. (cdr args))))
  564. (make-box-with-bp
  565. 140
  566. (glue-horiz
  567. (append (list "{")
  568. (list top)
  569. (list "}_{")
  570. (let lp ((scripts scripts))
  571. (if (null? (cdr scripts))
  572. (list (car scripts))
  573. (append (list (car scripts))
  574. (list ", ")
  575. (lp (cdr scripts)))))
  576. (list "}"))))))
  577. #|
  578. (define (tex:unparse-subscript uptable args)
  579. (let ((top (insure-bp uptable 140 (car args)))
  580. (script (insure-bp uptable 140 (cadr args))))
  581. (make-box-with-bp
  582. 140
  583. (glue-horiz (list top "_{" script "}")))))
  584. |#
  585. (define (unparse-derivative uptable args)
  586. (make-box-with-bp
  587. 140
  588. (glue-horiz (list "D" (insure-bp uptable 140 (car args))))))
  589. #|
  590. (define (unparse-derivative uptable args)
  591. (make-box-with-bp
  592. 140
  593. (glue-horiz (list (insure-bp uptable 140 (car args)) "'"))))
  594. |#
  595. (define (tex:unparse-sqrt uptable args)
  596. (make-box-with-bp
  597. 140
  598. (glue-horiz (list "\\sqrt{" (insure-bp uptable 90 (car args)) "}"))))
  599. (define (tex:unparse-dotted uptable args)
  600. (make-box-with-bp
  601. 140
  602. (glue-horiz (list "\\dot{" (insure-bp uptable 140 (car args)) "}"))))
  603. (define (2d:unparse-dotted uptable args)
  604. (make-box-with-bp
  605. 140
  606. (glue-horiz (list "(dot " (insure-bp uptable 140 (car args)) ")"))))
  607. (define (tex:unparse-dotdotted uptable args)
  608. (make-box-with-bp
  609. 140
  610. (glue-horiz (list "\\ddot{" (insure-bp uptable 140 (car args)) "}"))))
  611. (define (2d:unparse-dotdotted uptable args)
  612. (make-box-with-bp
  613. 140
  614. (glue-horiz (list "(ddot " (insure-bp uptable 140 (car args)) ")"))))
  615. (define (tex:unparse-primed uptable args)
  616. (let ((top (insure-bp uptable 140 (car args))))
  617. (make-box-with-bp 140
  618. (glue-horiz (list "{" top "}^\\prime")))))
  619. (define (2d:unparse-primed uptable args)
  620. (make-box-with-bp
  621. 140
  622. (glue-horiz (list "(prime " (insure-bp uptable 140 (car args)) ")"))))
  623. (define (tex:unparse-primeprimed uptable args)
  624. (let ((top (insure-bp uptable 140 (car args))))
  625. (make-box-with-bp 140
  626. (glue-horiz (list "{" top "}^{\\prime\\prime}")))))
  627. (define (2d:unparse-primeprimed uptable args)
  628. (make-box-with-bp
  629. 140
  630. (glue-horiz (list "(primeprime " (insure-bp uptable 140 (car args)) ")"))))
  631. #|
  632. (define (unparse-second-derivative uptable args)
  633. (make-box-with-bp
  634. 140
  635. (glue-horiz (list (insure-bp uptable 140 (car args)) "''"))))
  636. |#
  637. (define (2d:unparse-second-derivative uptable args)
  638. (make-box-with-bp
  639. 140
  640. (glue-horiz (list (2d:unparse-expt uptable (list "D" "2"))
  641. (insure-bp uptable 140 (car args))))))
  642. (define (tex:unparse-second-derivative uptable args)
  643. (make-box-with-bp
  644. 140
  645. (glue-horiz (list (tex:unparse-expt uptable (list "D" "2"))
  646. (insure-bp uptable 140 (car args))))))
  647. ;;; This does not work with multiple subscripts
  648. (define (2d:unparse-partial-derivative uptable args)
  649. (make-box-with-bp
  650. 140
  651. (glue-horiz (list (2d:unparse-subscript uptable (list "D" (cadr args)))
  652. (insure-bp uptable 140 (car args))))))
  653. (define (tex:unparse-partial-derivative uptable args)
  654. (make-box-with-bp
  655. 140
  656. (glue-horiz
  657. (list (tex:unparse-subscript uptable (cons "\\partial" (cdr args)))
  658. (insure-bp uptable 140 (car args))))))
  659. (define (2d:unparse-nth-derivative uptable args)
  660. (let ((op (2d:unparse-expt uptable (list "D" (cadr args)))))
  661. (make-box-with-bp
  662. 140
  663. (glue-horiz (list op (insure-bp uptable 140 (car args)))))))
  664. (define (tex:unparse-nth-derivative uptable args)
  665. (let ((op (tex:unparse-expt uptable (list "D" (cadr args)))))
  666. (make-box-with-bp
  667. 140
  668. (glue-horiz (list op (insure-bp uptable 140 (car args)))))))
  669. ;;; vector is printed as column matrix
  670. (define (2d:unparse-vector uptable args)
  671. (2d:unparse-matrix uptable
  672. (map list args)))
  673. ;;; a vector will be displayed as a 1-column matrix
  674. (define (tex:unparse-vector uptable args)
  675. ;;args here is the list of vector elements
  676. (tex:unparse-matrix uptable
  677. (map list args)))
  678. ;;; matrix list is a list of rows where each row is a list
  679. (define (2d:unparse-matrix uptable matrix-list)
  680. ;;first pad all elements in each column to the max width in the
  681. ;;column
  682. (define (transpose matrix-lists)
  683. (apply map (cons list matrix-lists)))
  684. (let* ((matrix-with-widended-columns
  685. (transpose
  686. (map (lambda (column)
  687. (let ((width (apply max (map box-width column))))
  688. (map (lambda (element)
  689. (pad-box-centered-to-width width element))
  690. column)))
  691. (transpose matrix-list))))
  692. ;;pad all elts in each row to the max height
  693. (matrix-with-lengthened-rows
  694. (map (lambda (row)
  695. (let ((height (apply max (map box-nlines row))))
  696. (map (lambda (element)
  697. (pad-box-centered-to-height height element))
  698. row)))
  699. matrix-with-widended-columns))
  700. ;;glue elts in each row together, separated by two spaces
  701. (row-boxes
  702. (map (lambda (row) (glue-horiz (interpolate " " row)))
  703. matrix-with-lengthened-rows))
  704. ;;glue the rows together, with separated by blank lines
  705. (separated-row-boxes
  706. (interpolate (make-empty-box (box-width (car row-boxes)) 1)
  707. row-boxes))
  708. (all-elts
  709. (glue-vert separated-row-boxes))
  710. ;;surround matrix by brackets
  711. (with-brackets
  712. (glue-horiz
  713. (list (strings->vbox (box-voffset all-elts)
  714. (make-list (box-nlines all-elts) "["))
  715. all-elts
  716. (strings->vbox (box-voffset all-elts)
  717. (make-list (box-nlines all-elts) "]"))))))
  718. ;;center matrix vertically
  719. (shift-top-to
  720. (floor->exact (/ (box-nlines with-brackets) 2))
  721. with-brackets)))
  722. (define (tex:unparse-matrix uptable matrix-list)
  723. (let* ((displaystyle-rows
  724. (map (lambda (row)
  725. (map (lambda (elt)
  726. (glue-horiz (list "\\displaystyle{ "
  727. elt
  728. "}")))
  729. row))
  730. matrix-list))
  731. (separated-rows
  732. (map (lambda (row) (glue-horiz (interpolate " & " row)))
  733. displaystyle-rows))
  734. (separated-columns
  735. (glue-horiz (interpolate " \\cr \\cr " separated-rows))))
  736. #;
  737. (glue-horiz
  738. (list "\\left\\{ \\matrix{ "
  739. separated-columns
  740. "} \\right\\}"))
  741. (glue-horiz
  742. (list "\\left\\lgroup \\matrix{ "
  743. separated-columns
  744. "} \\right\\rgroup"))))
  745. (define (tex:unparse-up uptable matrix-list)
  746. (let* ((displaystyle-rows
  747. (map (lambda (row)
  748. (map (lambda (elt)
  749. (glue-horiz (list "\\displaystyle{ "
  750. elt
  751. "}")))
  752. row))
  753. matrix-list))
  754. (separated-rows
  755. (map (lambda (row) (glue-horiz (interpolate " & " row)))
  756. displaystyle-rows))
  757. (separated-columns
  758. (glue-horiz (interpolate " \\cr \\cr " separated-rows))))
  759. (glue-horiz
  760. (list left-up-delimiter separated-columns right-up-delimiter))))
  761. (define (tex:unparse-down uptable matrix-list)
  762. (let* ((displaystyle-rows
  763. (map (lambda (row)
  764. (map (lambda (elt)
  765. (glue-horiz (list "\\displaystyle{ "
  766. elt
  767. "}")))
  768. row))
  769. matrix-list))
  770. (separated-rows
  771. (map (lambda (row) (glue-horiz (interpolate " & " row)))
  772. displaystyle-rows))
  773. (separated-columns
  774. (glue-horiz (interpolate " \\cr \\cr " separated-rows))))
  775. (glue-horiz
  776. (list left-down-delimiter separated-columns right-down-delimiter))))
  777. ;;; Unparsing table for 2D displays
  778. (define 2d:unparse-table
  779. `((parenthesize ,2d:parenthesize)
  780. (default ,unparse-default)
  781. (+ ,unparse-sum)
  782. ;;need sum (in addition to +) as an internal hook for
  783. ;;process-sum
  784. (sum ,unparse-sum)
  785. (- ,unparse-difference)
  786. (* ,2d:unparse-product)
  787. (negation ,unparse-negation)
  788. (/ ,2d:unparse-quotient)
  789. (signed-sum ,unparse-signed-sum)
  790. (expt ,2d:unparse-expt)
  791. (,derivative-symbol ,unparse-derivative)
  792. (derivative ,unparse-derivative)
  793. (second-derivative ,2d:unparse-second-derivative)
  794. (nth-derivative ,2d:unparse-nth-derivative)
  795. (partial-derivative ,2d:unparse-partial-derivative)
  796. (subscript ,2d:unparse-subscript)
  797. (superscript ,2d:unparse-superscript)
  798. (vector ,2d:unparse-vector)
  799. (row ,2d:unparse-matrix)
  800. (column ,2d:unparse-matrix)
  801. (down ,2d:unparse-matrix)
  802. (up ,2d:unparse-matrix)
  803. (matrix ,2d:unparse-matrix)
  804. (dotted ,2d:unparse-dotted)
  805. (dotdotted ,2d:unparse-dotdotted)
  806. (primed ,2d:unparse-primed)
  807. (primeprimed ,2d:unparse-primeprimed)
  808. ))
  809. (define 2d:symbol-substs
  810. `((derivative "D")
  811. ))
  812. (define tex:unparse-table
  813. `((parenthesize ,tex:parenthesize)
  814. (default ,unparse-default)
  815. (+ ,unparse-sum)
  816. ;;need sum (in addition to +) as an internal hook for
  817. ;;process-sum
  818. (sum ,unparse-sum)
  819. (- ,unparse-difference)
  820. (* ,tex:unparse-product)
  821. (& ,tex:unparse-product)
  822. (negation ,unparse-negation)
  823. (/ ,tex:unparse-quotient)
  824. (signed-sum ,unparse-signed-sum)
  825. (expt ,tex:unparse-expt)
  826. (,derivative-symbol ,unparse-derivative)
  827. (derivative ,unparse-derivative)
  828. (second-derivative ,tex:unparse-second-derivative)
  829. (nth-derivative ,tex:unparse-nth-derivative)
  830. (partial-derivative ,tex:unparse-partial-derivative)
  831. (subscript ,tex:unparse-subscript)
  832. (superscript ,tex:unparse-superscript)
  833. (vector ,tex:unparse-vector)
  834. (column ,tex:unparse-up)
  835. (row ,tex:unparse-down)
  836. (up ,tex:unparse-up)
  837. (down ,tex:unparse-down)
  838. (matrix ,tex:unparse-matrix)
  839. (sqrt ,tex:unparse-sqrt)
  840. (dotted ,tex:unparse-dotted)
  841. (dotdotted ,tex:unparse-dotdotted)
  842. (primed ,tex:unparse-primed)
  843. (primeprimed ,tex:unparse-primeprimed)
  844. ))
  845. (define tex:symbol-substs
  846. (append `((derivative "D")
  847. (acos "\\arccos")
  848. (asin "\\arcsin")
  849. (atan "\\arctan")
  850. )
  851. (map (lambda (string)
  852. (list (string->symbol string)
  853. (string-append "\\" string)))
  854. '(
  855. "alpha" "beta" "gamma" "delta" "epsilon" "zeta" "eta" "theta"
  856. "iota" "kappa" "lambda" "mu" "nu" "xi"
  857. ;; "omicron" does not appear in tex
  858. "pi" "rho" "tau" "upsilon" "phi" "chi" "psi" "omega"
  859. "varepsilon" "vartheta" "varpi" "varrho" "varsigma" "varphi"
  860. ;;"Alpha" "Beta"
  861. "Gamma" "Delta"
  862. ;;"Epsilon" "Zeta" "Eta"
  863. "Theta"
  864. ;;"Iota" "Kappa"
  865. "Lambda"
  866. ;;"Mu" "Nu"
  867. "Xi"
  868. ;;"Omicron"
  869. "Pi"
  870. ;;"Rho" "Tau"
  871. "Upsilon" "Phi"
  872. ;;"Chi"
  873. "Psi" "Omega"
  874. "aleph" "hbar" "nabla" "top" "bot" "mho" "Re" "Im"
  875. "infty" "Box" "diamond" "Diamond" "triangle"
  876. "sin" "cos" "tan" "cot" "sec" "csc" "log" "exp"
  877. ))
  878. (map (lambda (string)
  879. (list (string->symbol string)
  880. (string-append "{\\rm\\ " string " }")))
  881. '("&meter" "&kilogram" "&second"
  882. "&ampere" "&kelvin" "&mole"
  883. "&candela" "&radian"
  884. "&newton" "&joule" "&coulomb"
  885. "&watt" "&volt" "&ohm"
  886. "&siemens" "&farad" "&weber"
  887. "&henry" "&hertz" "&tesla"
  888. "&pascal" "&katal" "&becquerel"
  889. "&gray" "&sievert" "&inch"
  890. "&pound" "&slug" "&foot"
  891. "&mile" "&dyne" "&calorie"
  892. "&day" "&year" "&sidereal-year"
  893. "&AU" "&arcsec" "&pc"
  894. "&ly" "&esu" "&ev"))))
  895. ;;; Actual unparsing procedure. Symbol-substs is a table of special symbols
  896. ;;; to be substituted for. UPtable is an unparsing table.
  897. (define (unparse exp symbol-substs uptable)
  898. (let ((exp (unparse-special-convert exp))
  899. (up (lambda (exp) (unparse exp symbol-substs uptable))))
  900. (cond ((null? exp) "")
  901. ((number? exp) (unparse-number exp symbol-substs uptable))
  902. ((symbol? exp) (unparse-symbol exp symbol-substs uptable))
  903. ((up-maker? exp)
  904. ((cadr (assq 'column uptable))
  905. uptable
  906. (map list (map up (cdr exp)))))
  907. ((down-maker? exp)
  908. ((cadr (assq 'row uptable))
  909. uptable
  910. ;; For horizontal format
  911. ;;(list (map up (cdr exp)))
  912. ;; For vertical format
  913. (map list (map up (cdr exp)))))
  914. ((vector-maker? exp)
  915. ((cadr (assq 'vector uptable))
  916. uptable
  917. (map up (cdr exp))))
  918. ((matrix-by-rows-maker? exp)
  919. ((cadr (assq 'matrix uptable))
  920. uptable
  921. (map (lambda (row) (cdr (map up row)))
  922. (cdr exp))))
  923. ((eq? (car exp) '+)
  924. (process-sum exp symbol-substs uptable))
  925. ((symbol? (car exp))
  926. (let ((proc (assq (car exp) uptable)))
  927. (if proc
  928. ((cadr proc) uptable (map up (cdr exp)))
  929. ((cadr (assq 'default uptable)) uptable (map up exp)))))
  930. (else
  931. (let ((proc (assq 'default uptable)))
  932. ((cadr proc) uptable (map up exp)))))))
  933. (define (unparse-number n symbol-substs uptable)
  934. (cond ((and (real? n) (< n 0))
  935. (unparse `(- ,(- n)) symbol-substs uptable))
  936. ((and (rational? n) (exact? n) (not (= (denominator n) 1)))
  937. (unparse `(/ ,(numerator n) ,(denominator n))
  938. symbol-substs
  939. uptable))
  940. (else (number->string n))))
  941. ;;; symbols are treated as follows: some symbols are looked for and
  942. ;;; substituted specially (e.g., alpha turns into \alpha for tex).
  943. ;;; Other symbols have implied subscripts, e.g., m_1. Symbols that
  944. ;;; are more than one character long have a lower binding power than
  945. ;;; symbols that are one character long, so that the product of foo
  946. ;;; and x, for example, will be written as foo <dot> x in Tex, or the
  947. ;;; square of dt will be (dt)^2.
  948. (define (unparse-symbol symbol symbol-substs uptable)
  949. (let ((s (assq symbol symbol-substs)))
  950. (if s
  951. (cadr s)
  952. (let ((string (symbol->string symbol)))
  953. (split-at-underscore-or-caret
  954. string
  955. (lambda (before at after)
  956. (if (not before) ;no underscore or caret in symbol
  957. (unparse-string string symbol-substs uptable)
  958. (unparse `(,at ,(string->symbol before) ,(string->symbol after))
  959. symbol-substs
  960. uptable))))))))
  961. (define dotdot-string "dotdot")
  962. (define dotdot-string-length (string-length dotdot-string))
  963. (define dot-string "dot")
  964. (define dot-string-length (string-length dot-string))
  965. (define primeprime-string "primeprime")
  966. (define primeprime-string-length (string-length primeprime-string))
  967. (define prime-string "prime")
  968. (define prime-string-length (string-length prime-string))
  969. #|
  970. (define (unparse-string string symbol-substs uptable)
  971. (if (= (string-length string) 1)
  972. string
  973. (cond ((string-search-forward dotdot-string string)
  974. => (lambda (n)
  975. (if (= (+ n dotdot-string-length) ;terminal dotdot
  976. (string-length string))
  977. (unparse `(dotdotted
  978. ,(string->symbol (string-head string n)))
  979. symbol-substs uptable)
  980. (make-box-with-bp 190 string))))
  981. ((string-search-forward dot-string string)
  982. => (lambda (n)
  983. (if (= (+ n dot-string-length) ;terminal dot
  984. (string-length string))
  985. (unparse `(dotted
  986. ,(string->symbol (string-head string n)))
  987. symbol-substs uptable)
  988. (make-box-with-bp 190 string))))
  989. ((string-search-forward primeprime-string string)
  990. => (lambda (n)
  991. (if (= (+ n primeprime-string-length) ;terminal primeprime
  992. (string-length string))
  993. (unparse `(primeprimed
  994. ,(string->symbol (string-head string n)))
  995. symbol-substs uptable)
  996. (make-box-with-bp 190 string))))
  997. ((string-search-forward prime-string string)
  998. => (lambda (n)
  999. (if (= (+ n prime-string-length) ;terminal prime
  1000. (string-length string))
  1001. (unparse `(primed
  1002. ,(string->symbol (string-head string n)))
  1003. symbol-substs uptable)
  1004. (make-box-with-bp 190 string))))
  1005. (else
  1006. (make-box-with-bp 190 string)))))
  1007. |#
  1008. (define (unparse-string string symbol-substs uptable)
  1009. (define (for-terminal special-string special-string-length special-symbol)
  1010. (let ((n (string-search-forward special-string string)))
  1011. (if (and n (= (+ n special-string-length) (string-length string)))
  1012. (unparse `(,special-symbol
  1013. ,(string->symbol (string-head string n)))
  1014. symbol-substs uptable)
  1015. #f)))
  1016. (cond ((= (string-length string) 1) string)
  1017. ((for-terminal dotdot-string dotdot-string-length 'dotdotted))
  1018. ((for-terminal dot-string dot-string-length 'dotted))
  1019. ((for-terminal primeprime-string primeprime-string-length 'primeprimed))
  1020. ((for-terminal prime-string prime-string-length 'primed))
  1021. (else (make-box-with-bp 190 string))))
  1022. #|
  1023. (define (split-at-underscore-or-caret string cont)
  1024. ;;cont = (lambda (before after) ...)
  1025. (let ((index (string-find-next-char string #\_)))
  1026. (if (not index)
  1027. (cont #f #f)
  1028. (cont (string-head string index)
  1029. (string-tail string (+ index 1))))))
  1030. |#
  1031. (define (split-at-underscore-or-caret string cont)
  1032. ;;cont = (lambda (before at after) ...)
  1033. (let ((index (string-find-next-char-in-set string (char-set #\^ #\_))))
  1034. (if (not index)
  1035. (cont #f #f #f)
  1036. (cont (string-head string index)
  1037. (if (char=? (string-ref string index) #\^)
  1038. 'superscript
  1039. 'subscript)
  1040. (string-tail string (+ index 1))))))
  1041. ;;; Some forms have funny rules. For example, ((expt A 2) f) would
  1042. ;;; 2
  1043. ;;; unparse to A (f), but ((expt derivative 2) f) is traditionally
  1044. ;;; 2
  1045. ;;; written without parens, as D f. Partial derivatives are also
  1046. ;;; funny, since we will generally convert them to subscripts. The
  1047. ;;; following procedure catches these special forms. If there were
  1048. ;;; more of these, we would use a pattern matcher here.
  1049. (define (unparse-special-convert exp)
  1050. (cond ((and
  1051. ;;((expt derivative n) f) --> (nth-derivative f n)
  1052. (pair? exp)
  1053. (pair? (car exp))
  1054. (= (length exp) 2)
  1055. (= (length (car exp)) 3)
  1056. (eq? (caar exp) 'expt)
  1057. (or (eq? (cadar exp) 'derivative)
  1058. (eq? (cadar exp) derivative-symbol)))
  1059. (let ((exponent (list-ref (car exp) 2))
  1060. (base (cadr exp)))
  1061. (if (eq? exponent 2)
  1062. `(second-derivative ,base)
  1063. `(nth-derivative ,base ,exponent))))
  1064. ((and
  1065. ;;((partial x) f) --> (partial-derivative f x)
  1066. (pair? exp)
  1067. (pair? (car exp))
  1068. (= (length exp) 2)
  1069. (eq? (caar exp) 'partial))
  1070. `(partial-derivative ,(cadr exp) ,@(cdr (car exp))))
  1071. ((and
  1072. ;;(- x) --> (negation x)
  1073. (pair? exp)
  1074. (eq? (car exp) '-)
  1075. (eq? (length exp) 2))
  1076. `(negation ,(cadr exp)))
  1077. (else exp)))
  1078. ;;; for a sum, find all terms of the form (* -1 .....) and make them
  1079. ;;; appear without the -1 and with a negative sign in the sum
  1080. (define (process-sum exp symbol-substs uptable)
  1081. (let ((terms (cdr exp)))
  1082. (cond ((null? terms)
  1083. (unparse 0 symbol-substs uptable))
  1084. ((null? (cdr terms))
  1085. (unparse (car terms) symbol-substs uptable))
  1086. (else
  1087. (let ((signed-terms
  1088. (map (lambda (term)
  1089. (cond ((and (pair? term) (eq? (car term) '*))
  1090. (let ((first-factor (cadr term)))
  1091. (if (and (real? first-factor) (negative? first-factor))
  1092. (if (and (= first-factor -1) (not (null? (cddr term))))
  1093. (list '- (cons '* (cddr term)))
  1094. (list '- (cons '* (cons (- first-factor) (cddr term)))))
  1095. (list '+ term))))
  1096. ((and (pair? term) (eq? (car term) '/))
  1097. (let ((numer (cadr term)))
  1098. (cond ((and (real? numer) (negative? numer))
  1099. (list '- (cons '/ (cons (- numer) (cddr term)))))
  1100. ((and (pair? numer) (eq? (car numer) '*))
  1101. (let ((first-factor (cadr numer)))
  1102. (if (and (real? first-factor) (negative? first-factor))
  1103. (if (and (= first-factor -1) (not (null? (cddr numer))))
  1104. (list '-
  1105. (cons '/
  1106. (cons (cons '* (cddr numer))
  1107. (cddr term))))
  1108. (list '-
  1109. (cons '/
  1110. (cons (cons '*
  1111. (cons (- first-factor)
  1112. (cddr numer)))
  1113. (cddr term)))))
  1114. (list '+ term))))
  1115. (else
  1116. (list '+ term)))))
  1117. (else
  1118. (list '+ term))))
  1119. terms)))
  1120. (let ((processed-terms
  1121. (map (lambda (exp) (unparse exp symbol-substs uptable))
  1122. (map cadr signed-terms))))
  1123. ((cadr (assq 'signed-sum uptable))
  1124. uptable
  1125. (map car signed-terms)
  1126. processed-terms
  1127. )))))))
  1128. (set! internal-show-expression
  1129. (lambda (exp)
  1130. (set! last-tex-string-generated (expression->tex-string exp))
  1131. (let ((name (graphics-type-name (graphics-type #f))))
  1132. (if (and (eq? name 'X) enable-tex-display)
  1133. (begin (display-in-screen-window last-tex-string-generated)
  1134. (newline)
  1135. (newline)
  1136. ;; (display tex-string)
  1137. ;; (newline)
  1138. ;; (newline)
  1139. )
  1140. (2d-show-expression exp)))))
  1141. (set! 2d-show-expression
  1142. (lambda (exp)
  1143. (2d-display-box
  1144. (unparse exp 2d:symbol-substs 2d:unparse-table))))
  1145. (set! expression->tex-string
  1146. (lambda (exp)
  1147. (let* ((one-line-box (unparse exp tex:symbol-substs tex:unparse-table))
  1148. (tex-string
  1149. (with-output-to-string
  1150. (lambda ()
  1151. (for-each display
  1152. (line-elements (car (box-lines one-line-box))))))))
  1153. (string-append "\\boxit{ " "$$" tex-string "$$" "}"))))
  1154. #|
  1155. ;;; Beal's folly.
  1156. (set! expression->tex-string
  1157. (lambda (exp)
  1158. (let* ((one-line-box (unparse exp tex:symbol-substs tex:unparse-table))
  1159. (tex-string
  1160. (with-output-to-string
  1161. (lambda ()
  1162. (for-each display
  1163. (line-elements (car (box-lines one-line-box))))))))
  1164. (string-append "\\boxit{ " "$" tex-string "$" "}"))))
  1165. |#
  1166. (set! display-tex-string display-in-screen-window)
  1167. ) ;end let()
  1168. ;;;(define left-up-delimiter "\\left \\lceil \\matrix{ ")
  1169. ;;;(define right-up-delimiter "} \\right \\rceil")
  1170. ;;;(define left-down-delimiter "\\left \\lfloor \\matrix{ ")
  1171. ;;;(define right-down-delimiter "} \\right \\rfloor")
  1172. (define left-up-delimiter "\\left( \\matrix{ ")
  1173. (define right-up-delimiter "} \\right)")
  1174. (define left-down-delimiter "\\left[ \\matrix{ ")
  1175. (define right-down-delimiter "} \\right]")
  1176. #|
  1177. (define test
  1178. '(/
  1179. (+ alpha (/ ((derivative f) b) (+ alpha beta)))
  1180. (+ (/ (+ x y) 2) (expt (/ (+ a c (/ 2 x)) (* d e)) (+ f (/ g h))))))
  1181. |#