1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1981 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module nforma
)
15 (defmvar $exptdispflag t
)
16 (defmvar $negsumdispflag t
)
20 (defun nformat (form &aux
(p nil
))
22 (cond ((and (realp form
) (minusp form
) (not (float-inf-p form
))) (list '(mminus) (- form
)))
23 ((eq t form
) (if in-p t
'$true
))
24 ((eq nil form
) (if in-p nil
'$false
))
25 ;; revision, extension by Richard Fateman 3/2013.
26 ;; Perhaps some object is an atom, maybe a CLOS object or structure.
27 ;; Either its type is a symbolp..
28 ;; e.g. a structure like (defstruct (ri ...)) is type ri.
29 ;; so we look for a formatter on the type or car of the type.
31 ;; if car of the type is also not a symbol, we look for formatter on nil
33 ;; depending on the lisp, type-of may be more or less sophisticated.
35 ;; may return a list, e.g. (type-of "abc") is (simple-array character (3))
36 ;; in some lisps, e.g. GCL the type is just string.
38 ((and (setf p
(type-of form
))
39 (if (not (symbolp p
)) (setf p
(car p
)) p
)
40 (setf p
(get (and (symbolp p
) p
) 'formatter
))
41 ;; form is an atom of a type with a formatter property
43 ;; just display as a lisp symbol, number, or other atom.
45 ((atom (car form
)) form
) ;; probably an illegal form; just return it.
47 ;; Process FORM if it is simplified or has some other operator flag (e.g., TRUNC)
48 ;; (ignoring line number annotations). Otherwise, return FORM unchanged.
49 ((let ((foo (cdar form
)))
50 (or (null foo
) ;; no CAR flags at all
51 ;; only item in CAR is line number annotation
52 ;; (is it worth the trouble to find a faster way to test that?)
53 (and (eql (length foo
) 1) (let ((bar (first foo
))) (and (consp bar
) (equal (last bar
) '(src)))))))
56 ;; this next section is for the ordinary maxima objects that are tagged by
57 ;; their main operator or CAAR, e.g. ((mplus) a b) has CAAR mplus ...
58 ((and (symbolp (caar form
)) (setf p
(get (caar form
) 'formatter
))) ;; find the formatter. If there is one, call it.
60 (t form
))) ; if there is no formatter. Just return form unchanged.
63 (defun form-mplus (form &aux args trunc simplified
)
64 (setq args
(mapcar #'nformat
(cdr form
)))
65 (setq trunc
(member 'trunc
(cdar form
) :test
#'eq
))
66 (setq simplified
(member 'simp
(cdar form
) :test
#'eq
))
67 (cons (if trunc
'(mplus trunc
) '(mplus))
68 (cond ((and (member 'ratsimp
(cdar form
) :test
#'eq
)
69 (not (member 'simp
(cdar form
) :test
#'eq
)))
70 (if $powerdisp
(nreverse args
) args
))
71 ((and trunc
(not (member 'simp
(cdar form
) :test
#'eq
))) (nreverse args
))
72 ((or $powerdisp trunc
(member 'cf
(cdar form
) :test
#'eq
)) args
)
73 ((and $negsumdispflag
(null (cdddr form
)))
74 (if (and (not (mmminusp (car args
)))
75 (mmminusp (cadr args
)))
77 (if simplified
(nreverse args
) args
)))
78 (t (if simplified
(nreverse args
) args
)))))
80 (defun form-mtimes (form)
81 (cond ((null (cdr form
)) '((mtimes)))
82 ((equal -
1 (cadr form
)) (list '(mminus) (form-mtimes (cdr form
))))
83 (t (prog (num den minus flag
)
84 (do ((l (cdr form
) (cdr l
)) (dummy)) ((null l
))
85 (setq dummy
(nformat (car l
)))
86 (cond ((atom dummy
) (setq num
(cons dummy num
)))
87 ((eq 'mminus
(caar dummy
))
88 (setq minus
(not minus
) l
(append dummy
(cdr l
))))
89 ((or (eq 'mquotient
(caar dummy
))
90 (and (not $pfeformat
) (eq 'rat
(caar dummy
))))
91 (cond ((not (equal 1 (cadr dummy
)))
92 (setq num
(cons (cadr dummy
) num
))))
93 (setq den
(cons (caddr dummy
) den
)))
94 (t (setq num
(cons dummy num
)))))
95 (setq num
(cond ((null num
) 1)
96 ((null (cdr num
)) (car num
))
97 (t (cons '(mtimes) (nreverse num
))))
98 den
(cond ((null den
) (setq flag t
) nil
)
99 ((null (cdr den
)) (car den
))
100 (t (cons '(mtimes) (nreverse den
)))))
101 (if (not flag
) (setq num
(list '(mquotient) num den
)))
102 (return (if minus
(list '(mminus) num
) num
))))))
104 (defun form-mexpt (form &aux exp
)
105 (cond ((and $sqrtdispflag
(alike1 1//2 (caddr form
))) (list '(%sqrt
) (cadr form
)))
106 ((and $sqrtdispflag
(alike1 -
1//2 (caddr form
)))
107 (list '(mquotient) 1 (list '(%sqrt
) (cadr form
))))
108 ((and (or (and $%edispflag
(eq '$%e
(cadr form
)))
109 (and $exptdispflag
(not (eq '$%e
(cadr form
)))))
110 (not (atom (setq exp
(nformat (caddr form
)))))
111 (eq 'mminus
(caar exp
)))
112 (list '(mquotient) 1 (if (equal 1 (cadr exp
)) (cadr form
)
113 (list '(mexpt) (cadr form
) (cadr exp
)))))
114 (t (cons '(mexpt) (cdr form
)))))
116 (defun form-mrat (form)
117 (let ((trunc (member 'trunc
(cdar form
) :test
#'eq
)) exact
)
118 (if (and trunc
(eq (cadr form
) 'ps
))
119 (setq exact
(null (car (cadddr form
)))))
120 (setq form
(ratdisrepd form
))
122 (if (and trunc
(or (atom form
)
123 ;; A constant, e.g. ((mplus) $a 1)
124 (not (member (car form
) '((mplus exact
) (mplus trunc
)) :test
#'equal
))))
125 (cons (if exact
'(mplus exact
) '(mplus trunc
)) (ncons form
))
129 (cond ((or (atom form
) (specrepp form
)))
130 ((null (cdar form
)) (rplaca form
(list (caar form
) 'ratsimp
)))
131 (t (mapc #'rdis1
(cdr form
)))))
133 (defun nformat-all (form)
134 (setq form
(nformat form
))
136 (member (caar form
) '(bigfloat rat
))) ;can't recurse over cdrs
138 (cons (delsimp (car form
))
139 (if (member (caar form
) '(mdo mdoin
))
140 (mapcar #'(lambda (u) (if u
(nformat-all u
))) (cdr form
))
141 (mapcar #'nformat-all
(cdr form
))))))
143 ;;; we should define all the formatters in the file after the helper functions like form-mplus
145 (setf (get 'rat
'formatter
)
146 #'(lambda(form)(cond ((minusp (cadr form
))
147 (list '(mminus) (list '(rat) (- (cadr form
)) (caddr form
))))
148 (t (cons '(rat) (cdr form
))))))
150 (setf (get 'mmacroexpanded
'formatter
)
151 #'(lambda(form)(nformat (caddr form
))))
153 (setf (get 'mplus
'formatter
) 'form-mplus
)
154 (setf (get 'mtimes
'formatter
) 'form-mtimes
)
155 (setf (get 'mexpt
'formatter
) 'form-mexpt
)
156 (setf (get 'mrat
'formatter
) 'form-mrat
)
157 (setf (get 'mpois
'formatter
) #'(lambda(form)(nformat ($outofpois form
))))
159 (setf (get 'bigfloat
'formatter
)
161 (if (minusp (cadr form
))
162 (list '(mminus) (list (car form
) (- (cadr form
)) (caddr form
)))
163 (cons (car form
) (cdr form
)))))
165 (setf (get 'ratio
'formatter
) ;; in case a common lisp ratio is returned somehow.
168 (list '(mminus) (list '(rat) (- (numerator form
)) (denominator form
))))
169 (t (list '(rat) (numerator form
)(denominator form
))))))
171 (setf (get 'complex
'formatter
) ;; in case a common lisp complex number is returned somehow.
174 (nformat `((mplus) ,(realpart form
)
175 ((mtimes) ,(imagpart form
) $%i
)))
176 ;; some random form with caar COMPLEX
177 ;;not really a CL complex
179 #+gcl
(setf (get 'si
::complex
* 'formatter
) (get 'complex
'formatter
))
181 ;; something I added for fun
182 ;; (defstruct (ri (:constructor $interval (lo hi) ))lo hi)
183 ;; (setf (get 'ri 'formatter) ;; in case a structure of type ri [real interval] is computed
184 ;; #'(lambda(r) (list '($interval simp) (ri-lo r)(ri-hi r)))) ;; this prints it.
186 ;; so in maxima, we can construct ri structures by typing interval(1,2)
187 ;; and if we display it, it appear as interval(1,2).
188 ;; but ?print(interval(1,2)) shows the lisp value which is the structure,
189 ;; #s(ri :lo 1 :hi 2).
191 ;; we could set up formatters for , say, (simple-array single-float <dimensions>)
192 ;; or share the burden with display program .