snarkvm_circuit_types_field/
sub.rs1use super::*;
17
18impl<E: Environment> Sub<Field<E>> for Field<E> {
19 type Output = Self;
20
21 fn sub(self, other: Field<E>) -> Self::Output {
22 self - &other
23 }
24}
25
26impl<E: Environment> Sub<&Field<E>> for Field<E> {
27 type Output = Self;
28
29 fn sub(self, other: &Field<E>) -> Self::Output {
30 let mut result = self;
31 result -= other;
32 result
33 }
34}
35
36impl<E: Environment> Sub<Field<E>> for &Field<E> {
37 type Output = Field<E>;
38
39 fn sub(self, other: Field<E>) -> Self::Output {
40 self - &other
41 }
42}
43
44impl<E: Environment> Sub<&Field<E>> for &Field<E> {
45 type Output = Field<E>;
46
47 fn sub(self, other: &Field<E>) -> Self::Output {
48 let mut result = self.clone();
49 result -= other;
50 result
51 }
52}
53
54impl<E: Environment> SubAssign<Field<E>> for Field<E> {
55 fn sub_assign(&mut self, other: Field<E>) {
56 *self -= &other;
57 }
58}
59
60impl<E: Environment> SubAssign<&Field<E>> for Field<E> {
61 fn sub_assign(&mut self, other: &Field<E>) {
62 *self += -other;
63 }
64}
65
66impl<E: Environment> Metrics<dyn Sub<Field<E>, Output = Field<E>>> for Field<E> {
67 type Case = (Mode, Mode);
68
69 fn count(_case: &Self::Case) -> Count {
70 Count::is(0, 0, 0, 0)
71 }
72}
73
74impl<E: Environment> OutputMode<dyn Sub<Field<E>, Output = Field<E>>> for Field<E> {
75 type Case = (CircuitType<Field<E>>, CircuitType<Field<E>>);
76
77 fn output_mode(case: &Self::Case) -> Mode {
78 match (case.0.mode(), case.1.mode()) {
79 (Mode::Constant, Mode::Constant) => Mode::Constant,
80 (Mode::Public, Mode::Constant) => match &case.1 {
81 CircuitType::Constant(constant) => match constant.eject_value().is_zero() {
82 true => Mode::Public,
83 false => Mode::Private,
84 },
85 _ => E::halt("The constant is required to determine the output mode of Public + Constant"),
86 },
87 (_, _) => Mode::Private,
88 }
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use snarkvm_circuit_environment::Circuit;
96
97 const ITERATIONS: u64 = 10_000;
98
99 fn check_sub(
100 name: &str,
101 expected: &console::Field<<Circuit as Environment>::Network>,
102 a: &Field<Circuit>,
103 b: &Field<Circuit>,
104 ) {
105 Circuit::scope(name, || {
106 let candidate = a - b;
107 assert_eq!(*expected, candidate.eject_value(), "({} - {})", a.eject_value(), b.eject_value());
108 assert_count!(Sub(Field, Field) => Field, &(a.eject_mode(), b.eject_mode()));
109 assert_output_mode!(Sub(Field, Field) => Field, &(CircuitType::from(a), CircuitType::from(b)), candidate);
110 });
111 }
112
113 fn check_sub_assign(
114 name: &str,
115 expected: &console::Field<<Circuit as Environment>::Network>,
116 a: &Field<Circuit>,
117 b: &Field<Circuit>,
118 ) {
119 Circuit::scope(name, || {
120 let mut candidate = a.clone();
121 candidate -= b;
122 assert_eq!(*expected, candidate.eject_value(), "({} - {})", a.eject_value(), b.eject_value());
123 assert_count!(Sub(Field, Field) => Field, &(a.eject_mode(), b.eject_mode()));
124 assert_output_mode!(Sub(Field, Field) => Field, &(CircuitType::from(a), CircuitType::from(b)), candidate);
125 });
126 }
127
128 fn run_test(mode_a: Mode, mode_b: Mode) {
129 let mut rng = TestRng::default();
130
131 for i in 0..ITERATIONS {
132 let first = Uniform::rand(&mut rng);
133 let second = Uniform::rand(&mut rng);
134
135 let expected = first - second;
136 let a = Field::<Circuit>::new(mode_a, first);
137 let b = Field::<Circuit>::new(mode_b, second);
138
139 let name = format!("Sub: a - b {i}");
140 check_sub(&name, &expected, &a, &b);
141 let name = format!("SubAssign: a - b {i}");
142 check_sub_assign(&name, &expected, &a, &b);
143
144 let name = format!("Sub: a - 0 {i}");
146 let zero = Field::<Circuit>::new(mode_b, console::Field::<<Circuit as Environment>::Network>::zero());
147 check_sub(&name, &first, &a, &zero);
148 let name = format!("SubAssign: a - 0 {i}");
149 check_sub_assign(&name, &first, &a, &zero);
150
151 let name = format!("Sub: 0 - b {i}");
153 let zero = Field::<Circuit>::new(mode_a, console::Field::<<Circuit as Environment>::Network>::zero());
154 check_sub(&name, &(-second), &zero, &b);
155 let name = format!("SubAssign: 0 - b {i}");
156 check_sub_assign(&name, &(-second), &zero, &b);
157 }
158 }
159
160 #[test]
161 fn test_constant_plus_constant() {
162 run_test(Mode::Constant, Mode::Constant);
163 }
164
165 #[test]
166 fn test_constant_plus_public() {
167 run_test(Mode::Constant, Mode::Public);
168 }
169
170 #[test]
171 fn test_public_plus_constant() {
172 run_test(Mode::Public, Mode::Constant);
173 }
174
175 #[test]
176 fn test_constant_plus_private() {
177 run_test(Mode::Constant, Mode::Private);
178 }
179
180 #[test]
181 fn test_private_plus_constant() {
182 run_test(Mode::Private, Mode::Constant);
183 }
184
185 #[test]
186 fn test_public_plus_public() {
187 run_test(Mode::Public, Mode::Public);
188 }
189
190 #[test]
191 fn test_public_plus_private() {
192 run_test(Mode::Public, Mode::Private);
193 }
194
195 #[test]
196 fn test_private_plus_public() {
197 run_test(Mode::Private, Mode::Public);
198 }
199
200 #[test]
201 fn test_private_plus_private() {
202 run_test(Mode::Private, Mode::Private);
203 }
204
205 #[test]
206 fn test_0_minus_0() {
207 let zero = console::Field::<<Circuit as Environment>::Network>::zero();
208
209 let candidate = Field::<Circuit>::zero() - Field::zero();
210 assert_eq!(zero, candidate.eject_value());
211
212 let candidate = Field::<Circuit>::zero() - &Field::zero();
213 assert_eq!(zero, candidate.eject_value());
214
215 let candidate = Field::<Circuit>::new(Mode::Public, zero) - Field::new(Mode::Public, zero);
216 assert_eq!(zero, candidate.eject_value());
217
218 let candidate = Field::<Circuit>::new(Mode::Public, zero) - Field::new(Mode::Private, zero);
219 assert_eq!(zero, candidate.eject_value());
220
221 let candidate = Field::<Circuit>::new(Mode::Private, zero) - Field::new(Mode::Private, zero);
222 assert_eq!(zero, candidate.eject_value());
223 }
224
225 #[test]
226 fn test_1_minus_0() {
227 let zero = console::Field::<<Circuit as Environment>::Network>::zero();
228 let one = console::Field::<<Circuit as Environment>::Network>::one();
229
230 let candidate = Field::<Circuit>::one() - Field::zero();
231 assert_eq!(one, candidate.eject_value());
232
233 let candidate = Field::<Circuit>::one() - &Field::zero();
234 assert_eq!(one, candidate.eject_value());
235
236 let candidate = Field::<Circuit>::new(Mode::Public, one) - Field::new(Mode::Public, zero);
237 assert_eq!(one, candidate.eject_value());
238
239 let candidate = Field::<Circuit>::new(Mode::Public, one) - Field::new(Mode::Private, zero);
240 assert_eq!(one, candidate.eject_value());
241
242 let candidate = Field::<Circuit>::new(Mode::Private, one) - Field::new(Mode::Private, zero);
243 assert_eq!(one, candidate.eject_value());
244 }
245
246 #[test]
247 fn test_1_minus_1() {
248 let zero = console::Field::<<Circuit as Environment>::Network>::zero();
249 let one = console::Field::<<Circuit as Environment>::Network>::one();
250
251 let candidate = Field::<Circuit>::one() - Field::one();
252 assert_eq!(zero, candidate.eject_value());
253
254 let candidate = Field::<Circuit>::one() - &Field::one();
255 assert_eq!(zero, candidate.eject_value());
256
257 let candidate = Field::<Circuit>::new(Mode::Public, one) - Field::new(Mode::Public, one);
258 assert_eq!(zero, candidate.eject_value());
259
260 let candidate = Field::<Circuit>::new(Mode::Private, one) - Field::new(Mode::Public, one);
261 assert_eq!(zero, candidate.eject_value());
262
263 let candidate = Field::<Circuit>::new(Mode::Private, one) - Field::new(Mode::Private, one);
264 assert_eq!(zero, candidate.eject_value());
265 }
266
267 #[test]
268 fn test_2_minus_1() {
269 let one = console::Field::<<Circuit as Environment>::Network>::one();
270 let two = one + one;
271
272 let candidate_two = Field::<Circuit>::one() + Field::one();
273 let candidate = candidate_two - Field::one();
274 assert_eq!(one, candidate.eject_value());
275
276 let candidate_two = Field::<Circuit>::one() + &Field::one();
277 let candidate = candidate_two - &Field::one();
278 assert_eq!(one, candidate.eject_value());
279
280 let candidate = Field::<Circuit>::new(Mode::Public, two) - Field::new(Mode::Public, one);
281 assert_eq!(one, candidate.eject_value());
282
283 let candidate = Field::<Circuit>::new(Mode::Private, two) - Field::new(Mode::Public, one);
284 assert_eq!(one, candidate.eject_value());
285
286 let candidate = Field::<Circuit>::new(Mode::Private, two) - Field::new(Mode::Private, one);
287 assert_eq!(one, candidate.eject_value());
288 }
289}