2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; Purpose: Generate Presentation MathML code from MAXIMA
5 ;;; Author: Paul S. Wang
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 ;=============================================================================
10 ; (c) copyright 1999 Kent State University
11 ; all rights reserved.
12 ;=============================================================================
14 (macsyma-module mathml
)
16 ;; special variables used in TeXetting
17 (declaim (special *row
* *indent
* ccol mPrport $mPrautolabel $mPrworksheet $lamPrworksheet
18 $mPrlabelleft $lamPrautolabel $mPrdisplaytype $mPrevaluate
19 macmPr-lib lop rop $labels casep
))
21 ;;****************************************************************************
23 ;;****************************************************************************
24 ;;Generatig MathML presenation codes for the expr
25 ;;This is a maxima top-level function used the form
26 ;; prmathml(expr, [,(filename|stream)[,t (d)]]) on the C-line
28 (defmfun $prmathml
(&rest margs
)
29 (prog (ccol *row
* *indent
* filename mexplabel mexpress mPrport x y
)
30 (setq mexpress
(car margs
))
31 (setq ccol
1 *indent
* 0 *row
* t
)
33 ((null mexpress
) (princ " NO EXPRESSION GIVEN ")
35 ((null (cdr margs
)) (setq filename nil
) (setq mPrport t
))
38 (if (stringp (cadr margs
))
40 (setq filename
(cadr margs
))
44 :if-does-not-exist
:create
))
45 ;; otherwise, assume (cadr margs) is a stream.
47 (t (princ " wrong No. of Arguments given ")))
49 ((member mexpress $labels
:test
#'eq
)
51 (intern (concatenate 'string
"("
52 (princ-to-string (fullstrip1 mexpress
))
54 (setq mexpress
(eval mexpress
)))
55 (t (setq mexplabel nil
)
56 (when $mPrevaluate
(setq mexpress
(meval mexpress
)))))
57 (when $mPrautolabel
(setq mexplabel
(updateautolabel)))
58 (when (symbolp (setq x mexpress
))
61 ((setq y
(mget x
'mexprer
))
63 (list '(mdefine) (cons (list x
) (cdadr y
))
65 ((setq y
(mget x
'mmacro
))
67 (list '(mdefmacro) (cons (list x
) (cdadr y
))
69 ((setq y
(mget x
'aexpr
))
75 (when (and (consp mexpress
) (consp (car mexpress
))
76 (eq 'mlabel
(caar mexpress
)))
77 (setq mexpress
(cadr mexpress
)))
81 (member 'c
(explode mexplabel
) :test
#'eq
)))
82 (format mPrport
"\\begin{verbatim}~%~a " mexplabel
)
83 (mgrind mexpress mPrport
)
84 (format mPrport
";~%\\end{verbatim}~%"))
87 (member 'c
(explode mexplabel
) :test
89 (format mPrport
"|~a " mexplabel
)
90 (mgrind mexpress mPrport
) (format mPrport
";|~%"))
93 (format mPrport
"\\begin{equation}~%"))
95 (tprinc "<math xmlns='http://www.w3.org/1998/Math/MathML'>") )
96 (t (tprinc "<math xmlns='http://www.w3.org/1998/Math/MathML'>")))
97 (mPr_engine mexpress
'mparen
'mparen
)
100 (format mPrport
"~%\\end{equation}~%"))
104 (format mPrport
"\\leqno{\\tt ~a}" mexplabel
)
105 (format mPrport
"\\eqno{\\tt ~a}" mexplabel
)))
106 (tprinc "</math>") (myterpri))
107 (t (tprinc "</math>")))))
108 (when filename
(terpri mPrport
) (close mPrport
))
113 ;; mPr_engine is a kernel function for this program. It checks whether
114 ;;an argument "mexpress" is an atom or expression. Then it will assign
115 ;;a proper function to the expression or just print if it is an atom.
116 ;;This is an applied object-oriented programming technique.
118 ;; arg: mexpress - macsyma internal representaton
119 ;; lop , rop - left and right handside operator of mexpress
121 ;;special check if expression is an array
122 ;;check whether or not to put parenthesis
123 ;;if not a keyword,it is a function
125 ;;;;;; This is the work house routine ;;;;;;;;
127 (defun mPr_engine (mexpress lop rop
)
128 (setq mexpress
(nformat mexpress
))
129 (if (atom mexpress
) (mPr-atom mexpress
)
130 (when (listp (car mexpress
))
132 ((member 'array
(car mexpress
) :test
#'eq
)
133 (mPr-array mexpress
))
134 ((or (<= (mPr-lbp (caar mexpress
)) (mPr-rbp lop
))
135 (> (mPr-lbp rop
) (mPr-rbp (caar mexpress
))))
136 (mPr-paren mexpress
))
137 (t (if (get (caar mexpress
) 'mPrprocess
)
138 (funcall (get (caar mexpress
) 'mPrprocess
) mexpress
)
139 (mPr-function mexpress
)))))))
143 ;*************************************************************************
147 ;*************************************************************************
149 ;;; tprinc is an intelligent low level printing routine. it keeps track of
150 ;;; the size of the output for purposes of allowing the TeX file to
151 ;;; have a reasonable line-length. tprinc will break it at a space
152 ;;; once it crosses a threshold.
153 ;;; this has nothing to do with breaking the resulting equations.
155 ;- arg: chstr - string or number to princ
156 ;- scheme: This function keeps track of the current location
157 ;- on the line of the cursor and makes sure
158 ;- that a value is all printed on one line (and not divided
159 ;- by the crazy top level os routines)
161 (defun row-begin(str)
183 ;would have exceeded the line length
184 ; lead off with a space for safety
186 (defun tprinc (chstr)
187 (prog (chlst linebreak
)
188 (cond ((> (+ (length (setq chlst
(exploden chstr
))) ccol
) 80)
190 (cond (*row
* (setq *row
* nil
) (myterpri))) ;; *row* calls for new row
191 (do ((ch chlst
(cdr ch
)) (colc ccol
(1+ colc
)))
192 ((null ch
) (setq ccol colc
))
193 (write-char (car ch
) mPrport
)
194 (if (and linebreak
(eq (car ch
) '>)) ;; line break only after >
198 ;; myterpri is terpri with port and indent control
201 (if mPrport
(terpri mPrport
) (mterpri))
206 ;; lastlementp is a predicate function to check a list l
207 ;;that is there only one element left in the list.
209 (defun lastelementp (l) (equal (length l
) 1))
211 ;; getsymbol is a function tool. It'll get the information
212 ;;from the database which is a symbol for an argument (atom)
214 (defun getsymbol (atom) (get atom
'chchr
))
216 ;; get_process is a function tool. It'll get the information
217 ;;from the database about the process to handle the operator (atom)
218 ;; (defun get_process (atom) (get atom 'mPrprocess))
220 ;; setup is a function to build the database (put properties) for
223 ; check if property exists already
225 (mapc #'(lambda (ls) (setf (get (car arg
) (car ls
)) (cadr ls
)))
228 ;; mPr-lbp and mPr-rbp are the functions to get information
229 ;; about size of the particular operator
230 ;; this is from the latex version of this prog
231 ;; not sure how well it works for MathML
233 (defun mPr-lbp (x) (cond ((get x
'mPr-lbp
)) (t (lbp x
))))
235 (defun mPr-rbp (x) (cond ((get x
'mPr-rbp
)) (t (rbp x
))))
237 ;; reduce lbp and rbp value for mtimes to get less parenthesis
239 (setf (get 'mtimes
'mPr-lbp
) '110)
240 (setf (get 'mtimes
'mPr-rbp
) '110)
242 ;; get back to normal case for paren
244 (setf (get 'mtimes
'mPr-lbp
) '120)
245 (setf (get 'mtimes
'mPr-rbp
) '120)
248 ;; mPr-abs is a function to handle abs()
250 (defun mPr-abs (mexpress)
251 (tprinc "<mo>|</mo>")
252 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
253 (tprinc "<mo>|</mo>"))
255 (defun mPr-conjugate (mexpress)
258 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
260 (tprinc "<mo>¯</mo>") ;; macron
263 ;; a[1]^2 or a[x,y]^z
264 (defun mPr-arr-power(b e
)
266 (mPr_engine (caar b
) lop
'mfunction
)
268 ((equal (length b
) 2)
269 (mPr_engine (cadr b
) lop rop
)
271 (t (row-begin "<mrow>") ;;(tprinc "<mrow>")
272 (do ((l (cdr b
) (cdr l
))) ((null l
)(row-end "</mrow>"))
273 (mPr_engine (car l
) lop rop
)
274 (when (not (lastelementp l
)) (tprinc "<mo>,</mo>")))
276 (mPr_engine e
'mparen
'mparen
) (tprinc "</msubsup>")
279 ;; when the operator is array ,this function will be called
280 ;; ex. a[x1,..] is a top level representation
282 (defun mPr-array (mexpress)
284 (mPr_engine (caar mexpress
) lop
'mfunction
)
286 (do ((l (cdr mexpress
) (cdr l
))) ((null l
) (row-end "</mrow>")(tprinc "</msub>"))
287 (mPr_engine (car l
) lop rop
)
288 (when (not (lastelementp l
)) (tprinc "<mo>,</mo>"))))
290 ;; mPr-at is a function to handle at(..) function
292 (defun mPr-at (mexpress)
293 (row-begin "<mrow>") ;;(tprinc "<mrow>")
294 (mPr_engine (cadr mexpress
) lop rop
)
295 (tprinc "<msub><mo>|</mo>")
296 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
297 (tprinc "</msub>") (row-end "</mrow>")
299 ;; in mPr_engine ,whennever mexpress is an atom this function taking care
300 ;;of it by getting a TeX symbol if it exists. Also it handles some word which
301 ;;has a reserved character for TeX
303 ;; prints instead of returning value now
304 (defun mPr-atom (chr)
306 ((numberp chr
) (mPr-num chr
))
308 ;; ((atom chr) (tprinc "<mi>") (tprinc (fullstrip1 chr)) (tprinc "</mi>"))
309 ((safe-get chr
'chchr
) (tprinc "<mi>")
310 (tprinc (safe-get chr
'chchr
)) (tprinc "</mi>"))
312 (let ((my-atom (if (symbolp chr
) (print-invert-case (stripdollar chr
)) chr
)))
314 (tprinc (coerce (mapcar #'handle_rsw
(exploden my-atom
)) 'string
))
318 (do ((l list
(cdr l
)) (l2 nil
)) ((null l
) (reverse l2
))
319 (when (not (equal a
(car l
))) (setq l2
(cons (car l
) l2
)))))
322 ;; this fn is called by mPr-atom ,it checks for a reserved char.
323 (defun handle_rsw (c)
325 ((equal c
#\
<) "<")
326 ((equal c
#\
>) ">")
327 ((equal c
#\
&) "&")
331 ;; top level: binomail(x,y);
333 (defun mPr-binomial (mexpress)
334 (row-begin "<mrow>") (tprinc "<mo>(</mo><mfrac linethickness=\"0\">")
335 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
337 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
338 (tprinc "</mfrac><mo>)</mo>") (row-end "</mrow>"))
342 ;; mPr-det is a function to handle determinant()
344 (defun mPr-det (mexpress)
345 (let ((operand (cadr mexpress
)))
346 (tprinc "<mi>det</mi>")
347 (mPr_engine operand
'mparen
'mparen
)))
349 ;; mPr-dif is a function to handle diferentiation function.
350 ;;It calls to subfunctions powerof_d and denopart.
352 (defun mPr-diff (mexpress)
354 ((powerof_d (cddr mexpress
)) (denopart (cddr mexpress
))
355 (tprinc "</mfrac><mo>⁢</mo>")
356 (mPr_engine (cadr mexpress
) 'mtimes rop
)
358 (t (mPr_engine (cadr mexpress
) lop rop
))))
360 ;;if there is no repeating differentiation
362 ;; if diff(exp,x,no,..)
366 (row-begin "<mrow>")(tprinc "<mfrac><mo> ⅆ </mo>") t
)
367 (t (do ((l1 l
(cddr l1
)) (l2 nil
(cons (cadr l1
) l2
))
369 ((null l1
) (setq power_of_d
(addn l2 nil
))
371 ((numberp power_of_d
)
373 ((equal 0 power_of_d
) nil
)
374 ((equal 1 power_of_d
)(row-begin "<mrow>")(tprinc "<mfrac><mo> ⅆ </mo>") t
)
375 (t (row-begin "<mrow>")(tprinc "<mfrac><msup><mo> ⅆ</mo><mn>")
376 (tprinc power_of_d
) (tprinc "</mn></msup>") t
)))
377 (t (row-begin "<mrow>")(tprinc "<mfrac><msup><mo> ⅆ</mo>")
378 (mPr_engine power_of_d
'mparen
'mparen
)
379 (tprinc "</msup>") t
))))))
382 ;;if just diff(exp,x)
383 ;;if diff(exp,x,nox,y,noy,...)
387 ((lastelementp l
) (row-begin "<mrow>") (tprinc "<mo> ⅆ </mo>")
388 (p-op (getsymbol 'mtimes
)) (mPr_engine (car l
) 'mtimes rop
)
390 (t (do ((l1 l
(cddr l1
)) (l2 nil
)) ((null l1
) (setq result l2
))
392 (cons (append '((mexpt)) (list (car l1
))
395 (setq result
(muln result nil
))
397 ((atom result
) (row-begin "<mrow>")(tprinc "<mo> ⅆ </mo>")
398 (p-op (getsymbol 'mtimes
))
399 (mPr_engine result
'mparen
'mparen
) (row-end "</mrow>"))
402 ((eq (caar result
) 'mexpt
)
403 (row-begin "<mrow>")(tprinc "<mo> ⅆ </mo>")
404 (p-op (getsymbol 'mtimes
))
405 (mPr_engine result
'mtimes
'mparen
) (row-end "</mrow>"))
406 (t (row-begin "<mrow>")
407 (do ((l1 (cdr result
) (cdr l1
)) (l2 nil
)
409 ((null l1
) (row-end "</mrow>"))
410 (tprinc "<mo> ⅆ </mo>")
411 (p-op (getsymbol 'mtimes
))
412 (mPr_engine (car l1
) 'mtimes
'mtimes
)
413 (when (not (lastelementp l1
)) (tprinc "<mo>,</mo>"))
417 ;; this function is adopted the main idea form macTeX from Prof. Richard
418 ;; Fateman in the mPr-mexpt
420 ;; insert left-angle-brackets for mncexpt. a^<n> is how a^^n looks.
421 ;; here is where we have to check for f(x)^b to be displayed
422 ;; as f^b(x), as is the case for sin(x)^2 .
423 ;; which should be sin^2 x rather than (sin x)^2 or (sin(x))^2.
424 ;; yet we must not display (a+b)^2 as +^2(a,b)...
425 ;; or (sin(x))^(-1) as sin^(-1)x, which would be arcsine x
428 ;this is (x) [maybe (x,y..), or nil]
429 ;; this is the exponent
430 ; there is such a function
431 ;; insist it is a % or $ function
433 ;;this case like sin(x)^x --> sin x
434 ;; if for example exp = (x+2)^4
436 (defun mPr-expt (mexpress)
438 ((eq (caar mexpress
) 'mexpt
)
439 (if (and (not (atom (cadr mexpress
)))
440 (member 'array
(caadr mexpress
) :test
#'eq
) ;; array
442 (mPr-arr-power (cadr mexpress
) (caddr mexpress
))
443 (let* ((fx (cadr mexpress
))
444 (f (and (not (atom fx
)) (atom (caar fx
)) (caar fx
)))
445 (bascdr (and f
(cdr fx
))) (expon (caddr mexpress
))
446 (doit (and f
(member (char (string f
) 0) (list #\%
#\$
))
447 (not (member f
'(%sum %product
) :test
#'eq
)))))
449 (doit (cond ;;;; sin^2 x case
451 (row-begin "<mrow>")(tprinc "<msup>") (mPr-fname f
)
452 (mPr-atom expon
)(tprinc "</msup>")
453 (tprinc "<mo>⁡</mo>")
454 (if (cdr bascdr
) (mPr-listparen bascdr
)
455 (mPr_engine (car bascdr
) 'mtimes
'mtimes
))
459 (mPr_engine fx
'mparen
'mparen
)
460 (mPr_engine expon
'mparen
'mparen
)
461 (tprinc "</msup>"))))
463 (mPr_engine (cadr mexpress
) lop
(caar mexpress
))
464 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
465 (tprinc "</msup>")))))
467 (t (tprinc "<msup>") ;;; mnexpt case
468 (mPr_engine (cadr mexpress
) lop
(caar mexpress
))
469 (row-begin "<mrow>")(tprinc "<mo>⟨</mo>")
470 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
471 (tprinc "<mo>⟩</mo>")(row-end "</mrow>")
474 ;; this function will check that whether or not an arg has a symbol
475 ;;in data base or not, if not it 'll be treated to be function which 'll
476 ;;be printed in rm font
479 (tprinc (if (getsymbol f
) (getsymbol f
) f
))
482 ;; to handle if an operator is a function which will be printed
483 (defun mPr-function (mexpress)
484 (mPr_engine (caar mexpress
) 'mparen
'mparen
)
485 (tprinc "<mo>⁡</mo>")
486 (mPr-listparen (cdr mexpress
)))
488 (defun mPr-gamma (mexpress)
489 (mPr_engine '|$Gamma|
'mparen
'mparen
) ;; ensure big gamma instead of little gamma (CHCHR property)
490 (tprinc "<mo>⁡</mo>")
491 (mPr-listparen (cdr mexpress
)))
493 ;; for infix operator , and also handle when there is a truncation
494 ;;in macsyma expression (see mPr-infix1)
496 ;; 1)mPr-infix1 calling
500 ;if -x or +x so call mPr-function
501 (defun mPr-infix (mexpress)
502 (let ((moperator (car mexpress
)) (moperands (cdr mexpress
)))
504 ((equal (length moperands
) 1) (mPr-function mexpress
))
505 (t (row-begin "<mrow>")
506 (mPr_engine (car moperands
) lop
(car moperator
))
507 (p-op-oprd moperator
(cadr moperands
))
508 (mPr-infix1 moperator
(cddr moperands
))
512 (defun mPr-infix1 (moperator moperands
)
515 (when (member 'trunc moperator
:test
#'equal
)
516 (p-op (getsymbol (car moperator
)))
517 (tprinc "<mo>⃛</mo>")))
518 (t (p-op-oprd moperator
(car moperands
))
519 (mPr-infix1 moperator
(cdr moperands
)))))
521 ;; p-op-oprd is a function printing operator and operand consecutively
522 ;; ex + x when + is a infix op and x is oprd
524 (defun p-op-oprd (moperator moperand
)
525 (let ((op (car moperator
)))
531 ((equal (caar moperand
) 'mminus
) (tprinc "<mo>-</mo>")
532 (mPr_engine (cadr moperand
) 'mminus rop
))
533 (t (tprinc "<mo>+</mo>") (mPr_engine moperand
'mplus rop
))))
534 (t (tprinc "<mo>+</mo>") (mPr-atom moperand
))))
535 (t (p-op (getsymbol op
))
536 (mPr_engine moperand op op
))))
545 ;; mPr-intgrate handles an integration expression
546 ;; It will detect that integrate function is called in short form
547 ;; or long form example: integrate(x^4,x,0,inf) is a long form.
551 (defun mPr-integrate (mexpress)
552 (setq mexpress
(meval
553 (list '($substitute
) '((mminus) $inf
) '$minf mexpress
)))
555 ((equal (length mexpress
) 3)
556 (row-begin "<mrow>")(tprinc "<mo>∫</mo>"))
557 ((equal (length mexpress
) 5)
558 (row-begin "<mrow>")(tprinc "<msubsup><mo>∫</mo>")
560 (mPr_engine (cadddr mexpress
) 'mparen
'mparen
)
564 (mPr_engine (car (cddddr mexpress
)) 'mparen
'mparen
)
566 (tprinc "</msubsup>"))
567 (t (merror "Wrong NO. of Arguments")))
569 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
570 (row-end "</mrow>")(tprinc "<mo>⁢</mo><mo> ⅆ </mo>")
571 (mPr_engine (caddr mexpress
) 'mparen rop
)
575 ;; mPr-limit takes care the "limit(exp,var,val,dir)"
576 (defun mPr-limit (mexpress)
577 (setq mexpress
(meval
578 (list '($substitute
) '((mminus) $inf
) '$minf mexpress
)))
579 (row-begin "<mrow>")(tprinc "<munder><mo>lim</mo>")(row-begin "<mrow>")
580 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
581 (tprinc "<mo>→</mo>")
582 (mPr_engine (cadddr mexpress
) 'mparen
'mapren
)
583 (when (car (cddddr mexpress
))
584 (if (member (car (cddddr mexpress
)) '($minus $plus
) :test
#'equal
)
585 (p-op (getsymbol (car (cddddr mexpress
))))
586 (merror "THE 4TH ARG MUST BE PLUS OR MINUS")))
587 (row-end "</mrow>")(tprinc "</munder>")
588 ;; (tprinc "<mo>⁢</mo>")
589 (mPr_engine (cadr mexpress
) 'mparen rop
)
591 ;; This function handles a macsyma list expression
593 (defun mPr-list (mexpress)
594 (tprinc "<mo>[</mo>")
595 (do ((l (cdr mexpress
) (cdr l
))) ((null l
) (tprinc "<mo>]</mo>"))
596 (mPr_engine (car l
) 'mparen
'mparen
)
597 (when (not (lastelementp l
)) (tprinc "<mo>,</mo>"))))
600 ;; This function is a subfunction of mPr-expt , mPr-function and
602 (defun mPr-listparen (mexpress)
603 (row-begin "<mrow>")(tprinc "<mo>(</mo>")
604 (do ((l mexpress
(cdr l
))) ((null l
) (tprinc "<mo>)</mo>") (row-end "</mrow>"))
605 (mPr_engine (car l
) 'mparen
'mparen
)
606 (when (not (lastelementp l
)) (tprinc "<mo>,</mo>"))))
608 ;; mPr-matrix handles matrix function
609 (defun mPr-matrix (mexpress)
610 (row-begin "<mfenced open='(' close=')'><mtable>")
611 (mapc #'(lambda (arg)
613 (do ((l (cdr arg
) (cdr l
))) ((null l
) (row-end "</mtr>"))
615 (mPr_engine (car l
) 'mparen
'mparen
)
619 (row-end "</mtable></mfenced>")
622 (defun mPr-mqapply (mexpress)
623 (mPr_engine (cadr mexpress
) lop
'mfunction
)
624 (mPr-listparen (cddr mexpress
)))
626 ;; this function handles the floating point number.
627 ;; convert 1.2e20 to 1.2 \\cdot 10^{20}
629 ;; it is not. go with it as given
630 (defun mPr-num (atom)
631 (let (r firstpart exponent
)
633 ((integerp atom
) (tprinc "<mn>") (tprinc atom
) (tprinc "</mn>"))
634 (t (setq r
(exploden atom
))
635 ;; Hmm. What if the exponent marker is something other than 'e' or 'E' ??
636 (setq exponent
(or (member #\e r
) (member #\E r
)))
638 ((null exponent
) (tprinc "<mn>") (tprinc atom
) (tprinc "</mn>"))
640 (nreverse (cdr (or (member #\e
(reverse r
)) (member #\E
(reverse r
))))))
642 (mapc #'tpchar firstpart
) (tprinc "</mn>")
643 (tprinc "<mo>·</mo><msup><mn>10</mn> <mn>")
644 (mapc #'tpchar
(cdr exponent
))
645 (tprinc "</mn></msup>")))))))
647 ;; this function puts parenthesis for the expression
648 (defun mPr-paren (mexpress)
649 (row-begin "<mrow>")(tprinc "<mo>(</mo>")
650 (mPr_engine mexpress
'mparen
'mparen
)
651 (tprinc "<mo>)</mo>") (row-end "</mrow>"))
652 ;; this function handles "+" operator which is infix form
654 ;if -x or +x so call mPr-function
655 (defun mPr-plus (mexpress)
656 (let ((moperands (cdr mexpress
))
657 (flag_trunc (member 'trunc
(car mexpress
) :test
#'eq
)))
659 ((equal (length moperands
) 1) (mPr-prefix mexpress
))
660 (t (row-begin "<mrow>")
661 (mPr_engine (car moperands
) lop
'mplus
)
662 (print_op_oprd (cadr moperands
))
663 (mPr-plus1 (cddr moperands
) flag_trunc
)
668 (defun mPr-plus1 (moperands flag_trunc
)
670 ((null moperands
) (when flag_trunc
(tprinc "<mo>+</mo><mo>⃛</mo>")))
671 (t (print_op_oprd (car moperands
))
672 (mPr-plus1 (cdr moperands
) flag_trunc
))))
675 (defun print_op_oprd (moperand)
679 ((equal (caar moperand
) 'mminus
) (tprinc "<mo>-</mo>")
680 (mPr_engine (cadr moperand
) 'mplus rop
))
681 (t (tprinc "<mo>+</mo>") (mPr_engine moperand
'mplus
'mparen
))))
682 (t (tprinc "<mo>+</mo>") (mPr-atom moperand
))))
683 ;; mPr-postfix handles for postfix notation expression like factorial
685 (defun mPr-postfix (mexpress)
687 (mPr_engine (cadr mexpress
) lop
(caar mexpress
))
689 (p-op (getsymbol (caar mexpress
))))
691 ;; mPr-prefix is a function to handle a prefix notation form
693 (defun mPr-prefix (mexpress)
694 (let ((op (caar mexpress
)) (oprnd (cadr mexpress
)))
696 (p-op (getsymbol op
))
697 (mPr_engine oprnd op rop
)
698 (row-end "</mrow>")))
699 ;; this function takes care the quotient function or "/" sign
701 (defun mPr-quotient (mexpress)
702 (row-begin "<mfrac><mrow>")
703 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
706 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
707 (row-end "</mrow></mfrac>"))
709 (defun mPr-rat (mexpress) (mPr-quotient mexpress
))
711 ;; this function handles binomial coefficients
713 (defun mPr-binomial(mexpress)
714 (row-begin "<mrow><mfenced open='(' close=')'><mfrac linethickness='0'><mrow>")
715 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
716 (tprinc "</mrow><mrow>")
717 (mPr_engine (caddr mexpress
) 'mparen
'mparen
)
718 (row-end "</mrow></mfrac></mfenced></mrow>")
721 ;; this function handles sqrt
723 (defun mPr-sqrt (mexpress)
725 (mPr_engine (cadr mexpress
) 'mparen
'mparen
)
728 ;; This function takes care both sum(exp,ind,lo,hi) and
729 ;; product(exp,ind,lo,hi)
734 (defun mPr-sumprod (mexpress)
735 (row-begin "<mrow>")(tprinc "<munderover>")
736 (p-op (getsymbol (caar mexpress
)))
738 (mPr_engine (caddr mexpress
) 'mparen
'mequal
)
739 (tprinc "<mo>=</mo>")
741 (list '($substitute
) '((mminus) $inf
) '$minf
(cadddr mexpress
)))
745 (list '($substitute
) '((mminus) $inf
) '$minf
(car (cddddr mexpress
))))
747 (tprinc "</munderover>")
748 (mPr_engine (cadr mexpress
) 'mparen rop
)
750 ;; mPr-times a function handle multiplication
751 (defun mPr-times (mexpress)
752 (let ((lop 'mtimes
) (rop 'mtimes
)) (mPr-infix mexpress
)))
754 (defun mathml-presentation-lambda (mexpress)
756 ((op (caar mexpress
))
757 (args (cdr (cadr mexpress
)))
758 (body (cddr mexpress
)))
759 (mPr_engine op
'mparen
'mparen
)
760 (if (= (length args
) 1)
761 (mPr_engine (car args
) 'mparen
'mparen
)
762 (mPr-listparen args
))
763 (mPr_engine "." 'mparen
'mparen
)
764 (if (= (length body
) 1)
765 (mPr_engine (car body
) 'mparen
'mparen
)
766 (mPr-listparen body
))))
768 ;; An improvement on the default, but not much.
769 ;; Could benefit from just a little more attention.
770 (defun mathml-presentation-buildinfo (mexpress)
771 (mPr_engine `(($matrix
) ,@(mapcar #'(lambda (e) `((mlist) ,e
)) (cdr mexpress
))) 'mparen
'mparen
))
775 (setup '(mlist (mPrprocess mPr-list
)))
777 (setup '(mplus (mPrprocess mPr-plus
) (mPr-lbp 100) (mPr-rbp 100)
780 (setup '(mminus (mPrprocess mPr-prefix
) (mPr-lbp 100) (mPr-rbp 100)
783 (setup '(mquote (mPrprocess mPr-prefix
) (mPr-rbp 201) (chchr "'")))
785 (setup '(mand (mPrprocess mPr-infix
) (mPr-lbp 60) (mPr-rbp 60)
788 (setup '(mor (mPrprocess mPr-infix
) (mPr-lbp 50) (mPr-rbp 50)
791 (setup '(mnot (mPrprocess mPr-prefix
) (mPr-rbp 70) (chchr "¬")))
793 (setup '(mgreaterp (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
796 (setup '(mgeqp (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
800 (setup '(mnotequal (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
801 (chchr "≠")))
803 (setup '(mleqp (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
806 (setup '(mlessp (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
809 (setup '(msetq (mPrprocess mPr-infix
) (mPr-lbp 180) (mPr-rbp 20)
812 (setup '(mset (mPrprocess mPr-infix
) (mPr-lbp 180) (mPr-rbp 20)
813 (chchr "≔"))) ;;; This is not math
815 (setup '(mdefine (mPrprocess mPr-infix
) (mPr-lbp 180) (mPr-rbp 20)
818 (setup '(mfactorial (mPrprocess mPr-postfix
) (mPr-lbp 160) (chchr "!")))
820 (setup '(mabs (mPrprocess mPr-abs
)))
822 (setup '(%abs
(mPrprocess mPr-abs
)))
824 (setup '($conjugate
(mPrprocess mPr-conjugate
)))
826 (setup '(mnctimes (mPrprocess mPr-infix
) (mPr-lbp 110) (mPr-rbp 109)
827 (chchr "·")))
829 (setup '(marrow (mPrprocess mPr-infix
) (mPr-lbp 180) (mPr-rbp 20)
830 (chchr "→")))
832 (setup '(mrarrow (mPrprocess mPr-prefix
) (mPr-lbp 180) (mPr-rbp 20)
833 (chchr "→")))
835 (setup '(mdif (mPrprocess mPr-infix
) (mPr-lbp 100) (mPr-rbp 100)
838 (setup '(mtimes (mPrprocess mPr-times
) (mPr-lbp 120) (mPr-rbp 120)
839 (chchr "⁢")))
841 (setup '(mdottimes (mPrprocess mPr-infix
) (mPr-lbp 120) (mPr-rbp 120)
842 (chchr "·")))
844 (setup '(mexpt (mPrprocess mPr-expt
) (mPr-lbp 140) (mPr-rbp 139)))
846 (setup '(mncexpt (mPrprocess mPr-expt
) (mPr-lbp 135) (mPr-rbp 134)))
848 (setup '(%at
(mPrprocess mPr-at
)))
850 (setup '($at
(mPrprocess mPr-at
)))
852 (setup '($det
(mPrprocess mPr-det
)))
854 (setup '(%determinant
(mPrprocess mPr-det
)))
856 (setup '($binomial
(mPrprocess mPr-binomial
)))
858 (setup '(%binomial
(mPrprocess mPr-binomial
)))
860 (setup '(%sum
(mPrprocess mPr-sumprod
) (chchr "∑")))
862 (setup '($sum
(mPrprocess mPr-sumprod
) (chchr "∑")))
864 (setup '($product
(mPrprocess mPr-sumprod
) (chchr "&Prod;")))
866 (setup '(%product
(mPrprocess mPr-sumprod
) (chchr "&Prod;")))
868 (setup '($integrate
(mPrprocess mPr-integrate
) (chchr "∫")))
870 (setup '(%integrate
(mPrprocess mPr-integrate
) (chchr "∫")))
872 (setup '($diff
(mPrprocess mPr-diff
) (chchr "<mo>ⅆ</mo>")))
874 (setup '(%derivative
(mPrprocess mPr-diff
) (chchr "<mo>ⅆ</mo>")))
876 (setup '($limit
(mPrprocess mPr-limit
)))
878 (setup '(%limit
(mPrprocess mPr-limit
)))
880 (setup '($sqrt
(mPrprocess mPr-sqrt
) (chchr "√")))
882 (setup '(%sqrt
(mPrprocess mPr-sqrt
) (chchr "√")))
884 (setup '(%binomial
(mPrprocess mPr-binomial
)))
886 (setup '(mquotient (mPrprocess mPr-quotient
) (mPr-lbp 122)
887 (mPr-rbp 123) (chchr "<mo>/</mo>")))
889 (setup '(rat (mPrprocess mPr-rat
) (mPr-lbp 120) (mPr-rbp 121)))
891 (setup '(mconc (mPrprocess mPr-infix
) (chchr " ")))
893 (setup '(mparen (chchr " ")))
895 (setup '(mbrak (chchr " ")))
897 (setup '(mequal (mPrprocess mPr-infix
) (mPr-lbp 80) (mPr-rbp 80)
900 ;;(setup '(mmsubs (mPrprocess mPr-mmsubs) (chchr "&")))
902 (setup '(mqapply (mPrprocess mPr-mqapply
)))
904 (setup '(mmfunct (mPrprocess mPr-funct
)))
906 (setup '($matrix
(mPrprocess mPr-matrix
)))
908 (setup '(lambda (mPrprocess mathml-presentation-lambda
)))
910 (setup '(%build_info
(mPrprocess mathml-presentation-buildinfo
)))
912 (setup '($%pi
(chchr "π")))
914 (setup '($%e
(chchr "ⅇ")))
916 (setup '($%gamma
(chchr "γ")))
918 (setup '($%phi
(chchr "φ")))
920 (setup '(& (chchr "&")))
922 (setup '(%
(chchr "%")))
924 (setup '($
(chchr "$")))
926 (setup '(_ (chchr "_")))
928 (setup '($minus
(chchr "-")))
930 (setup '($plus
(chchr "+")))
933 (setup '(mprog (chchr "block")))
935 (setup '($$block
(chchr "block")))
937 (setup '($$boldif
(chchr "if")))
939 (setup '($$boldthen
(chchr "then")))
941 (setup '($$boldelse
(chchr "else")))
944 ;;;; routines to access these fields
946 ;; The following are databases for special characters
948 (setf (get '$inf
'chchr
) '"∞")
949 ;;;(setf (get '$minf 'chchr) '"<mo>-</mo>∞")
951 ;; lower case greek database
953 (setf (get '$alpha
'chchr
) '"α")
954 (setf (get '%alpha
'chchr
) '"α")
955 (setf (get '$beta
'chchr
) '"β")
956 (setf (get '$gamma
'chchr
) '"γ")
957 (setf (get '%gamma
'chchr
) '"γ")
958 (setf (get '%gamma_incomplete
'chchr
) '"Γ")
959 (setf (get '%gamma_incomplete_generalized
'chchr
) '"Γ")
960 (setf (get '%gamma_incomplete_regularized
'chchr
) '"Q")
961 (setf (get '$gamma_incomplete_lower
'chchr
) '"γ")
962 (setf (get '$delta
'chchr
) '"δ")
963 (setf (get '$epsilon
'chchr
) '"ε")
964 (setf (get '$varepsilon
'chchr
) '"ϵ")
965 (setf (get '$zeta
'chchr
) '"ζ")
966 (setf (get '$eta
'chchr
) '"η")
967 (setf (get '$theta
'chchr
) '"θ")
968 (setf (get '$vartheta
'chchr
) '"ϑ")
969 (setf (get '$iota
'chchr
) '"ι")
970 (setf (get '$kappa
'chchr
) '"κ")
971 (setf (get '$lambda
'chchr
) '"λ")
972 (setf (get 'lambda
'chchr
) '"λ")
973 (setf (get '$mu
'chchr
) '"μ")
974 (setf (get '$nu
'chchr
) '"ν")
975 (setf (get '$xi
'chchr
) '"ξ")
976 (setf (get '$pi
'chchr
) '"π")
977 (setf (get '$varpi
'chchr
) '"ϖ")
978 (setf (get '$rho
'chchr
) '"ρ")
979 (setf (get '$varrho
'chchr
) '"ϱ")
980 (setf (get '$sigma
'chchr
) '"σ")
981 (setf (get '$varsigma
'chchr
) '"ς")
982 (setf (get '$tau
'chchr
) '"τ")
983 (setf (get '$upsilon
'chchr
) '"υ")
984 (setf (get '$phi
'chchr
) '"φ")
985 (setf (get '$varphi
'chchr
) '"ϕ")
986 (setf (get '$chi
'chchr
) '"χ")
987 (setf (get '$psi
'chchr
) '"ψ")
988 (setf (get '$omega
'chchr
) '"ω")
990 ;; Greek Upper Case Database
992 (setf (get '|$Alpha|
'chchr
) '"Α")
993 (setf (get '|$Gamma|
'chchr
) '"Γ")
994 (setf (get '|$Delta|
'chchr
) '"Δ")
995 (setf (get '|$Theta|
'chchr
) '"Θ")
996 (setf (get '|$Lambda|
'chchr
) '"Λ")
997 (setf (get '|$Xi|
'chchr
) '"Ξ")
998 (setf (get '|$Pi|
'chchr
) '"Π")
999 (setf (get '|$Sigma|
'chchr
) '"Σ")
1000 (setf (get '|$Upsilon|
'chchr
) '"Υ")
1001 (setf (get '|$Phi|
'chchr
) '"Φ")
1002 (setf (get '|$Psi|
'chchr
) '"Ψ")
1003 (setf (get '|$Omega|
'chchr
) '"Ω")
1004 (setf (get '|$Re|
'chchr
) '"ℜ")
1005 (setf (get '|$Im|
'chchr
) '"ℑ")
1007 ;; Miscellaneous symbols
1009 (setf (get '$aleph
'chchr
) '"ℵ")
1010 (setf (get '$hbar
'chchr
) '"ℏ")
1011 (setf (get '$%i
'chchr
) '"ⅈ")
1012 (setf (get '$%j
'chchr
) '"&ij")
1013 (setf (get '$ell
'chchr
) '"ℓ")
1014 (setf (get '$wp
'chchr
) '"℘")
1015 (setf (get '$mho
'chchr
) '"℧")
1016 (setf (get '$infty
'chchr
) '"&infty;")
1017 (setf (get '$nabla
'chchr
) '"∇")
1018 (setf (get '$partial
'chchr
) '"∂")
1019 (setf (get '$triangle
'chchr
) '"▵")
1022 (setup '(%sin
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sin")))
1023 (setup '(%cos
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cos")))
1024 (setup '(%tan
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"tan")))
1025 (setup '(%cot
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cot")))
1026 (setup '(%sec
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sec")))
1027 (setup '(%csc
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"csc")))
1029 (setup '(%asin
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arcsin")))
1030 (setup '(%acos
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arccos")))
1031 (setup '(%atan
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arctan")))
1032 (setup '(%acot
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acot")))
1033 (setup '(%asec
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asec")))
1034 (setup '(%acsc
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acsc")))
1035 (setup '(%sinh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sinh")))
1036 (setup '(%cosh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cosh")))
1037 (setup '(%tanh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"tanh")))
1038 (setup '(%coth
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"coth")))
1039 (setup '(%sech
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sec")))
1040 (setup '(%csch
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"csch")))
1043 (setup '(%asinh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asinh")))
1044 (setup '(%acosh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acosh")))
1045 (setup '(%atanh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"atanh")))
1046 (setup '(%acoth
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acoth")))
1047 (setup '(%asech
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asec")))
1048 (setup '(%acsch
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acsch")))
1050 (setup '(%ln
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"ln")))
1051 (setup '(%log
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"log")))
1053 (setup '($sin
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sin")))
1054 (setup '($cos
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cos")))
1055 (setup '($tan
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"tan")))
1056 (setup '($cot
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cot")))
1057 (setup '($sec
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sec")))
1058 (setup '($csc
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"csc")))
1060 (setup '($asin
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arcsin")))
1061 (setup '($acos
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arccos")))
1062 (setup '($atan
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"arctan")))
1063 (setup '($acot
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acot")))
1064 (setup '($asec
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asec")))
1065 (setup '($acsc
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acsc")))
1067 (setup '($sinh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sinh")))
1068 (setup '($cosh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"cosh")))
1069 (setup '($tanh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"tanh")))
1070 (setup '($coth
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"coth")))
1071 (setup '($sech
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"sec")))
1072 (setup '($csch
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"csch")))
1074 (setup '($asinh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asinh")))
1075 (setup '($acosh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acosh")))
1076 (setup '($atanh
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"atanh")))
1077 (setup '($acoth
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acoth")))
1078 (setup '($asech
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"asec")))
1079 (setup '($acsch
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"acsch")))
1080 (setup '($ln
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"ln")))
1081 (setup '($log
(mPrprocess mPr-function
) (mPr-rbp 110) (chchr"log")))
1082 (setup '(%gamma
(mPrprocess mPr-gamma
)))
1086 ;; set the preference feature
1089 (setq casep nil
) ;set to distinguish a capital or lower case
1090 (setq $mPrworksheet nil
) ;set TeX worksheet mode false
1091 (setq $lamPrworksheet nil
) ;set LaTeX worksheet mode false
1092 (setq $mPrlabelleft nil
) ;set Tex or LaTeX left Labeling mode false
1093 (setq $mPrdisplaytype t
) ;set default for TeX or LaTeX in display type
1094 (setq $mPrevaluate t
) ;set default for evaluating macsyma expression
1095 (setq $mPrautolabel nil
) ;set autolabel mode off, can be set to be integer
1096 (setq $lamPrautolabel nil
) ;set LaTeX autolabel mode false
1098 ;; The MathML presentation code has been loaded. Run each post-load hook. This
1099 ;; let other libraries hook in to the MathML library easily (doing so needs
1100 ;; SETUP and MPR_ENGINE to be defined).
1102 ;; Each hook should be an idempotent thunk.
1104 (when (boundp '*mathml-presentation-hook
*)
1105 (dolist (hook (symbol-value '*mathml-presentation-hook
*))