/// Enforce the constraints that ensure that `lower` consists of binary values and that the num
/// representation thereof is smaller than or equal to `upper`.
Enforce the constraints that ensure that `lower` consists of binary values and that the num
representation thereof is smaller than or equal to `upper`.
Enforce the constraints that ensure that ` lower ` consists of binary values and that the num representation thereof is smaller than or equal to ` upper ` .
pub fn comparison<Scalar: PrimeField, CS: ConstraintSystem<Scalar>>(
    mut cs: CS,
    lower: &[AllocatedNum<Scalar>],
    upper: &[Boolean],
) -> Result<(), SynthesisError> {
    assert_eq!(lower.len(), upper.len());
    let mut pis = vec![CS::one()];
    let mut pi_values = vec![Some(Scalar::one())];
    for (i, (l, u)) in lower
        .iter()
        .zip(upper.iter())
        .rev()
        .skip(1)
        .rev()
        .enumerate()
    {
        let pi_prev = pis.last().expect("This vector is not empty.");
        let pi_prev_value = *pi_values.last().expect("This vector is not empty.");
        let pi_helper = AllocatedNum::alloc(
            cs.namespace(|| format!("pi_(n-{}) helper bit", i + 1)),
            || {
                if !(*u.get_value().get()?) {
                    Ok(Scalar::one())
                } else {
                    l.get_value().get().map(|&l| l)
                }
            },
        )?;
        cs.enforce(
            || format!("pi_(n-{}) helper bit constraint", i + 1),
            |lc| lc + &u.lc(CS::one(), Scalar::one()),
            |lc| lc + CS::one() - l.get_variable(),
            |lc| lc + CS::one() - pi_helper.get_variable(),
        );
        let pi_new = AllocatedNum::alloc(cs.namespace(|| format!("pi_(n-{})", i + 1)), || {
            if !(*u.get_value().get()?) {
                pi_prev_value.get().map(|&x| x)
            } else {
                let mut pi_prev = *pi_prev_value.get()?;
                l.get_value().get().map(|l| {
                    pi_prev.mul_assign(l);
                    pi_prev
                })
            }
        })?;
        cs.enforce(
            || format!("pi_(n-{}) constraints", i + 1),
            |lc| lc + *pi_prev,
            |lc| lc + pi_helper.get_variable(),
            |lc| lc + pi_new.get_variable(),
        );
        pis.push(pi_new.get_variable());
        pi_values.push(pi_new.get_value());
    }
    // --> constrain lower bits
    for (i, (l, u)) in lower.iter().zip(upper.iter()).enumerate() {
        let effective_pi = AllocatedNum::alloc(
            cs.namespace(|| format!("effective pi for constraint {}", i)),
            || {
                if *u.get_value().get()? {
                    Ok(Scalar::zero())
                } else {
                    pi_values[i].get().map(|&pi| pi)
                }
            },
        )?;
        cs.enforce(
            || format!("effective pi for constraint {} constraint", i),
            |lc| lc + pis[i],
            |lc| lc + CS::one() - &u.lc(CS::one(), Scalar::one()),
            |lc| lc + effective_pi.get_variable(),
        );
        cs.enforce(
            || format!("constrain lower bit n-{}", i + 1),
            |lc| lc + l.get_variable(),
            |lc| lc + CS::one() - effective_pi.get_variable() - l.get_variable(),
            |lc| lc,
        );
    }
    Ok(())
}
pub fn comparison < Scalar : PrimeField , CS : ConstraintSystem < Scalar > > ( mut cs : CS , lower : & [ AllocatedNum < Scalar > ] , upper : & [ Boolean ] , ) -> Result < ( ) , SynthesisError > { assert_eq ! ( lower len ( ) upper len ( ) ) ; let mut pis = vec ! [ CS one ( ) ] ; let mut pi_values = vec ! [ Some ( Scalar one ( ) ) ] ; for ( i , ( l , u ) ) in lower . iter ( ) . zip ( upper . iter ( ) ) . rev ( ) . skip ( 1 ) . rev ( ) . enumerate ( ) { let pi_prev = pis . last ( ) . expect ( " " ) ; let pi_prev_value = * pi_values . last ( ) . expect ( " " ) ; let pi_helper = AllocatedNum :: alloc ( cs . namespace ( | | format ! ( " " i 1 ) ) , | | { if ! ( * u . get_value ( ) . get ( ) ? ) { Ok ( Scalar :: one ( ) ) } else { l . get_value ( ) . get ( ) . map ( | & l | l ) } } , ) ? ; cs . enforce ( | | format ! ( " " i 1 ) , | lc | lc + & u . lc ( CS :: one ( ) , Scalar :: one ( ) ) , | lc | lc + CS :: one ( ) - l . get_variable ( ) , | lc | lc + CS :: one ( ) - pi_helper . get_variable ( ) , ) ; let pi_new = AllocatedNum :: alloc ( cs . namespace ( | | format ! ( " " i 1 ) ) , | | { if ! ( * u . get_value ( ) . get ( ) ? ) { pi_prev_value . get ( ) . map ( | & x | x ) } else { let mut pi_prev = * pi_prev_value . get ( ) ? ; l . get_value ( ) . get ( ) . map ( | l | { pi_prev . mul_assign ( l ) ; pi_prev } ) } } ) ? ; cs . enforce ( | | format ! ( " " i 1 ) , | lc | lc + * pi_prev , | lc | lc + pi_helper . get_variable ( ) , | lc | lc + pi_new . get_variable ( ) , ) ; pis . push ( pi_new . get_variable ( ) ) ; pi_values . push ( pi_new . get_value ( ) ) ; } // --> constrain lower bits for ( i , ( l , u ) ) in lower . iter ( ) . zip ( upper . iter ( ) ) . enumerate ( ) { let effective_pi = AllocatedNum :: alloc ( cs . namespace ( | | format ! ( " " i ) ) , | | { if * u . get_value ( ) . get ( ) ? { Ok ( Scalar :: zero ( ) ) } else { pi_values [ i ] . get ( ) . map ( | & pi | pi ) } } , ) ? ; cs . enforce ( | | format ! ( " " i ) , | lc | lc + pis [ i ] , | lc | lc + CS :: one ( ) - & u . lc ( CS :: one ( ) , Scalar :: one ( ) ) , | lc | lc + effective_pi . get_variable ( ) , ) ; cs . enforce ( | | format ! ( " " i 1 ) , | lc | lc + l . get_variable ( ) , | lc | lc + CS :: one ( ) - effective_pi . get_variable ( ) - l . get_variable ( ) , | lc | lc , ) ; } Ok ( ( ) ) }
Enforce the constraints that ensure that `lower` consists of binary values and that the num
representation thereof is smaller than or equal to `upper`.
Enforce the constraints that ensure that ` lower ` consists of binary values and that the num representation thereof is smaller than or equal to ` upper ` .
cs
CS
lower
&[AllocatedNum<Scalar>]
upper
&[Boolean]