use crate::cmp::CmpGadget; use super::*; impl> CmpGadget for UInt { fn is_ge(&self, other: &Self) -> Result, SynthesisError> { if N + 1 < ((F::MODULUS_BIT_SIZE - 1) as usize) { let a = self.to_fp()?; let b = other.to_fp()?; let (bits, _) = (a - b + F::from(T::max_value()) + F::one()) .to_bits_le_with_top_bits_zero(N + 1)?; Ok(bits.last().unwrap().clone()) } else { unimplemented!("bit sizes larger than modulus size not yet supported") } } } #[cfg(test)] mod tests { use super::*; use crate::{ alloc::{AllocVar, AllocationMode}, prelude::EqGadget, uint::test_utils::{run_binary_exhaustive, run_binary_random}, R1CSVar, }; use ark_ff::PrimeField; use ark_test_curves::bls12_381::Fr; fn uint_gt>( a: UInt, b: UInt, ) -> Result<(), SynthesisError> { let cs = a.cs().or(b.cs()); let both_constant = a.is_constant() && b.is_constant(); let expected_mode = if both_constant { AllocationMode::Constant } else { AllocationMode::Witness }; let computed = a.is_gt(&b)?; let expected = Boolean::new_variable(cs.clone(), || Ok(a.value()? > b.value()?), expected_mode)?; assert_eq!(expected.value(), computed.value()); expected.enforce_equal(&computed)?; if !both_constant { assert!(cs.is_satisfied().unwrap()); } Ok(()) } fn uint_lt>( a: UInt, b: UInt, ) -> Result<(), SynthesisError> { let cs = a.cs().or(b.cs()); let both_constant = a.is_constant() && b.is_constant(); let expected_mode = if both_constant { AllocationMode::Constant } else { AllocationMode::Witness }; let computed = a.is_lt(&b)?; let expected = Boolean::new_variable(cs.clone(), || Ok(a.value()? < b.value()?), expected_mode)?; assert_eq!(expected.value(), computed.value()); expected.enforce_equal(&computed)?; if !both_constant { assert!(cs.is_satisfied().unwrap()); } Ok(()) } fn uint_ge>( a: UInt, b: UInt, ) -> Result<(), SynthesisError> { let cs = a.cs().or(b.cs()); let both_constant = a.is_constant() && b.is_constant(); let expected_mode = if both_constant { AllocationMode::Constant } else { AllocationMode::Witness }; let computed = a.is_ge(&b)?; let expected = Boolean::new_variable(cs.clone(), || Ok(a.value()? >= b.value()?), expected_mode)?; assert_eq!(expected.value(), computed.value()); expected.enforce_equal(&computed)?; if !both_constant { assert!(cs.is_satisfied().unwrap()); } Ok(()) } fn uint_le>( a: UInt, b: UInt, ) -> Result<(), SynthesisError> { let cs = a.cs().or(b.cs()); let both_constant = a.is_constant() && b.is_constant(); let expected_mode = if both_constant { AllocationMode::Constant } else { AllocationMode::Witness }; let computed = a.is_le(&b)?; let expected = Boolean::new_variable(cs.clone(), || Ok(a.value()? <= b.value()?), expected_mode)?; assert_eq!(expected.value(), computed.value()); expected.enforce_equal(&computed)?; if !both_constant { assert!(cs.is_satisfied().unwrap()); } Ok(()) } #[test] fn u8_gt() { run_binary_exhaustive(uint_gt::).unwrap() } #[test] fn u16_gt() { run_binary_random::<1000, 16, _, _>(uint_gt::).unwrap() } #[test] fn u32_gt() { run_binary_random::<1000, 32, _, _>(uint_gt::).unwrap() } #[test] fn u64_gt() { run_binary_random::<1000, 64, _, _>(uint_gt::).unwrap() } #[test] fn u128_gt() { run_binary_random::<1000, 128, _, _>(uint_gt::).unwrap() } #[test] fn u8_lt() { run_binary_exhaustive(uint_lt::).unwrap() } #[test] fn u16_lt() { run_binary_random::<1000, 16, _, _>(uint_lt::).unwrap() } #[test] fn u32_lt() { run_binary_random::<1000, 32, _, _>(uint_lt::).unwrap() } #[test] fn u64_lt() { run_binary_random::<1000, 64, _, _>(uint_lt::).unwrap() } #[test] fn u128_lt() { run_binary_random::<1000, 128, _, _>(uint_lt::).unwrap() } #[test] fn u8_le() { run_binary_exhaustive(uint_le::).unwrap() } #[test] fn u16_le() { run_binary_random::<1000, 16, _, _>(uint_le::).unwrap() } #[test] fn u32_le() { run_binary_random::<1000, 32, _, _>(uint_le::).unwrap() } #[test] fn u64_le() { run_binary_random::<1000, 64, _, _>(uint_le::).unwrap() } #[test] fn u128_le() { run_binary_random::<1000, 128, _, _>(uint_le::).unwrap() } #[test] fn u8_ge() { run_binary_exhaustive(uint_ge::).unwrap() } #[test] fn u16_ge() { run_binary_random::<1000, 16, _, _>(uint_ge::).unwrap() } #[test] fn u32_ge() { run_binary_random::<1000, 32, _, _>(uint_ge::).unwrap() } #[test] fn u64_ge() { run_binary_random::<1000, 64, _, _>(uint_ge::).unwrap() } #[test] fn u128_ge() { run_binary_random::<1000, 128, _, _>(uint_ge::).unwrap() } }