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 (defmethod cat2 ((u list
) v
)
19 (cat2 (tuple-list u
) v
))
21 (defmethod cat2 (u (v list
))
22 (cat2 u
(tuple-list v
)))
24 (defmethod vcat2 ((u list
) v
)
25 (vcat2 (tuple-list u
) v
))
27 (defmethod vcat2 (u (v list
))
28 (vcat2 u
(tuple-list v
)))
30 ;V The do* macro with tails.V
32 (((&body tails-args
) . do-args
)
33 (s-pred . s-cleanup
) . s-proc
)
34 (let ((begin-loop-tag (gensym))
35 (end-loop-tag (gensym))
42 :for
(v a ta condit
) :in tails-args
43 ;V See if /v/ has an initial value.V
44 :for init-v
= (when (consp v
)
48 ;V Find if the tail should be V
49 ;V initialized as something. V
53 (cadr (shiftf ta
(car ta
)))
55 ;V No tail mentioned by user, set /ta/ V
56 ;V as a symbol name and return nil. V
58 ;> /ta/ is now strictly the variable name referring to the
59 ;> accum-list's tail. There is always a tail at this point.
60 ;V Find what the accum-list is initialized with V
61 ;V and what its part of the /post-inits/ looks like.V
62 :for
(adef a-init-part
) =
64 (list (when a
(cadr (shiftf a
(car a
))))
65 ;^ If /a/ is a cons, set it to its symbol ^
66 ;^ name and return its initialization form.^
68 `(if ,a
(cdr (rplacd (last ,a
) (cons ,v nil
)))
69 (setq ,a
(list ,v
)))))
70 ;V The accum-list does not have an init value, V
71 ;V but will be initialized in the beginning let.V
72 `(nil (setq ,a
(cons ,v nil
))))
73 ;> /a/ is now strictly the variable name referring to the
74 ;> accum-list or nil if the list exists before this macro.
75 :for default-val-setq
=
79 (cons v
(cdr condit
)))
81 ;V Collect variables and initializations V
82 ;V to be used in the outer let form. V
83 :collect
(if init-v
(list v init-v
) v
) :into vlist
85 :collect
(if adef
(list a adef
) a
) :into vlist
86 :collect
(if tadef
(list ta tadef
) ta
) :into vlist
87 ;V The stuff for /post-inits/.V
89 `(,ta
,(if tadef
`(cdr (rplacd ,ta
,a-init-part
))
93 :nconc default-val-setq
:into ilist
95 `(if ,(if (consp condit
) (car condit
) v
)
96 (setq ,ta
(cdr (rplacd ,ta
(cons ,v nil
)))
100 `(,ta
(cdr (rplacd ,ta
(cons ,v nil
))))
102 :finally
(setq pre-inits vlist
104 s-conditail-setqs condlist
106 ;V Handle regular do arguments.V
107 (loop :for
(v i a
) :in do-args
108 :collect
(if i
(list v i
) v
) :into vlist
109 :when a
:collect v
:into alist
110 :and
:collect a
:into alist
111 :finally
(nconc pre-inits vlist
)
112 (setq do-setqs alist
))
113 (loop :while
(and (consp (car s-proc
))
114 (eq 'declare
(caar s-proc
)))
115 :collect
(pop s-proc
) :into decl
116 :finally
(setq s-declarations decl
))
117 `(let* (,@pre-inits
);< All variable initializations.
120 ;V Run loop contents here only if the first V
121 ;V value to accumulate is not specified. V
122 ,@(unless var-init-p s-proc
)
123 ;V Give all tails a value if they don't have one, V
124 (setq ,@post-inits
);< update some nil lists too.
127 (setq ,@do-setqs
);< Normal do-loop updates.
128 (if ,s-pred
(go ,end-loop-tag
))
129 ,@s-proc
;< Run inner loop.
130 ,@s-conditail-setqs
;< Conditional tail updates.
131 (setq ,@tail-setqs
);< Update all tails.
134 ;V Loop is over, run user's cleanup forms.V
148 (arem (gensym)) (brem (gensym))
151 (((,row
,rows
,tail
))
152 (,arem
,s-arows
(cdr ,arem
))
153 (,brem
,s-brows
(cdr ,brem
))
154 (,finished nil
(not (and ,arem
,brem
))))
159 (let* (,@(when s-bwidth
`((,width
,s-bwidth
)))
161 (mapcar #'(lambda (,arow
) ,s-cat
) ,arem
))
163 (let* (,@(when s-awidth
`((,width
,s-awidth
)))
165 (mapcar #'(lambda (,brow
) ,s-cat
) ,brem
)))))
167 (let ((,arow
(car ,arem
))
169 (setq ,row
,s-cat
)))))
172 (defmethod cat2 ((a number
) (b number
))
173 (make-mtrix :dimdom
2 :dimcodom
1
174 :elems
(list (list a b
))))
176 (defmethod vcat2 ((a number
) (b number
))
177 (make-tuple :dim
2 :elems
(list a b
)))
179 (defmethod cat2 ((k number
) (u tuple
))
180 (make-mtrix :dimdom
2 :dimcodom
(tuple-dim u
)
181 :elems
(mapcar #'(lambda (x) (list k x
))
184 (defmethod cat2 ((u tuple
) (k number
))
185 (make-mtrix :dimdom
2 :dimcodom
(tuple-dim u
)
186 :elems
(mapcar #'(lambda (x) (list x k
))
189 (defmethod vcat2 ((k number
) (u tuple
))
190 (make-tuple :dim
(1+ (tuple-dim u
))
191 :elems
(cons k
(tuple-elems u
))))
193 (defmethod vcat2 ((u tuple
) (k number
))
194 (make-tuple :dim
(1+ (tuple-dim u
))
195 :elems
`(,@(tuple-elems u
) ,k
)))
197 ;V Align two tuples into a column matrix.V
198 (defmethod cat2 ((u tuple
) (v tuple
))
200 ((uelem (tuple-elems u
))
201 (velem (tuple-elems v
))
204 (nil (nil 0) (nil 0))
205 (make-mtrix :dimdom
2
206 :dimcodom
(max (tuple-dim u
)
210 ;V Merge two tuples together into one long vector.V
211 (defmethod vcat2 ((u tuple
) (v tuple
))
212 (make-tuple :dim
(+ (tuple-dim u
) (tuple-dim v
))
213 :elems
(append (tuple-elems u
)
216 ;V Add a column vector /u/ to V
217 ;V the left side of matrix /a/.V
218 (defmethod cat2 ((u tuple
) (a mtrix
))
220 ((uelem (tuple-elems u
))
221 (arow (mtrix-elems a
))
227 (make-list width
:initial-element
0)))
228 (make-mtrix :dimdom
(1+ (mtrix-dimdom a
))
229 :dimcodom
(max (tuple-dim u
)
233 (defmethod cat2 ((a mtrix
) (u tuple
))
235 ((arow (mtrix-elems a
))
236 (uelem (tuple-elems u
))
241 (make-list width
:initial-element
0))
243 (make-mtrix :dimdom
(1+ (mtrix-dimdom a
))
244 :dimcodom
(mtrix-dimcodom a
)
247 (defmethod cat2 ((a mtrix
) (b mtrix
))
249 ((arow (mtrix-elems a
))
250 (brow (mtrix-elems b
))
255 (make-list width
:initial-element
0))
257 (make-list width
:initial-element
0)))
258 (make-mtrix :dimdom
(+ (mtrix-dimdom a
)
260 :dimcodom
(max (mtrix-dimcodom a
)
264 (defmethod vcat2 ((u tuple
) (a mtrix
))
265 (let ((uwid (tuple-dim u
))
266 (awid (mtrix-dimdom a
))
267 (rows (cons (tuple-elems u
)
273 (make-list (- awid uwid
)
274 :initial-element
0)))
275 (unless (= uwid awid
)
276 (shiftf awid uwid
(- uwid awid
))
283 (make-list uwid
:initial-element
0)))
285 (make-mtrix :dimdom awid
286 :dimcodom
(1+ (mtrix-dimcodom a
))
289 (defmethod vcat2 ((a mtrix
) (u tuple
))
290 (let ((awid (mtrix-dimdom a
))
291 (uwid (tuple-dim u
)))
293 :dimcodom
(1+ (mtrix-dimcodom a
))
297 ,(append (tuple-elems u
)
298 (make-list (- awid uwid
)
299 :initial-element
0)))
301 `(,@(mtrix-elems a
) ,(tuple-elems u
))
303 (shiftf awid uwid
(- uwid awid
))
306 (arem (mtrix-elems a
) (cdr arem
)))
308 (rplacd tail
(cons (tuple-elems u
) nil
))
314 uwid
:initial-element
0)))))))
317 ;V Join a column of /k/'s onto the left of /a/.V
318 (defmethod cat2 ((k number
) (a mtrix
))
320 :dimdom
(1+ (mtrix-dimdom a
))
321 :dimcodom
(mtrix-dimcodom a
)
322 :elems
(mapcar #'(lambda (row) (cons k row
))
325 ;V Join a column of /k/'s onto the right of /a/.V
326 (defmethod cat2 ((a mtrix
) (k number
))
328 :dimdom
(1+ (mtrix-dimdom a
))
329 :dimcodom
(mtrix-dimcodom a
)
330 :elems
(mapcar #'(lambda (row) `(,@row
,k
))
333 ;V Join a row of /k/'s onto the top of /a/.V
334 (defmethod vcat2 ((k number
) (a mtrix
))
336 :dimdom
(mtrix-dimdom a
)
337 :dimcodom
(1+ (mtrix-dimcodom a
))
338 :elems
(cons (make-list (mtrix-dimdom a
)
342 ;V Join a row of /k/'s onto the bottom of /a/.V
343 (defmethod vcat2 ((a mtrix
) (k number
))
345 :dimdom
(mtrix-dimdom a
)
346 :dimcodom
(1+ (mtrix-dimcodom a
))
347 :elems
`(,@(mtrix-elems a
)
348 ,(make-list (mtrix-dimdom a
)
349 :initial-element k
))))
351 (defmethod vcat2 ((a mtrix
) (b mtrix
))
352 (let* ((awid (mtrix-dimdom a
))
353 (bwid (mtrix-dimdom b
))
354 (finwid (max awid bwid
))
355 (zeros (make-list (abs (- awid bwid
))
356 :initial-element
0)))
359 :dimcodom
(+ (mtrix-dimcodom a
)
362 (if (= awid finwid
) (mtrix-elems a
)
363 (mapcar #'(lambda (row)
366 (if (= bwid finwid
) (mtrix-elems b
)
367 (mapcar #'(lambda (row)
369 (mtrix-elems b
)))))))