snarkvm_circuit_types_field/
compare.rs1use super::*;
17
18impl<E: Environment> Compare<Field<E>> for Field<E> {
19 type Output = Boolean<E>;
20
21 fn is_less_than(&self, other: &Self) -> Self::Output {
23 if self.is_constant() && other.is_constant() {
25 Boolean::constant(self.eject_value() < other.eject_value())
26 }
27 else if self.is_constant() {
29 self.eject_value().to_bits_le().into_iter().zip_eq(other.to_bits_le()).fold(
31 Boolean::constant(false),
32 |is_less_than, (this, that)| match this {
33 true => that.bitand(&is_less_than),
34 false => that.bitor(&is_less_than),
35 },
36 )
37 }
38 else if other.is_constant() {
40 self.to_bits_le().into_iter().zip_eq(other.eject_value().to_bits_le()).fold(
42 Boolean::constant(false),
43 |is_less_than, (this, that)| match that {
44 true => (!this).bitor(is_less_than),
45 false => (!this).bitand(&is_less_than),
46 },
47 )
48 }
49 else {
51 self.to_bits_le()
70 .iter()
71 .zip_eq(other.to_bits_le())
72 .fold(Boolean::constant(false), |is_less_than, (this, that)| {
73 Boolean::ternary(&this.bitxor(&that), &that, &is_less_than)
74 })
75 }
76 }
77
78 fn is_greater_than(&self, other: &Self) -> Self::Output {
80 other.is_less_than(self)
81 }
82
83 fn is_less_than_or_equal(&self, other: &Self) -> Self::Output {
85 other.is_greater_than_or_equal(self)
86 }
87
88 fn is_greater_than_or_equal(&self, other: &Self) -> Self::Output {
90 !self.is_less_than(other)
91 }
92}
93
94#[cfg(test)]
97mod tests {
98 use super::*;
99 use snarkvm_circuit_environment::Circuit;
100
101 const ITERATIONS: u64 = 100;
102
103 fn check_is_less_than(
104 name: &str,
105 expected: bool,
106 a: &Field<Circuit>,
107 b: &Field<Circuit>,
108 num_constants: u64,
109 num_public: u64,
110 num_private: u64,
111 num_constraints: u64,
112 ) {
113 Circuit::scope(name, || {
115 let candidate = a.is_less_than(b);
116 assert_eq!(expected, candidate.eject_value());
117 match (a.eject_mode(), b.eject_mode()) {
118 (Mode::Constant, Mode::Constant) => {
119 assert_scope!(num_constants, num_public, num_private, num_constraints)
120 }
121 (_, Mode::Constant) | (Mode::Constant, _) => {
122 assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints)
123 }
124 _ => assert_scope!(num_constants, num_public, num_private, num_constraints),
125 }
126 });
127 Circuit::reset();
128 }
129
130 fn run_test(
131 mode_a: Mode,
132 mode_b: Mode,
133 num_constants: u64,
134 num_public: u64,
135 num_private: u64,
136 num_constraints: u64,
137 ) {
138 let mut rng = TestRng::default();
139
140 for i in 0..ITERATIONS {
141 let first = Uniform::rand(&mut rng);
142 let second = Uniform::rand(&mut rng);
143
144 let a = Field::<Circuit>::new(mode_a, first);
145 let b = Field::<Circuit>::new(mode_b, second);
146 let expected = first < second;
147 let name = format!("{mode_a} {mode_b} {i}");
148 check_is_less_than(&name, expected, &a, &b, num_constants, num_public, num_private, num_constraints);
149
150 let a = Field::<Circuit>::new(mode_a, first);
152 let b = Field::<Circuit>::new(mode_b, first);
153 check_is_less_than(
154 "first !< first",
155 false,
156 &a,
157 &b,
158 num_constants,
159 num_public,
160 num_private,
161 num_constraints,
162 );
163 }
164 }
165
166 #[test]
167 fn test_constant_is_less_than_constant() {
168 run_test(Mode::Constant, Mode::Constant, 0, 0, 0, 0);
169 }
170
171 #[test]
172 fn test_constant_is_less_than_public() {
173 run_test(Mode::Constant, Mode::Public, 0, 0, 757, 759);
174 }
175
176 #[test]
177 fn test_constant_is_less_than_private() {
178 run_test(Mode::Constant, Mode::Private, 0, 0, 757, 759);
179 }
180
181 #[test]
182 fn test_public_is_less_than_constant() {
183 run_test(Mode::Public, Mode::Constant, 0, 0, 757, 759);
184 }
185
186 #[test]
187 fn test_public_is_less_than_public() {
188 run_test(Mode::Public, Mode::Public, 0, 0, 1516, 1520);
189 }
190
191 #[test]
192 fn test_public_is_less_than_private() {
193 run_test(Mode::Public, Mode::Private, 0, 0, 1516, 1520);
194 }
195
196 #[test]
197 fn test_private_is_less_than_constant() {
198 run_test(Mode::Private, Mode::Constant, 0, 0, 757, 759);
199 }
200
201 #[test]
202 fn test_private_is_less_than_public() {
203 run_test(Mode::Private, Mode::Public, 0, 0, 1516, 1520);
204 }
205
206 #[test]
207 fn test_private_is_less_than_private() {
208 run_test(Mode::Private, Mode::Private, 0, 0, 1516, 1520);
209 }
210}