Fix #4398: Fix arg order to calls to laptimes
[maxima.git] / share / affine / amacros.lisp
blobf27bd050430375051c03d60edd9fc3f92676277f
1 ;;; -*- Mode:Lisp; Package:CL-MAXIMA; Syntax:COMMON-LISP; Base:10 -*-
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; ;;;;;
4 ;;; Copyright (c) 1984 by William Schelter,University of Texas ;;;;;
5 ;;; All rights reserved ;;;;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 (in-package :maxima)
10 (defmacro iassert (expr)
11 `(cond ((null ,expr) (fsignal "The expression ~A was not true" ',expr))))
13 (defun alphagreatp (x y)
14 (and (not (alphalessp x y)) (not (equal x y))))
16 (defun $monomial_alphalessp (x y)
17 (cond ((atom x)
18 (cond ((atom y) (alphalessp x y))
19 ((null (cdr y)) (alphalessp x (car y) ))
20 ; x<x.z , x< x.*
21 ((eql x (cadr y)))
22 (t (alphalessp x (cadr y)))))
23 ((atom y)
24 (cond ((null (cdr x)) (alphalessp (car x) y)) ;x cannot be an atom here
25 (t (alphalessp (cadr x) y))))
27 (alphalessp (cdr x) (cdr y)))))
29 (defun $monomial_alphagreatp (x y)
30 (not (or (equal x y) ($monomial_alphalessp x y))))
32 (defun $power_series_monomial_alphalessp (x y)
33 (cond ((equal x y) nil)
35 (let ((x-deg ($nc_degree x :order-weight))(y-deg ($nc_degree y :order-weight)))
36 (cond ((eql x-deg y-deg)($monomial_alphalessp x y))
37 ((zerop y-deg) (not (zerop x-deg)))
38 ((zerop x-deg) nil)
39 ((> x-deg y-deg) t)
40 (t nil))))))
42 (defun $polynomial_monomial_alphalessp (x y)
43 (cond ((equal x y) nil)
45 (let ((x-deg ($nc_degree x :order-weight))(y-deg ($nc_degree y :order-weight)))
46 (cond ((eql x-deg y-deg)($monomial_alphalessp x y))
47 ((zerop x-deg) (not (zerop y-deg)))
48 ((zerop y-deg) nil)
49 ((< x-deg y-deg) t)
50 (t nil))))))
52 (defun fix-optional (args &aux (tem (copy-list args)))
53 (loop for v on tem
54 for i from 0
55 when (member (car v) '(&optional &key))
56 do (loop for w on (cdr v)
57 until (and (atom (car w)) (search "&" (string (car w)) :test #'char-equal))
58 when (atom (car w))
59 do (setq tem (car w))
60 else do (setq tem (caar w))
61 when (eq (car v) '&key)
62 collecting (intern (string-upcase (string tem)) 'keyword) into opts
63 collecting tem into opts
64 finally
65 (setq args (append (subseq args 0 i) opts (cdr w)))(return 'done))
66 (return 'done))
67 args)
69 (defun delete-from-&aux (list)
70 (loop for u in list
71 for i from 1
72 when (eq u '&aux) do (return (subseq list 0 (1- i)))
73 finally (return list)))
75 (defun clear-memory-function (f &aux tem)
76 (cond ((setq tem (get f ':memory-table))
77 (clrhash tem))))
79 (defmacro defremember (func-spec arglist &rest body
80 &aux hash-args hash-put-args (call-arglist (copy-list arglist)))
81 "Like defun but defines function foo that remembers previous calls to
82 it it unless the calls were made while (disable-remember foo) until
83 (enable-remember foo) is done. To clear memory do (clear-hash (get 'foo
84 :memory-table)) . Redefining clears memory. The equal-hash table is
85 stored as the :memory-table property of foo. also it is useful to
86 use as optional arguments of global variables or other data not
87 included in the arguments upon which the function call depends. These
88 will then become part of the argument."
90 (cond ((get func-spec :memory-table)
91 (clrhash (get func-spec :memory-table))))
92 (remprop func-spec :dont-remember)
93 ;; (show call-arglist)
95 (setq call-arglist (fix-optional(delete-from-&aux call-arglist)))
96 (cond ((member '&aux call-arglist :test #'eq)
97 (format t "~%It is inadvisable to use &aux with defremember")))
98 ;; (show call-arglist)
99 (cond ((equal (length arglist) 1)(setq hash-put-args (setq hash-args (car arglist))))
100 ((equal (car arglist) '&rest) (setq hash-args (second arglist))
101 (setq hash-put-args `(copy-list ,(second arglist)))
102 (setq call-arglist (second arglist)))
103 ((member '&rest arglist :test #'eq) (setq hash-args `(list ,@ (DELETE '&rest call-arglist)))
104 (setq hash-put-args (copy-list hash-args))
105 (setf (nth (1- (length hash-put-args)) hash-put-args)
106 `(copy-list ,(car (last hash-put-args)))))
107 (t (setq hash-put-args (setq hash-args (cons 'list call-arglist)))))
108 `(defun ,func-spec ,arglist
109 (cond ((null (get ',func-spec :dont-remember))
110 (let (hash-table ans)
111 (cond ((setq hash-table (get ',func-spec :memory-table))
112 (cond ((setq ans (gethash ,hash-args hash-table)) ans)
113 (t (setq ans (progn ,@ body))
114 (setf (gethash ,hash-put-args hash-table) ans)
115 ans)))
116 (t (setf (get ',func-spec :memory-table)
117 (make-hash-table :test 'equal)
119 ,(cond ((member '&rest arglist :test #'eq)
120 `(apply ',func-spec ,@
121 ` ,(DELETE '&rest
122 (copy-list call-arglist))))
123 (t `(,func-spec ,@ call-arglist)))))))
124 (t (progn ,@ body)))))
126 (defmacro disable-remember (f)
127 `(putprop ',f t :dont-remember))
129 (defmacro enable-remember (f)
130 `(remprop ',f :dont-remember))
132 (defmacro function-let (alist &body body &aux sym)
133 (loop for v in alist
134 for i from 1
135 do (setq sym (gensym))
136 collecting sym into locals
137 collecting `(setq ,sym (symbol-function ',(first v))) into initial
138 collecting `(setf (symbol-function ',(first v))
139 (symbol-function ',(second v))) into initial
140 collecting `(cond (,sym (setf (symbol-function ',(first v)) ,sym))) into protects
141 finally (return `(let ,locals
142 (unwind-protect
143 (progn ,@ initial
144 ,@ body)
145 ,@ protects)))))
147 (defmacro with-no-query (&rest body)
148 `(function-let ((fquery no-query-aux)) ,@body))
150 (defmacro with-no-query-answer-no (&rest body)
151 `(function-let ((fquery (lambda (ignore ctrl &rest args) (apply 'format t ctrl args ) nil))) ,@body))
153 (defmacro find-minimal (in-list ordering &optional such-that ind)
154 (cond (such-that
155 (cond ((functionp such-that)(setq ind '-ind-)
156 (setq such-that `(,such-that -ind-)))
158 (check-arg ind (not (null ind)) "non nil. Must specify index")))
159 ` (loop for ,ind in ,in-list
160 with prev-min
161 when ,such-that
162 do (cond (prev-min
163 (cond ((funcall ,ordering ,ind prev-min)
164 (setq prev-min ,ind))))
165 (t (setq prev-min ,ind)))
166 finally (return prev-min)))
167 (t `(loop for v in ,in-list
168 with prev-min
169 do (cond (prev-min
170 (cond ((funcall , ordering v prev-min)
171 (setq prev-min v))))
172 (t (setq prev-min v)))
173 finally (return prev-min)))))
175 (defmacro user-supply (var)
176 `(setq ,var (user-supply1 ',var ,var)))
178 (defun user-supply1 (var val)
179 (let ((*print-level* 3)
180 .new.
181 .ch.)
182 (loop do
183 (format t "~%The value of ~A is ~A ." var val)
184 (format t "~%Supply a form to evaluate to use for ~A or hit return to keep same :" var)
185 (setq .ch. (read-char *standard-input*))
186 (cond ((eql .ch. #\newline)
187 (return val))
188 (t (unread-char .ch. *standard-input*)))
189 (setq .new. (eval (read)))
190 (cond ((eq .new. 'keep)
191 (return var))
193 (format t "~%Use ~A?" .new.)
194 (cond ((y-or-n-p)
195 (return (setq var .new.)))))))))
197 (defvar *timed-process-priority* 1)
199 (defmacro tim (&rest body)
200 `(time (progn ,@body)))
202 ;;Idea is that you have two function definitions possibly with the
203 ;;same name, and lots of places where the first one is called.
204 ;;you may want to replace the first function with the second one
205 ;;and think you have the definition correct. You want to compare
206 ;;the speed and whether they work the same. So wrap
207 ;;compare-functions around the two definitions, then it will compare
208 ;;them as to speed (and value) in the applications. It might be reasonable to implement
209 ;;this as an emacs macro wrapping it around a region.
211 (defmacro compare-functions (defa defb &rest assertions)
212 (let (.fa. .fb.
213 .boda. .bodb.
214 (.assert. (loop for v in assertions
215 collecting `(iassert ,v) into tem
216 finally
217 (return (cons `(iassert (equal .ansa. .ansb.)) tem)))))
218 (check-arg defa (eq (car defa) 'defun) "Should be a defun")
219 (cond ((atom defb)
220 (setq defb `(defun ,(string-append defb (symbol-name '#:-compare)) (&rest .l.)
221 (apply ',defb .l.)))))
222 (setq .fa. (intern (string-append (second defa) (symbol-name '#:-a))))
223 (setq .fb. (intern (string-append (second defb) (symbol-name '#:-b))))
224 (setq .boda. (subst .fa. (second defa) (cdddr defa)))
225 (setq .bodb. (subst .fb. (second defb) (cdddr defb)))
226 `(progn
227 (defun , .fa. ,(third defa)
228 (tim ,@ .boda. ))
229 (defun , .fb. ,(third defb)
230 (tim ,@ .bodb.))
231 (defun ,(second defa)
232 (&rest l)
233 (declare (arglist ,. (loop for v in (third defa)
234 until (eq v '&aux) collecting v)))
235 (let (.ansa. .ansb.)
236 (format t "~%Comparing the functions ~A and ~A " ', .fa. ', .fb.)
237 (setq .ansa.
238 (multiple-value-list (apply ', .fa. (copy-list l))))
239 (setq .ansb. (multiple-value-list (apply ', .fb. (copy-list l))))
240 ,@ .assert.
241 (apply 'values .ansa.))))))
243 (defmacro compare-recursive-functions (fn-a fn-b &rest assertions)
244 `(progn
245 ,fn-a
246 ,fn-b
247 , `(compare-functions
248 (defun ,(intern (string-append (second fn-a) (symbol-name '#:-compare))) ,@ (cddr fn-a))
249 (defun ,(intern (string-append (second fn-b) (symbol-name '#:-compare))) ,@ (cddr fn-b))
250 ,@ assertions)))
252 ;;sample usage of compare-recursive-functions
253 ;(compare-recursive-functions
254 ; (defun my-pgcd (f g) ...
255 ; ...
256 ; (my-pgcd (cof f) ..))
257 ; (defun pgcd (f g)
258 ; ...)
261 ;;then to invoke the comparison call
262 ;;(my-pgcd-compare u v) and it will calculate the gcd using the two methods check they
263 ;;are equal (or check other assertions you specify) and print the time spent
264 ;;in my-pgcd-compare-a and in my-pgcd-compare-b
266 ;(compare-functions
267 ;(defun ff (u &optional v)
268 ; (values (+ u v) ))
273 ;(compare-functions
274 ;(defun ff (u &optional v)
275 ; (values (+ u v) u))
276 ;(defun ff (u &optional v)
277 ; (values (+ v u) v))
279 ;;then if you run some functions that call ff it will give the comparison
280 ;;note that ff and gg may have the same name
281 ;(defun test (c d)
282 ; (ff c d))
284 (defun write-object (filename obj)
285 (with-open-file (st filename :direction :output)
286 (format st "~A" obj)))
288 (defstruct (s-var (:type list) :named (:conc-name sv-))
289 zopens) ;; list of open sets
291 (defmacro set-slots (struct conc-prefix &rest alt-list)
292 (loop for v on alt-list by #'cddr
293 collecting `(setf ( ,(intern (format nil "~a~a" conc-prefix (car v))) ,struct) ,(second v))
294 into tem
295 finally (return (cons 'progn tem))))
297 ;; Note that ZL-COPY-STRUCTURE works only for structures which are
298 ;; represented by lists. The `ZL' is just for analogy with other private
299 ;; versions of list related functions in Maxima and no reference to any
300 ;; historical version of Lisp is intended.
301 (defmacro zl-copy-structure (struct conc-prefix &rest alt-list)
302 ` (let (( .ans. (copy-list ,struct)))
303 (set-slots .ans. ,conc-prefix ,@ alt-list)
304 .ans.))
306 ;(defstruct (s-var (:type list ) :named (:conc-name sv-))
307 ; zopens ;; list of open sets
308 ; ;; a list of opens each having its intersection slot specified
309 ; intersections
310 ; ;;glueing: for each element of the intersections will have a
311 ; ;;a list of maps between elements of intersections
312 ; ;;so that the map from that element to the reverse intersection
313 ; glueing
316 (defstruct (pre-ldata-sheaves (:type list ) :named (:conc-name pls-))
317 s-var
318 ;;for each open a list of ldata
319 data)
321 (defstruct (ldata (:type list ) :named (:conc-name ldata-))
322 eqns
323 (inequality 1)
324 (usedup 0)
325 (open-inequality 1)
326 variables)
328 (defstruct (rmap (:type list ) :named (:conc-name rmap-))
330 denom)
332 (defstruct (zopen (:type list) :named (:conc-name zopen-))
333 ;;coord is an r-map
334 coord
335 ;;inv is an r-map
337 inequality
338 history)
340 (defstruct (variable-correspondence :named (:conc-name vc-))
341 genvar
342 varlist
343 add-method)
345 (defstruct (ideal :named (:conc-name ideal-))
346 char-set
347 generators
348 localization
349 variable-correspondence)
351 (defstruct ( polynomial-vectors :named (:conc-name pv-))
352 length-of-array-of-tables
353 rows
354 (constants-column-number nil)
355 (relations nil)
356 (type-of-entries :integer)
357 (variables nil)
358 (verify-conversion nil)
359 array-of-polynomials
360 array-of-tables
361 last-column-number
362 number-of-independent-terms ;;never occurs
363 solution-in-macsyma-format
364 table
365 the-sparse-matrix
366 type-of-polynomials
367 solution-plist
370 (defstruct (poly-data :named (:conc-name pd-))
371 rows
372 sparse-matrix
373 segments ;;beginning of each new group of monoms in big-monom-list
374 big-monom-list)
376 (defmacro gshow (form)
377 `(progn (format t "~%The value of ~A is" ',form)
378 (grind-top-level ,form)))
380 (defmacro mshow (&rest l)
381 (loop for v in l
382 collecting `(format t "~%The value of ~A is.. " ',v) into tem
383 collecting `(des ,v) into tem
384 finally (return (cons 'progn tem))))
386 (defmacro ncmul* (&rest factors)
387 (cond ((= (length factors) 2) `(ncmul2* . ,factors))
388 (t `(ncmuln (list . ,factors) nil))))
390 (defstruct (matrix (:type list) :named (:conc-name matrix-))
391 rows) ;; list of open sets
393 ;(defmacro matrix-p (mat)
394 ; `(and (listp ,mat) (eq (car ,mat) 'matrix)))
396 (defvar *verbose-check-overlaps* nil)
398 (defmacro if-verbose (&rest l)
399 `(when *verbose-check-overlaps* ,@l))