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);