-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lazy if and division by zero #107
Comments
We can't exactly do a "lazy if" in Vamp-IR because circuits are static and can't introspect into the value of a variable to choose not to evaluate a branch. Both branches of an However I think we can address this in a different way, using the "division or zero" ( I think |
Thanks! Yes, using |
It just calls rust's built-in |
So it seems we need an analogue of |
If you want to run |
Without a non-crashing modulo there seems to be no way to compile Juvix programs which compute a remainder of a division by an unknown quantity, because there is no way to lazily check for 0. How would you implement the GCD function above without it? Unless you can somehow use |
It is possible to calculate |
Thanks! But it seems in The broader question is why do you have the |
I wouldn't call it tragic, but, yes, it would be less efficient. As for your other questions, I assume it was to minimize complexity. It's easier to call rust built-ins than to consider what might be most useful. But you do make a good point. |
My experience with compiling Juvix programs to VampIR is that this matters a lot. For example, I initially implemented |
Your
It doesn't do any range check on By contrast,
If we used it in a definition of
then
You may notice that the last exponent on the x is 2^7, not 2^8. Correcting this in your predicate would give us
but this still doesn't give us a guarantee that |
Yes, you're right, thanks. I know And it worked, because the values actually used are correct, just the circuit doesn't check it, as far as I understand. |
I'll correct it, but it is going to slow things down. These are basic operations used repeatedly everywhere - any slight inefficiency in their implementation results in significant overhead overall. |
Sorry, maybe this is a stupid question, but I still don't understand why you add |
I guess it works because in the |
I guess you also want some close to two's complement bit decomposition for a negative number, but the exact form of the bit decomposition doesn't matter for just checking if number is negative? And with the |
Or maybe the idea is that all numbers (positive and negative) are represented by field elements in the range |
No, this doesn't seem to make sense, because then adding |
From the documentation:
Isn't this just exactly the two's complement representation of -55 in an 8bit system? It's the binary representation of |
Hmm... it appears that you're right. The implementation in that section is incorrect. It should be 2^7 - 55, which has its last bit flipped. With the current implementation, To clear up some confusion, the |
Yes, thanks for the explanation. I was talking about the |
And in the book the |
I want to implement the GCD function in VampIR, unrolled up to some depth. Here is my code:
This compiles fine, but it will give a "division by zero" error while generating a proof for all small enough inputs. These are all the inputs we would want gcd to work with - it won't divide by zero only if the recursion depth limit is reached.
The problem is that the
if
is not lazy - it always "evaluates" both branches and one of them will ultimately lead to division by zero in a further recursive call.Is there any way to implement a lazy if?
Otherwise, there doesn't seem to be any way to guard against division by zero, which seems to rule out the possibility of correctly compiling Juvix programs which check for zero and terminate early to avoid division by zero.
The text was updated successfully, but these errors were encountered: