1pub use bigint::{Invert, Reduce};
4pub use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, SubAssign};
5
6use crate::CurveGroup;
7use core::iter;
8use ff::Field;
9use subtle::{Choice, CtOption};
10
11#[cfg(feature = "alloc")]
12use alloc::{borrow::ToOwned, vec::Vec};
13
14pub trait BatchInvert<FieldElements: ?Sized> {
17 type Output;
19
20 fn batch_invert(field_elements: FieldElements) -> <Self as BatchInvert<FieldElements>>::Output;
22}
23
24impl<const N: usize, T> BatchInvert<[T; N]> for T
25where
26 T: Field,
27{
28 type Output = CtOption<[Self; N]>;
29
30 fn batch_invert(mut field_elements: [Self; N]) -> CtOption<[Self; N]> {
31 let mut field_elements_pad = [Self::default(); N];
32 let inversion_succeeded =
33 invert_batch_internal(&mut field_elements, &mut field_elements_pad, invert);
34
35 CtOption::new(field_elements, inversion_succeeded)
36 }
37}
38
39#[cfg(feature = "alloc")]
40impl<'this, T> BatchInvert<&'this mut [Self]> for T
41where
42 T: Field,
43{
44 type Output = CtOption<&'this mut [Self]>;
45
46 fn batch_invert(field_elements: &'this mut [Self]) -> CtOption<&'this mut [Self]> {
47 let mut field_elements_pad: Vec<Self> = vec![Self::default(); field_elements.len()];
48 let inversion_succeeded =
49 invert_batch_internal(field_elements, &mut field_elements_pad, invert);
50
51 CtOption::new(field_elements, inversion_succeeded)
52 }
53}
54
55#[cfg(feature = "alloc")]
56impl<T> BatchInvert<&[Self]> for T
57where
58 T: Field,
59{
60 type Output = CtOption<Vec<Self>>;
61
62 fn batch_invert(field_elements: &[Self]) -> CtOption<Vec<Self>> {
63 let mut field_elements: Vec<Self> = field_elements.to_owned();
64 let mut field_elements_pad: Vec<Self> = vec![Self::default(); field_elements.len()];
65 let inversion_succeeded =
66 invert_batch_internal(&mut field_elements, &mut field_elements_pad, invert);
67
68 CtOption::new(field_elements, inversion_succeeded)
69 }
70}
71
72#[cfg(feature = "alloc")]
73impl<T> BatchInvert<Vec<Self>> for T
74where
75 T: Field,
76{
77 type Output = CtOption<Vec<Self>>;
78
79 fn batch_invert(mut field_elements: Vec<Self>) -> CtOption<Vec<Self>> {
80 let mut field_elements_pad: Vec<Self> = vec![Self::default(); field_elements.len()];
81 let inversion_succeeded =
82 invert_batch_internal(&mut field_elements, &mut field_elements_pad, invert);
83
84 CtOption::new(field_elements, inversion_succeeded)
85 }
86}
87
88fn invert<T: Field>(scalar: T) -> (T, Choice) {
89 let scalar = scalar.invert();
90 let choice = scalar.is_some();
91 let scalar = scalar.unwrap_or(T::default());
92
93 (scalar, choice)
94}
95
96pub(crate) fn invert_batch_internal<T: Copy + Mul<Output = T> + MulAssign>(
103 field_elements: &mut [T],
104 field_elements_pad: &mut [T],
105 invert: fn(T) -> (T, Choice),
106) -> Choice {
107 let batch_size = field_elements.len();
108 if batch_size != field_elements_pad.len() {
109 return Choice::from(0);
110 }
111 if batch_size == 0 {
112 return Choice::from(1);
113 }
114
115 let mut acc = field_elements[0];
116 field_elements_pad[0] = acc;
117
118 for (field_element, field_element_pad) in field_elements
119 .iter_mut()
120 .zip(field_elements_pad.iter_mut())
121 .skip(1)
122 {
123 acc *= *field_element;
125 *field_element_pad = acc;
126 }
127
128 let (mut acc, choice) = invert(acc);
129
130 let field_elements_pad = field_elements_pad
132 .iter()
133 .rev()
134 .skip(1)
135 .map(Some)
136 .chain(iter::once(None));
137
138 for (field_element, field_element_pad) in
139 field_elements.iter_mut().rev().zip(field_elements_pad)
140 {
141 if let Some(field_element_pad) = field_element_pad {
142 let tmp = acc * *field_element;
145 *field_element = acc * *field_element_pad;
147 acc = tmp;
148 } else {
149 *field_element = acc;
150 }
151 }
152
153 choice
154}
155
156pub trait LinearCombination<PointsAndScalars>: CurveGroup
163where
164 PointsAndScalars: AsRef<[(Self, Self::Scalar)]> + ?Sized,
165{
166 fn lincomb(points_and_scalars: &PointsAndScalars) -> Self {
168 points_and_scalars
169 .as_ref()
170 .iter()
171 .copied()
172 .map(|(point, scalar)| point * scalar)
173 .sum()
174 }
175}
176
177pub trait ReduceNonZero<T>: Reduce<T> {
185 fn reduce_nonzero(n: &T) -> Self;
187}