Problem with Sum in Constraint
Opened this issue · 9 comments
The following expression is not behaving as expected:
(eq! DATA_HI
(+ (for i
[0 : LLARGEMO]
(* (^ 256 (- LLARGEMO i))
[BYTE_HI i]))))
This is suppose to reconstruct the value of a byte decomposition.
@letypequividelespoubelles Feel free to add any further comments
@letypequividelespoubelles One thing I can say immediately is that the expression is not formulated correctly. This is because arrays are indexed from 1
in Corset, not 0
. Therefore, I think you can rewrite the above like so:
(eq! DATA_HI
(+ (for i
[1 : LLARGE]
(* (^ 256 (- LLARGE i))
[BYTE_HI i]))))
Notice: [0 : LLARGEMO]
becomes [1 : LLARGE]
and likewise (^ 256 LLARGEMO)
becomes (^ 256 LLARGE)
Ok, so there is an issue here. Here's my minimal test case:
(module test)
(defconst WIDTH 2)
(defcolumns
WORD
(BYTE :byte@prove :array[WIDTH]))
(defconstraint test1 () (eq! WORD
(+ (for i [1:WIDTH]
(* (^ 256 (- WIDTH i)) [BYTE i])))))
(defconstraint test2 () (eq! WORD
(+ (* 256 [BYTE 1]) [BYTE 2])))
Here, test1
and test2
are supposed to be equivalent. The output from corset debug -ceeee
is:
test.test1 :=
WORD .- {
256 * BYTE_1
1 * BYTE_2
}
test.test2 :=
WORD .- (256 * BYTE_1 + BYTE_2)
Also, here's is a trace which is (unexpectedly) rejected by constraint test1
above (but not test2
):
{ "test": {"WORD": [0,1,255,256,257], "BYTE_1": [0,0,0,1,1], "BYTE_2": [0,1,255,0,1] } }
Specifically, the last row of the trace where WORD=257
, BYTE_1=1
and BYTE_2=1
is the problem.
I think the issue is related to how the for
loops are being expanded. I guess that it is being expanded as this:
(defconstraint test2 ()
(eq! WORD
(+ (begin
(* 256 [BYTE 1])
[BYTE 2]))))
Yes, that's it.
@letypequividelespoubelles I'm not sure you can use a for
loop in this way unfortunately. Its intended for generating multiple distinct constraints, rather than generating multiple expressions.
@delehef Any comments?
Yep, one should use reduce
; as in (reduce + (for i [1:5] (* 3 i)))
==
There is a bug however; test1
should not compile, as +
should refuse non-scalar arguments, such as the list generated by a for
. Ideally, this should be fixed in the type validation for Intrinsic::Add
.
Ah ha, thanks --- I've upgraded this to have bug status!
@letypequividelespoubelles One thing I can say immediately is that the expression is not formulated correctly. This is because arrays are indexed from
1
in Corset, not0
. Therefore, I think you can rewrite the above like so:
Yes but in the columns.go
, I specifically define the columns array to start at 0 : (BYTE_HI :array [0 : LLARGEMO] :byte@prove)
Yep, one should use reduce
I tried with reduce
too but it was the exact same output
Yes but in the columns.go, I specifically define the columns array to start at 0
Ah, ok, I see. I will try to get reduce
to work.
Can confirm this:
(module test)
(defconst WIDTH 2)
(defcolumns
WORD
(BYTE :byte@prove :array[WIDTH]))
(defconstraint test1 () (eq! WORD
(reduce + (for i [1:WIDTH]
(* (^ 256 (- WIDTH i)) [BYTE i])))))
Accepts this trace:
{ "test": {"WORD": [0,1,255,256,257], "BYTE_1": [0,0,0,1,1], "BYTE_2": [0,1,255,0,1] } }
And, can also confirm this:
(module test)
(defconst
WIDTH 2
WIDTHMO (- WIDTH 1)
)
(defcolumns
WORD
(BYTE :byte@prove :array[0:WIDTHMO]))
(defconstraint test1 () (eq! WORD
(reduce + (for i [0:WIDTHMO]
(* (^ 256 (- WIDTHMO i)) [BYTE i])))))
accepts the following trace:
{ "test": {"WORD": [0,1,255,256,257], "BYTE_0": [0,0,0,1,1], "BYTE_1": [0,1,255,0,1] } }
@letypequividelespoubelles I think we need some more info on how its failing for you with reduce
?