fp/vector/fp_wrapper/
helpers.rs

1//! This module defines methods that assist in plumbing together methods that operate on `u32`s,
2//! such as the ones on `FpVector`, with methods that operate on `FieldElement<Fp<P>>`s, such as the
3//! ones on `FqVector`.
4//!
5//! The difficulty is that the field is necessary to make the conversion, through the
6//! `FieldInternal::el` method, but depending on the field, the return type will be different. For
7//! example, depending on whether an `FpVector` is over F2 or F3, the field element will be either
8//! `FieldElement<Fp<P2>>` or `FieldElement<Fp<P3>>`. Therefore, it is the struct itself that needs
9//! to make the conversion using its own field attribute.
10//!
11//! It would in theory be possible to just hide the conversion in a more complicated macro, but
12//! because the `u32` arguments have various names and appear in different positions in the
13//! signature of the methods, I suspect it would be a major hassle.
14
15use itertools::Itertools;
16
17use super::{FqSlice, FqSliceMut, FqVector, FqVectorIterator, FqVectorNonZeroIterator};
18use crate::field::Field;
19
20impl<F: Field> FqVector<F> {
21    pub(super) fn scale_helper(&mut self, c: F::ElementContainer) {
22        self.scale(self.fq().el(c))
23    }
24
25    pub(super) fn entry_helper(&self, index: usize) -> F::ElementContainer {
26        self.entry(index).val()
27    }
28
29    pub(super) fn set_entry_helper(&mut self, index: usize, value: F::ElementContainer) {
30        self.set_entry(index, self.fq().el(value))
31    }
32
33    pub(super) fn add_helper(&mut self, other: &Self, c: F::ElementContainer) {
34        self.add(other, self.fq().el(c))
35    }
36
37    pub(super) fn add_offset_helper(
38        &mut self,
39        other: &Self,
40        c: F::ElementContainer,
41        offset: usize,
42    ) {
43        self.add_offset(other, self.fq().el(c), offset)
44    }
45
46    pub(super) fn add_basis_element_helper(&mut self, index: usize, value: F::ElementContainer) {
47        self.add_basis_element(index, self.fq().el(value))
48    }
49
50    pub(super) fn copy_from_slice_helper(&mut self, other: &[F::ElementContainer]) {
51        self.copy_from_slice(&other.iter().map(|x| self.fq().el(x.clone())).collect_vec())
52    }
53
54    pub(super) fn add_truncate_helper(
55        &mut self,
56        other: &Self,
57        c: F::ElementContainer,
58    ) -> Option<()> {
59        self.add_truncate(other, self.fq().el(c))
60    }
61
62    pub(super) fn add_carry_helper<T>(
63        &mut self,
64        other: &Self,
65        c: F::ElementContainer,
66        rest: &mut [T],
67    ) -> bool
68    where
69        for<'a> &'a mut T: TryInto<&'a mut Self>,
70    {
71        self.add_carry(other, self.fq().el(c), rest)
72    }
73
74    pub(super) fn first_nonzero_helper(&self) -> Option<(usize, F::ElementContainer)> {
75        self.first_nonzero().map(|(idx, c)| (idx, c.val()))
76    }
77}
78
79impl<F: Field> FqSlice<'_, F> {
80    pub(super) fn entry_helper(&self, index: usize) -> F::ElementContainer {
81        self.entry(index).val()
82    }
83
84    pub(super) fn first_nonzero_helper(&self) -> Option<(usize, F::ElementContainer)> {
85        self.first_nonzero().map(|(idx, c)| (idx, c.val()))
86    }
87}
88
89impl<F: Field> FqSliceMut<'_, F> {
90    pub(super) fn scale_helper(&mut self, c: F::ElementContainer) {
91        self.scale(self.fq().el(c))
92    }
93
94    pub(super) fn add_helper(&mut self, other: FqSlice<F>, c: F::ElementContainer) {
95        self.add(other, self.fq().el(c))
96    }
97
98    pub(super) fn add_offset_helper(
99        &mut self,
100        other: FqSlice<F>,
101        c: F::ElementContainer,
102        offset: usize,
103    ) {
104        self.add_offset(other, self.fq().el(c), offset)
105    }
106
107    pub(super) fn set_entry_helper(&mut self, index: usize, value: F::ElementContainer) {
108        self.set_entry(index, self.fq().el(value))
109    }
110
111    pub(super) fn add_basis_element_helper(&mut self, index: usize, value: F::ElementContainer) {
112        self.add_basis_element(index, self.fq().el(value))
113    }
114
115    pub(super) fn add_masked_helper(
116        &mut self,
117        other: FqSlice<F>,
118        c: F::ElementContainer,
119        mask: &[usize],
120    ) {
121        self.add_masked(other, self.fq().el(c), mask)
122    }
123
124    pub(super) fn add_unmasked_helper(
125        &mut self,
126        other: FqSlice<F>,
127        c: F::ElementContainer,
128        mask: &[usize],
129    ) {
130        self.add_unmasked(other, self.fq().el(c), mask)
131    }
132
133    pub(super) fn add_tensor_helper(
134        &mut self,
135        offset: usize,
136        coeff: F::ElementContainer,
137        left: FqSlice<F>,
138        right: FqSlice<F>,
139    ) {
140        self.add_tensor(offset, self.fq().el(coeff), left, right)
141    }
142}
143
144impl<F: Field> FqVectorIterator<'_, F> {
145    pub(super) fn next_helper(&mut self) -> Option<F::ElementContainer> {
146        self.next().map(|x| x.val())
147    }
148}
149
150impl<F: Field> FqVectorNonZeroIterator<'_, F> {
151    pub(super) fn next_helper(&mut self) -> Option<(usize, F::ElementContainer)> {
152        self.next().map(|x| (x.0, x.1.val()))
153    }
154}