Skip to content

Commit b63cd4a

Browse files
TomasRikerrtoy
authored andcommitted
Make MAXMINL a macro, add in-place option and use it
- MAXMINL is turned into a macro to avoid having to check in the innermost loop (many times) whether we're doing MAX or MIN. - MAXMINL gets an optional IN-PLACE argument. If non-NIL, it destructively modifies the first sublist to contain the result. - Define MAXLIST-IN-PLACE and MINLIST-IN-PLACE as in-place variants of MAXLIST and MINLIST. - The only places where MAXLIST and MINLIST are used operate on freshly constructed lists that are not used afterwards, so it's safe to use the in-place variants. This reduces memory usage ("consed bytes") of the test suite by ~3.5% and runtime by ~0.5% (SBCL).
1 parent 128c086 commit b63cd4a

2 files changed

Lines changed: 26 additions & 16 deletions

File tree

src/factor.lisp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,8 @@
411411
loop (cond ((null c) (return ans)))
412412
(setq ans
413413
(nconc (degvector (cons (car c) lf) (1+ j) (cadr c)) ans))
414-
(cond (*mx* (setq ans (ncons (maxlist ans))))
415-
(*min* (setq ans (ncons (minlist ans)))))
414+
(cond (*mx* (setq ans (ncons (maxlist-in-place ans))))
415+
(*min* (setq ans (ncons (minlist-in-place ans)))))
416416
(setq c (cddr c))
417417
(go loop)))
418418

src/rat3d.lisp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,33 +66,43 @@
6666
(list tcont (pquotient p tcont))))
6767

6868
(defun pmindegvec (p)
69-
(minlist (let ((*odr* (putodr (reverse genvar)))
69+
(minlist-in-place
70+
(let ((*odr* (putodr (reverse genvar)))
7071
(nn* (1+ (length genvar)))
7172
(*min* t))
7273
(degvector nil 1 p))))
7374

7475
(defun pdegreevector (p)
75-
(maxlist (let ((*odr* (putodr (reverse genvar)))
76+
(maxlist-in-place
77+
(let ((*odr* (putodr (reverse genvar)))
7678
(nn* (1+ (length genvar)))
7779
(*mx* t))
7880
(degvector nil 1 p))))
7981

82+
(defmacro maxminl (l do-max &optional in-place)
83+
"Given a list of lists ((A1 ... An) (B1 ... Bn) (C1 ... Cn) ...), which should
84+
all have the same length and contain REAL numbers, MAXMINL returns a list
85+
((OP A1 B1 C1 ...) (OP A2 B2 C2 ...) ... (OP An Bn Cn ...)), where OP is either
86+
MAX (when DO-MAX is non-NIL) or MIN.
87+
If IN-PLACE is non-NIL, the first sublist will be destructively modified
88+
to contain the result."
89+
(let ((op (if do-max '> '<)))
90+
`(do ((l1 ,(if in-place '(car l) '(copy-list (car l))))
91+
(ll (cdr l) (cdr ll)))
92+
((null ll) l1)
93+
(do ((v1 l1 (cdr v1))
94+
(v2 (car ll) (cdr v2)))
95+
((null v1))
96+
(when (,op (car v2) (car v1))
97+
(rplaca v1 (car v2)))))))
98+
8099
(defun maxlist(l) (maxminl l t))
81100

101+
(defun maxlist-in-place(l) (maxminl l t t))
102+
82103
(defun minlist(l) (maxminl l nil))
83104

84-
(defun maxminl (l switch)
85-
(do ((l1 (copy-list (car l)))
86-
(ll (cdr l) (cdr ll)))
87-
((null ll) l1)
88-
(do ((v1 l1 (cdr v1))
89-
(v2 (car ll) (cdr v2)))
90-
((null v1))
91-
(cond (switch
92-
(cond ((> (car v2) (car v1))
93-
(rplaca v1 (car v2)))))
94-
(t (cond ((< (car v2) (car v1))
95-
(rplaca v1 (car v2)))))))))
105+
(defun minlist-in-place(l) (maxminl l nil t))
96106

97107
(defun quick-sqfr-check (p var)
98108
(let ((gv (delete var (listovars p) :test #'equal))

0 commit comments

Comments
 (0)