ark_r1cs_std/uint/add/
wrapping.rs1use ark_ff::PrimeField;
2use ark_relations::r1cs::SynthesisError;
3
4use crate::uint::*;
5use crate::R1CSVar;
6
7impl<const N: usize, T: PrimUInt, F: PrimeField> UInt<N, T, F> {
8 pub fn wrapping_add_in_place(&mut self, other: &Self) {
10 let result = Self::wrapping_add_many(&[self.clone(), other.clone()]).unwrap();
11 *self = result;
12 }
13
14 pub fn wrapping_add(&self, other: &Self) -> Self {
16 let mut result = self.clone();
17 result.wrapping_add_in_place(other);
18 result
19 }
20
21 #[tracing::instrument(target = "r1cs", skip(operands))]
26 pub fn wrapping_add_many(operands: &[Self]) -> Result<Self, SynthesisError>
27 where
28 F: PrimeField,
29 {
30 let (mut sum_bits, value) = Self::add_many_helper(operands, |a, b| a.wrapping_add(&b))?;
31 if operands.is_constant() {
32 Ok(UInt::constant(value.unwrap()))
35 } else {
36 sum_bits.truncate(N);
37 Ok(UInt {
38 bits: sum_bits.try_into().unwrap(),
39 value,
40 })
41 }
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::{
49 alloc::{AllocVar, AllocationMode},
50 prelude::EqGadget,
51 uint::test_utils::{run_binary_exhaustive, run_binary_random},
52 R1CSVar,
53 };
54 use ark_ff::PrimeField;
55 use ark_test_curves::bls12_381::Fr;
56
57 fn uint_wrapping_add<T: PrimUInt, const N: usize, F: PrimeField>(
58 a: UInt<N, T, F>,
59 b: UInt<N, T, F>,
60 ) -> Result<(), SynthesisError> {
61 let cs = a.cs().or(b.cs());
62 let both_constant = a.is_constant() && b.is_constant();
63 let computed = a.wrapping_add(&b);
64 let expected_mode = if both_constant {
65 AllocationMode::Constant
66 } else {
67 AllocationMode::Witness
68 };
69 let expected = UInt::new_variable(
70 cs.clone(),
71 || Ok(a.value()?.wrapping_add(&b.value()?)),
72 expected_mode,
73 )?;
74 assert_eq!(expected.value(), computed.value());
75 expected.enforce_equal(&computed)?;
76 if !both_constant {
77 assert!(cs.is_satisfied().unwrap());
78 }
79 Ok(())
80 }
81
82 #[test]
83 fn u8_wrapping_add() {
84 run_binary_exhaustive(uint_wrapping_add::<u8, 8, Fr>).unwrap()
85 }
86
87 #[test]
88 fn u16_wrapping_add() {
89 run_binary_random::<1000, 16, _, _>(uint_wrapping_add::<u16, 16, Fr>).unwrap()
90 }
91
92 #[test]
93 fn u32_wrapping_add() {
94 run_binary_random::<1000, 32, _, _>(uint_wrapping_add::<u32, 32, Fr>).unwrap()
95 }
96
97 #[test]
98 fn u64_wrapping_add() {
99 run_binary_random::<1000, 64, _, _>(uint_wrapping_add::<u64, 64, Fr>).unwrap()
100 }
101
102 #[test]
103 fn u128_wrapping_add() {
104 run_binary_random::<1000, 128, _, _>(uint_wrapping_add::<u128, 128, Fr>).unwrap()
105 }
106}