2 (in-package :lineal.overload
)
4 (defun over-cat (&rest args
)
7 (reduce #'cat2 args
:from-end t
)
9 (throw 'over-ex
"Can't cat nothing.")))
11 (defun over-vcat (&rest args
)
14 (reduce #'vcat2 args
:from-end t
)
16 (throw 'over-ex
"Can't vcat nothing.")))
18 ;V The do* macro with tails.V
20 (((&body tails-args
) . do-args
)
21 (s-pred . s-cleanup
) . s-proc
)
22 (let ((begin-loop-tag (gensym))
23 (end-loop-tag (gensym))
30 :for
(v a ta condit
) :in tails-args
31 ;V See if /v/ has an initial value.V
32 :for init-v
= (when (consp v
)
36 ;V Find if the tail should be V
37 ;V initialized as something. V
41 (cadr (shiftf ta
(car ta
)))
43 ;V No tail mentioned by user, set /ta/ V
44 ;V as a symbol name and return nil. V
46 ;> /ta/ is now strictly the variable name referring to the
47 ;> accum-list's tail. There is always a tail at this point.
48 ;V Find what the accum-list is initialized with V
49 ;V and what its part of the /post-inits/ looks like.V
50 :for
(adef a-init-part
) =
52 (list (when a
(cadr (shiftf a
(car a
))))
53 ;^ If /a/ is a cons, set it to its symbol ^
54 ;^ name and return its initialization form.^
56 `(if ,a
(cdr (rplacd (last ,a
) (cons ,v nil
)))
57 (setq ,a
(list ,v
)))))
58 ;V The accum-list does not have an init value, V
59 ;V but will be initialized in the beginning let.V
60 `(nil (setq ,a
(cons ,v nil
))))
61 ;> /a/ is now strictly the variable name referring to the
62 ;> accum-list or nil if the list exists before this macro.
63 :for default-val-setq
=
67 (cons v
(cdr condit
)))
69 ;V Collect variables and initializations V
70 ;V to be used in the outer let form. V
71 :collect
(if init-v
(list v init-v
) v
) :into vlist
73 :collect
(if adef
(list a adef
) a
) :into vlist
74 :collect
(if tadef
(list ta tadef
) ta
) :into vlist
75 ;V The stuff for /post-inits/.V
77 `(,ta
,(if tadef
`(cdr (rplacd ,ta
,a-init-part
))
81 :nconc default-val-setq
:into ilist
83 `(if ,(if (consp condit
) (car condit
) v
)
84 (setq ,ta
(cdr (rplacd ,ta
(cons ,v nil
)))
88 `(,ta
(cdr (rplacd ,ta
(cons ,v nil
))))
90 :finally
(setq pre-inits vlist
92 s-conditail-setqs condlist
94 ;V Handle regular do arguments.V
95 (loop :for
(v i a
) :in do-args
96 :collect
(if i
(list v i
) v
) :into vlist
97 :when a
:collect v
:into alist
98 :and
:collect a
:into alist
99 :finally
(nconc pre-inits vlist
)
100 (setq do-setqs alist
))
101 (loop :while
(and (consp (car s-proc
))
102 (eq 'declare
(caar s-proc
)))
103 :collect
(pop s-proc
) :into decl
104 :finally
(setq s-declarations decl
))
105 `(let* (,@pre-inits
);< All variable initializations.
108 ;V Run loop contents here only if the first V
109 ;V value to accumulate is not specified. V
110 ,@(unless var-init-p s-proc
)
111 ;V Give all tails a value if they don't have one, V
112 (setq ,@post-inits
);< update some nil lists too.
115 (setq ,@do-setqs
);< Normal do-loop updates.
116 (if ,s-pred
(go ,end-loop-tag
))
117 ,@s-proc
;< Run inner loop.
118 ,@s-conditail-setqs
;< Conditional tail updates.
119 (setq ,@tail-setqs
);< Update all tails.
122 ;V Loop is over, run user's cleanup forms.V
136 (arem (gensym)) (brem (gensym))
139 (((,row
,rows
,tail
))
140 (,arem
,s-arows
(cdr ,arem
))
141 (,brem
,s-brows
(cdr ,brem
))
142 (,finished nil
(not (and ,arem
,brem
))))
147 (let* (,@(when s-bwidth
`((,width
,s-bwidth
)))
149 (mapcar #'(lambda (,arow
) ,s-cat
) ,arem
))
151 (let* (,@(when s-awidth
`((,width
,s-awidth
)))
153 (mapcar #'(lambda (,brow
) ,s-cat
) ,brem
)))))
155 (let ((,arow
(car ,arem
))
157 (setq ,row
,s-cat
)))))
160 (defmethod cat2 ((a number
) (b number
))
161 (make-mtrix :dimdom
2 :dimcodom
1
162 :elems
(list (list a b
))))
164 (defmethod vcat2 ((a number
) (b number
))
165 (make-tuple :dim
2 :elems
(list a b
)))
167 (defmethod cat2 ((k number
) (u tuple
))
168 (make-mtrix :dimdom
2 :dimcodom
(tuple-dim u
)
169 :elems
(mapcar #'(lambda (x) (list k x
))
172 (defmethod cat2 ((u tuple
) (k number
))
173 (make-mtrix :dimdom
2 :dimcodom
(tuple-dim u
)
174 :elems
(mapcar #'(lambda (x) (list x k
))
177 (defmethod vcat2 ((k number
) (u tuple
))
178 (make-tuple :dim
(1+ (tuple-dim u
))
179 :elems
(cons k
(tuple-elems u
))))
181 (defmethod vcat2 ((u tuple
) (k number
))
182 (make-tuple :dim
(1+ (tuple-dim u
))
183 :elems
`(,@(tuple-elems u
) ,k
)))
185 ;V Align two tuples into a column matrix.V
186 (defmethod cat2 ((u tuple
) (v tuple
))
188 ((uelem (tuple-elems u
))
189 (velem (tuple-elems v
))
192 (nil (nil 0) (nil 0))
193 (make-mtrix :dimdom
2
194 :dimcodom
(max (tuple-dim u
)
198 ;V Merge two tuples together into one long vector.V
199 (defmethod vcat2 ((u tuple
) (v tuple
))
200 (make-tuple :dim
(+ (tuple-dim u
) (tuple-dim v
))
201 :elems
(append (tuple-elems u
)
204 ;V Add a column vector /u/ to V
205 ;V the left side of matrix /a/.V
206 (defmethod cat2 ((u tuple
) (a mtrix
))
208 ((uelem (tuple-elems u
))
209 (arow (mtrix-elems a
))
215 (make-list width
:initial-element
0)))
216 (make-mtrix :dimdom
(1+ (mtrix-dimdom a
))
217 :dimcodom
(max (tuple-dim u
)
221 (defmethod cat2 ((a mtrix
) (u tuple
))
223 ((arow (mtrix-elems a
))
224 (uelem (tuple-elems u
))
229 (make-list width
:initial-element
0))
231 (make-mtrix :dimdom
(1+ (mtrix-dimdom a
))
232 :dimcodom
(mtrix-dimcodom a
)
235 (defmethod cat2 ((a mtrix
) (b mtrix
))
237 ((arow (mtrix-elems a
))
238 (brow (mtrix-elems b
))
243 (make-list width
:initial-element
0))
245 (make-list width
:initial-element
0)))
246 (make-mtrix :dimdom
(+ (mtrix-dimdom a
)
248 :dimcodom
(max (mtrix-dimcodom a
)
252 (defmethod vcat2 ((u tuple
) (a mtrix
))
253 (let ((uwid (tuple-dim u
))
254 (awid (mtrix-dimdom a
))
255 (rows (cons (tuple-elems u
)
261 (make-list (- awid uwid
)
262 :initial-element
0)))
263 (unless (= uwid awid
)
264 (shiftf awid uwid
(- uwid awid
))
271 (make-list uwid
:initial-element
0)))
273 (make-mtrix :dimdom awid
274 :dimcodom
(1+ (mtrix-dimcodom a
))
277 (defmethod vcat2 ((a mtrix
) (u tuple
))
278 (let ((awid (mtrix-dimdom a
))
279 (uwid (tuple-dim u
)))
281 :dimcodom
(1+ (mtrix-dimcodom a
))
285 ,(append (tuple-elems u
)
286 (make-list (- awid uwid
)
287 :initial-element
0)))
289 `(,@(mtrix-elems a
) ,(tuple-elems u
))
291 (shiftf awid uwid
(- uwid awid
))
294 (arem (mtrix-elems a
) (cdr arem
)))
296 (rplacd tail
(cons (tuple-elems u
) nil
))
302 uwid
:initial-element
0)))))))
305 ;V Join a column of /k/'s onto the left of /a/.V
306 (defmethod cat2 ((k number
) (a mtrix
))
308 :dimdom
(1+ (mtrix-dimdom a
))
309 :dimcodom
(mtrix-dimcodom a
)
310 :elems
(mapcar #'(lambda (row) (cons k row
))
313 ;V Join a column of /k/'s onto the right of /a/.V
314 (defmethod cat2 ((a mtrix
) (k number
))
316 :dimdom
(1+ (mtrix-dimdom a
))
317 :dimcodom
(mtrix-dimcodom a
)
318 :elems
(mapcar #'(lambda (row) `(,@row
,k
))
321 ;V Join a row of /k/'s onto the top of /a/.V
322 (defmethod vcat2 ((k number
) (a mtrix
))
324 :dimdom
(mtrix-dimdom a
)
325 :dimcodom
(1+ (mtrix-dimcodom a
))
326 :elems
(cons (make-list (mtrix-dimdom a
)
330 ;V Join a row of /k/'s onto the bottom of /a/.V
331 (defmethod vcat2 ((a mtrix
) (k number
))
333 :dimdom
(mtrix-dimdom a
)
334 :dimcodom
(1+ (mtrix-dimcodom a
))
335 :elems
`(,@(mtrix-elems a
)
336 ,(make-list (mtrix-dimdom a
)
337 :initial-element k
))))
339 (defmethod vcat2 ((a mtrix
) (b mtrix
))
340 (let* ((awid (mtrix-dimdom a
))
341 (bwid (mtrix-dimdom b
))
342 (finwid (max awid bwid
))
343 (zeros (make-list (abs (- awid bwid
))
344 :initial-element
0)))
347 :dimcodom
(+ (mtrix-dimcodom a
)
350 (if (= awid finwid
) (mtrix-elems a
)
351 (mapcar #'(lambda (row)
354 (if (= bwid finwid
) (mtrix-elems b
)
355 (mapcar #'(lambda (row)
357 (mtrix-elems b
)))))))