pub fn inv(&mut self, v: &Variable) -> (Variable, Variable) {
        let is_zero = self.new_variable();
        let v_inverse = self.new_variable();
        let hint = Some(Hint {
            function: |v: &FE<F>| {
                if *v == FE::zero() {
                    FE::one()
                } else {
                    FE::zero()
                }
            },
            input: Column::L,
            output: Column::R,
        });
        // v * z == 0
        self.add_constraint(Constraint {
            constraint_type: ConstraintType {
                ql: FE::zero(),
                qr: FE::zero(),
                qm: FE::one(),
                qo: FE::zero(),
                qc: FE::zero(),
            },
            l: *v,
            r: is_zero,
            o: self.null_variable(),
            hint,
        });
        // v * w + z == 1
        self.add_constraint(Constraint {
            constraint_type: ConstraintType {
                ql: FE::zero(),
                qr: FE::zero(),
                qm: FE::one(),
                qo: FE::one(),
                qc: -FE::one(),
            },
            l: *v,
            r: v_inverse, // w
            o: is_zero,   // z
            hint: Some(Hint {
                function: |v: &FE<F>| {
                    if *v == FE::zero() {
                        FE::zero()
                    } else {
                        v.inv().unwrap()
                    }
                },
                input: Column::L,
                output: Column::R,
            }),
        });
        (is_zero, v_inverse)
    }
Creates two new variables `is_zero` and `v_inverse`. The former is constrained
to be a boolean value holding `1` if `v` is zero and `0` otherwise. The latter
is constrained to be `v^{-1}` when `v` is not zero and equal to `0` otherwise.
crates/provers/plonk/src/constraint_system/operations.rs