IntDiv
template IntDiv(n) {
signal input in[2];
signal output out;
// divisor must be non-zero
signal is_non_zero <== IsZero()(in[1]);
0 === is_non_zero;
// compute the quotient and remainder outside the circuit
var quot_hint = in[0] \ in[1];
var rem_hint = in[0] % in[1];
signal quot <-- quot_hint;
signal rem <-- rem_hint;
// contrain the division operation
// in[0] / in[1] is defined as the unique pair (q, r) s.t.
// in[0] = in[1] * q + r and 0 <= r < |in[1]|
in[0] === quot * in[1] + rem;
// OPTIONAL: quot edge case is when `rem = 0` and `in[1] = 1`
// signal quot_is_valid <== LessEqThan(n)([quot, in[0]]);
// 1 === quot_is_valid;
signal rem_is_valid <== LessThan(n)([rem, in[1]]);
1 === rem_is_valid;
out <== quot;
}
Doing integer division within a circuit is more costly than what one might one expect! Consider two -bit numbers and . An integer division implies the following equation:
where is the quotient, and is the remainder such that . As an example, consider the division . We have:
giving us the quotient and remainder . Notice that if we allowed , we could have:
which would be wrong! On a side note, one may look at the case if we allowed such as the following:
which is again wrong. Thankfully, the constraint on remainder prevents this as well; here we get which corresponds to a very large number in the prime field, much larger than in most cases. If the integer division takes place over very large numbers, one may additionally check for .