arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/fields/nonnative/mul_result.rs
src/fields/nonnative/mul_result.rsRaw
 1use super::{AllocatedNonNativeFieldMulResultVar, NonNativeFieldVar};
 2use ark_ff::PrimeField;
 3use ark_relations::r1cs::Result as R1CSResult;
 4
 5/// An intermediate representation especially for the result of a
 6/// multiplication, containing more limbs. It is intended for advanced usage to
 7/// improve the efficiency.
 8///
 9/// That is, instead of calling `mul`, one can call `mul_without_reduce` to
10/// obtain this intermediate representation, which can still be added.
11/// Then, one can call `reduce` to reduce it back to `NonNativeFieldVar`.
12/// This may help cut the number of reduce operations.
13#[derive(Debug)]
14#[must_use]
15pub enum NonNativeFieldMulResultVar<TargetField: PrimeField, BaseField: PrimeField> {
16    /// as a constant
17    Constant(TargetField),
18    /// as an allocated gadget
19    Var(AllocatedNonNativeFieldMulResultVar<TargetField, BaseField>),
20}
21
22impl<TargetField: PrimeField, BaseField: PrimeField>
23    NonNativeFieldMulResultVar<TargetField, BaseField>
24{
25    /// Create a zero `NonNativeFieldMulResultVar` (used for additions)
26    pub fn zero() -> Self {
27        Self::Constant(TargetField::zero())
28    }
29
30    /// Create an `NonNativeFieldMulResultVar` from a constant
31    pub fn constant(v: TargetField) -> Self {
32        Self::Constant(v)
33    }
34
35    /// Reduce the `NonNativeFieldMulResultVar` back to NonNativeFieldVar
36    #[tracing::instrument(target = "r1cs")]
37    pub fn reduce(&self) -> R1CSResult<NonNativeFieldVar<TargetField, BaseField>> {
38        match self {
39            Self::Constant(c) => Ok(NonNativeFieldVar::Constant(*c)),
40            Self::Var(v) => Ok(NonNativeFieldVar::Var(v.reduce()?)),
41        }
42    }
43}
44
45impl<TargetField: PrimeField, BaseField: PrimeField>
46    From<&NonNativeFieldVar<TargetField, BaseField>>
47    for NonNativeFieldMulResultVar<TargetField, BaseField>
48{
49    fn from(src: &NonNativeFieldVar<TargetField, BaseField>) -> Self {
50        match src {
51            NonNativeFieldVar::Constant(c) => NonNativeFieldMulResultVar::Constant(*c),
52            NonNativeFieldVar::Var(v) => {
53                NonNativeFieldMulResultVar::Var(AllocatedNonNativeFieldMulResultVar::<
54                    TargetField,
55                    BaseField,
56                >::from(v))
57            },
58        }
59    }
60}
61
62impl_bounded_ops!(
63    NonNativeFieldMulResultVar<TargetField, BaseField>,
64    TargetField,
65    Add,
66    add,
67    AddAssign,
68    add_assign,
69    |this: &'a NonNativeFieldMulResultVar<TargetField, BaseField>, other: &'a NonNativeFieldMulResultVar<TargetField, BaseField>| {
70        use NonNativeFieldMulResultVar::*;
71        match (this, other) {
72            (Constant(c1), Constant(c2)) => Constant(*c1 + c2),
73            (Constant(c), Var(v)) | (Var(v), Constant(c)) => Var(v.add_constant(c).unwrap()),
74            (Var(v1), Var(v2)) => Var(v1.add(v2).unwrap()),
75        }
76    },
77    |this: &'a NonNativeFieldMulResultVar<TargetField, BaseField>, other: TargetField| { this + &NonNativeFieldMulResultVar::Constant(other) },
78    (TargetField: PrimeField, BaseField: PrimeField),
79);