Coverage report: /home/runner/work/geb/geb/src/geb/trans.lisp
Kind | Covered | All | % |
expression | 370 | 581 | 63.7 |
branch | 5 | 20 | 25.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;; Transition or Translation functions about geb
3
(in-package :geb.trans)
5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;; Morph to Poly Implementation
7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
;; This maintains exhaustion while leaving it open to extension. you
10
;; can subclass <substmorph>, without having to update the exhaustion
11
;; set, however you'll need to properly implement the interface
14
;; Hopefully I can form a complete list somewhere, so one can see the
15
;; interface functions intended.
17
;; We could have also derived this from methods, these are equivalent,
18
;; so both styles are acceptable
19
(defmethod to-poly ((obj <substmorph>))
20
(typecase-of substmorph obj
21
(substobj (error "impossible"))
24
(inject-left poly:ident)
25
(inject-right (poly:+ (obj-to-nat (mcar obj)) poly:ident))
26
(comp (poly:compose (to-poly (mcar obj))
27
(to-poly (mcadr obj))))
28
(project-right (let ((nat (obj-to-nat (mcadr obj))))
31
(poly:mod poly:ident nat))))
32
(project-left (let ((nat (obj-to-nat (mcar obj))))
35
;; we want to bitshift it by the size
38
;; we need to remove the right value
39
;; we are doing project-right
40
(to-poly (<-right (mcar obj) (mcadr obj))))
42
(distribute (let ((cx (obj-to-nat (mcar obj)))
43
(cy (obj-to-nat (mcadr obj)))
44
(cz (obj-to-nat (mcaddr obj))))
45
(if (and (zerop cy) (zerop cz))
47
(let* ((yz (poly:+ cy cz))
48
(xin (poly:/ poly:ident yz))
49
(yzin (poly:mod poly:ident yz)))
51
(poly:+ (poly:* cy xin) yzin)
52
(poly:+ (poly:* cz xin)
55
(pair (let* ((z (codom (mcdr obj)))
57
(poly:+ (poly:* cz (to-poly (mcar obj)))
58
(to-poly (mcdr obj)))))
59
(case (let* ((f (mcar obj))
62
(poly-g (to-poly (mcadr obj))))
65
(poly:if-lt poly:ident cx
68
(poly:- poly:ident cx))))))
69
(otherwise (subclass-responsibility obj))))
71
;; put here just to avoid confusion
72
(defmethod to-poly ((obj <substobj>))
73
(declare (ignore obj))
76
(defun obj-to-nat (obj)
79
(defmethod to-circuit ((obj <substmorph>) name)
80
"Turns a @GEB-SUBSTMORPH to a Vamp-IR Term"
81
(to-circuit (to-seqn obj) name))
83
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
84
;; Morph to Bitc Implementation
85
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
87
(defmethod bitwidth ((obj <substobj>))
88
(typecase-of substobj obj
91
(coprod (+ 1 (max (bitwidth (mcar obj)) (bitwidth (mcadr obj)))))
92
(prod (+ (bitwidth (mcar obj)) (bitwidth (mcadr obj))))
93
(otherwise (subclass-responsibility obj))))
95
(defmethod to-bitc ((obj <substmorph>))
96
(typecase-of substmorph obj
98
(bitc:ident (bitwidth obj)))
100
(bitc:compose (to-bitc (mcar obj))
101
(to-bitc (mcadr obj))))
102
;; This should never occure, but if it does, it produces a
103
;; constant morphism onto an all 0s list
105
(let* ((list (zero-list (bitwidth (mcar obj))))
107
(cond ((= 0 len) (bitc:drop 0))
108
((= 1 len) bitc:zero)
109
(t (apply #'bitc:parallel list)))))
110
;; Terminal maps any bit-list onto the empty bit-list
112
(bitc:drop (bitwidth (mcar obj))))
114
;; Inject-left x -> x + y tags the x with a 0, indicating left,
115
;; and pads the encoded x with as many zeros as would be needed
116
;; to store either an x or a y.
118
(let ((car-width (bitwidth (mcar obj)))
119
(cadr-width (bitwidth (mcadr obj))))
120
(apply #'bitc:parallel
121
(append (list bitc:zero (bitc:ident car-width))
122
(zero-list (padding-bits cadr-width
124
;; Inject-right y -> x + y tags the y with a 1, indicating right,
125
;; and pads the encoded y with as many zeros as would be needed
126
;; to store either an x or a y.
128
(let ((car-width (bitwidth (mcar obj)))
129
(cadr-width (bitwidth (mcadr obj))))
130
(apply #'bitc:parallel
131
(append (list bitc:one (bitc:ident cadr-width))
132
(zero-list (padding-bits car-width
135
;; Case translates directly into a branch. The sub-morphisms of
136
;; case are padded with drop so they have the same input lengths.
138
(let ((car-width (bitwidth (dom (mcar obj))))
139
(cadr-width (bitwidth (dom (mcadr obj)))))
140
(bitc:branch (bitc:parallel (to-bitc (mcar obj))
142
(padding-bits cadr-width car-width)))
143
(bitc:parallel (to-bitc (mcadr obj))
145
(padding-bits car-width cadr-width))))))
146
;; project-left just drops any bits not being used to encode the
149
(bitc:parallel (bitc:ident (bitwidth (mcar obj)))
150
(bitc:drop (bitwidth (mcadr obj)))))
152
;; project-right just drops any bits not being used to encode the
155
(bitc:parallel (bitc:drop (bitwidth (mcar obj)))
156
(bitc:ident (bitwidth (mcadr obj)))))
158
;; Pair will copy the input and run the encoded morphisms in pair
159
;; on the two copied subvetors.
161
(bitc:compose (bitc:parallel (to-bitc (mcar obj)) (to-bitc (mcdr obj)))
162
(bitc:fork (bitwidth (dom (mcar obj))))))
163
;; a * (b + c) will be encoded as [a] [0 or 1] [b or c]. By
164
;; swapping the [0 or 1] with [a], we get an encoding for (a * b)
167
(bitc:parallel (bitc:swap (bitwidth (mcar obj)) 1)
168
(bitc:ident (max (bitwidth (mcadr obj))
169
(bitwidth (mcaddr obj))))))
170
(otherwise (subclass-responsibility obj))))
172
(defun zero-list (length)
173
(make-list length :initial-element bitc:zero))
175
(-> padding-bits ((integer 0) (integer 0)) (integer 0))
176
(defun padding-bits (number number2)
181
is the bits needed to store NUMBER or NUMBER2
183
Thus if we want to calculate the number of padding bits needed then we
187
(- (max number number2) number2)
190
We use an optimized version in actual code, which happens to compute the same result"
191
(max (- number number2) 0))
193
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
194
;; Geb to Seqn Implementation
195
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
197
(defmethod to-seqn ((obj <substobj>))
198
"Preserves identity morphims"
199
(seqn:id (geb.common:width obj)))
201
(defmethod to-seqn ((obj geb.extension.spec:<natobj>))
202
(seqn:id (geb.common:width obj)))
204
(defmethod to-seqn ((obj comp))
205
"Preserves composition"
206
(seqn:composition (to-seqn (mcar obj))
207
(to-seqn (mcadr obj))))
209
(defmethod to-seqn ((obj init))
210
"Produces a list of zeroes
211
Currently not aligning with semantics of drop-width
212
as domain and codomain can be of differing lengths"
213
(seqn:drop-width (list 0)
216
(defmethod to-seqn ((obj terminal))
217
"Drops everything to the terminal object,
219
(drop-nil (width (mcar obj))))
221
(defmethod to-seqn ((obj inject-left))
222
"Injects an x by marking its entries with 0
223
and then inserting as padded bits if necessary"
224
(let ((l1 (width (mcar obj)))
225
(l3 (width (coprod (mcar obj)
227
;; (a1,...,an) -> (0, a1,...,an) -> (1, max(a1, b1),..., max(an, 0) or max(an, bn))
229
(composition (parallel-seq zero-bit
230
(inj-coprod-parallel l1 l3))
231
(inj-length-right (list 0)
234
(defmethod to-seqn ((obj inject-right))
235
"Injects an x by marking its entries with 1
236
and then inserting as padded bits if necessary"
237
(let ((l2 (width (mcadr obj)))
238
(l3 (width (coprod (mcar obj)
240
(composition (parallel-seq one-bit
241
(inj-coprod-parallel l2
243
(inj-length-right (list 0)
246
(defmethod to-seqn ((obj case))
247
"Cases by forgetting the padding and if necessary dropping
248
the extra entries if one of the inputs had more of them to start
250
(let* ((lft (dom (mcar obj)))
251
(rt (dom (mcadr obj)))
257
(lengthleft (length wlft))
258
(lengthright (length wrt)))
261
(composition (to-seqn z)
262
(composition (remove-right x)
269
(drop-nil (nthcdr (1+ (length x))
272
(composition (to-seqn x)
273
(drop-width (cdr (width cpr)) y))))
274
(cond ((< lengthleft lengthright)
275
;; branch on the left counts the first entries of an occuring and drops the rest
276
;; then injects it into the smaller bit sizes if necessary
277
;; (max(a1, b1),,,.,(max (an, bn),..., max(0, bm))) -> (a1,...,an,0)
279
;; branch on the right is just injecting
280
;; (max(a1, b1),..., max(0, bn)) -> (b1, ...., bn) -> codom))
281
(branch-seq (funor wlft wrt mcar) (funinj mcadr wrt)))
282
((< lengthright lengthleft)
283
(branch-seq (funinj mcar wlft) (funor wrt wlft mcadr)))
284
((= lengthright lengthleft)
285
(branch-seq (funinj mcar wlft) (funinj mcadr wrt)))))))
287
(defmethod to-seqn ((obj project-left))
288
"Takes a list of an even length and cuts the right half"
289
(let ((sw (width (mcar obj))))
290
(composition (remove-right sw)
291
(parallel-seq (id sw)
292
(drop-nil (width (mcadr obj)))))))
294
(defmethod to-seqn ((obj project-right))
295
"Takes a list of an even length and cuts the left half"
296
(let ((sw (width (mcadr obj))))
297
(composition (remove-left sw)
298
(parallel-seq (drop-nil (width (mcar obj)))
301
(defmethod to-seqn ((obj pair))
302
"Forks entries and then applies both morphism
303
on corresponding entries"
304
(composition (parallel-seq (to-seqn (mcar obj))
305
(to-seqn (mcdr obj)))
306
(fork-seq (width (dom obj)))))
308
(defmethod to-seqn ((obj distribute))
309
"Given A x (B + C) simply moves the 1-bit entry
310
to the front and keep the same padding relations to
311
get ((A x B) + (A x C)) as times appends sequences"
312
(shift-front (width (dom obj))
313
(1+ (length (width (mcar obj))))))
315
(defmethod to-seqn ((obj geb.extension.spec:nat-add))
316
"Addition is interpreted as addition"
317
(seqn-add (geb.extension.spec:num obj)))
319
(defmethod to-seqn ((obj geb.extension.spec:nat-mult))
320
"Multiplication is interpreted as multiplication"
321
(seqn-multiply (geb.extension.spec:num obj)))
323
(defmethod to-seqn ((obj geb.extension.spec:nat-sub))
324
"Subtraction is interpreted as subtraction"
325
(seqn-subtract (geb.extension.spec:num obj)))
327
(defmethod to-seqn ((obj geb.extension.spec:nat-div))
328
"Division is interpreted as divition"
329
(seqn-divide (geb.extension.spec:num obj)))
331
(defmethod to-seqn ((obj geb.extension.spec:nat-mod))
332
"Modulo is interpreted as modulo"
333
(seqn-mod (geb.extension.spec:num obj)))
335
(defmethod to-seqn ((obj geb.extension.spec:nat-const))
336
"A choice of a natural number is the same exact choice in SeqN"
337
(seqn-nat (geb.extension.spec:num obj) (geb.extension.spec:pos obj)))
339
(defmethod to-seqn ((obj geb.extension.spec:nat-inj))
340
"Injection of bit-sizes is interpreted in the same maner in SeqN"
341
(let ((num (geb.extension.spec:num obj)))
342
(inj-size num (1+ num))))
344
(defmethod to-seqn ((obj geb.extension.spec:nat-concat))
345
"Concatenation is interpreted as concatenation"
346
(seqn-concat (geb.extension.spec:num-left obj)
347
(geb.extension.spec:num-right obj )))
349
(defmethod to-seqn ((obj geb.extension.spec:one-bit-to-bool))
350
"Iso interpreted in an evident manner"
351
(inj-length-left (list 1) (list 0)))
353
(defmethod to-seqn ((obj geb.extension.spec:nat-decompose))
354
"Decomposition is interpreted on the nose"
355
(seqn-decompose (geb.extension.spec:num obj)))
357
(defmethod to-seqn ((obj geb.extension.spec:nat-eq))
358
"Equality predicate is interpreted on the nose"
359
(seqn-eq (geb.extension.spec:num obj)))
361
(defmethod to-seqn ((obj geb.extension.spec:nat-lt))
362
"Equality predicate is interpreted on the nose"
363
(seqn-lt (geb.extension.spec:num obj)))