binius_field/arch/portable/
pairwise_recursive_arithmetic.rs1use crate::{
4 arch::PairwiseRecursiveStrategy,
5 arithmetic_traits::{
6 InvertOrZero, MulAlpha, Square, TaggedInvertOrZero, TaggedMul, TaggedMulAlpha, TaggedSquare,
7 },
8 packed::PackedField,
9 TowerExtensionField,
10};
11
12impl<P> TaggedMul<PairwiseRecursiveStrategy> for P
13where
14 P: PackedField,
15 P::Scalar: TowerExtensionField<DirectSubfield: MulAlpha>,
16{
17 #[inline]
18 fn mul(self, rhs: Self) -> Self {
19 P::from_fn(|i| {
20 let (a0, a1) = self.get(i).into();
21 let (b0, b1) = rhs.get(i).into();
22 let (z0, z2) = (a0 * b0, a1 * b1);
23 let z0z2 = z0 + z2;
24 let z1 = (a0 + a1) * (b0 + b1) - z0z2;
25 let z2a = MulAlpha::mul_alpha(z2);
26
27 (z0z2, z1 + z2a).into()
28 })
29 }
30}
31
32impl<P> TaggedSquare<PairwiseRecursiveStrategy> for P
33where
34 P: PackedField,
35 P::Scalar: TowerExtensionField<DirectSubfield: MulAlpha>,
36{
37 #[inline]
38 fn square(self) -> Self {
39 P::from_fn(|i| {
40 let (a0, a1) = self.get(i).into();
41 let (z0, z2) = (Square::square(a0), Square::square(a1));
42 let z2a = MulAlpha::mul_alpha(z2);
43 (z0 + z2, z2a).into()
44 })
45 }
46}
47
48impl<P> TaggedMulAlpha<PairwiseRecursiveStrategy> for P
49where
50 P: PackedField,
51 P::Scalar: TowerExtensionField<DirectSubfield: MulAlpha>,
52{
53 #[inline]
54 fn mul_alpha(self) -> Self {
55 P::from_fn(|i| {
56 let (a0, a1) = self.get(i).into();
57 let z1 = MulAlpha::mul_alpha(a1);
58
59 (a1, a0 + z1).into()
60 })
61 }
62}
63
64impl<P> TaggedInvertOrZero<PairwiseRecursiveStrategy> for P
65where
66 P: PackedField,
67 P::Scalar: TowerExtensionField<DirectSubfield: MulAlpha + InvertOrZero>,
68{
69 #[inline]
70 fn invert_or_zero(self) -> Self {
71 P::from_fn(|i| {
72 let (a0, a1) = self.get(i).into();
73 let a0z1 = a0 + MulAlpha::mul_alpha(a1);
74 let delta = a0 * a0z1 + Square::square(a1);
75 let delta_inv = InvertOrZero::invert_or_zero(delta);
76 let inv0 = delta_inv * a0z1;
77 let inv1 = delta_inv * a1;
78 (inv0, inv1).into()
79 })
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use crate::test_utils::{
87 define_invert_tests, define_mul_alpha_tests, define_multiply_tests, define_square_tests,
88 };
89
90 define_multiply_tests!(
91 TaggedMul<PairwiseRecursiveStrategy>::mul,
92 TaggedMul<PairwiseRecursiveStrategy>
93 );
94
95 define_square_tests!(
96 TaggedSquare<PairwiseRecursiveStrategy>::square,
97 TaggedSquare<PairwiseRecursiveStrategy>
98 );
99
100 define_invert_tests!(
101 TaggedInvertOrZero<PairwiseRecursiveStrategy>::invert_or_zero,
102 TaggedInvertOrZero<PairwiseRecursiveStrategy>
103 );
104
105 define_mul_alpha_tests!(
106 TaggedMulAlpha<PairwiseRecursiveStrategy>::mul_alpha,
107 TaggedMulAlpha<PairwiseRecursiveStrategy>
108 );
109}