binius_field/arch/portable/
pairwise_arithmetic.rs1use crate::{
4 arch::PairwiseStrategy,
5 arithmetic_traits::{
6 InvertOrZero, MulAlpha, Square, TaggedInvertOrZero, TaggedMul, TaggedMulAlpha,
7 TaggedPackedTransformationFactory, TaggedSquare,
8 },
9 linear_transformation::{FieldLinearTransformation, Transformation},
10 packed::{PackedBinaryField, PackedField},
11};
12
13impl<PT: PackedField> TaggedMul<PairwiseStrategy> for PT {
14 #[inline]
15 fn mul(self, b: Self) -> Self {
16 if PT::WIDTH == 1 {
17 self * b
19 } else {
20 Self::from_fn(|i| self.get(i) * b.get(i))
21 }
22 }
23}
24
25impl<PT: PackedField> TaggedSquare<PairwiseStrategy> for PT
26where
27 PT::Scalar: Square,
28{
29 #[inline]
30 fn square(self) -> Self {
31 if PT::WIDTH == 1 {
32 PackedField::square(self)
34 } else {
35 Self::from_fn(|i| Square::square(self.get(i)))
36 }
37 }
38}
39
40impl<PT: PackedField> TaggedInvertOrZero<PairwiseStrategy> for PT
41where
42 PT::Scalar: InvertOrZero,
43{
44 #[inline]
45 fn invert_or_zero(self) -> Self {
46 if PT::WIDTH == 1 {
47 PackedField::invert_or_zero(self)
49 } else {
50 Self::from_fn(|i| InvertOrZero::invert_or_zero(self.get(i)))
51 }
52 }
53}
54
55impl<PT: PackedField + MulAlpha> TaggedMulAlpha<PairwiseStrategy> for PT
56where
57 PT::Scalar: MulAlpha,
58{
59 #[inline]
60 fn mul_alpha(self) -> Self {
61 if PT::WIDTH == 1 {
62 MulAlpha::mul_alpha(self)
64 } else {
65 Self::from_fn(|i| MulAlpha::mul_alpha(self.get(i)))
66 }
67 }
68}
69
70pub struct PairwiseTransformation<I> {
72 inner: I,
73}
74
75impl<I> PairwiseTransformation<I> {
76 pub const fn new(inner: I) -> Self {
77 Self { inner }
78 }
79}
80
81impl<IP, OP, IF, OF, I> Transformation<IP, OP> for PairwiseTransformation<I>
82where
83 IP: PackedField<Scalar = IF>,
84 OP: PackedField<Scalar = OF>,
85 I: Transformation<IF, OF>,
86{
87 fn transform(&self, data: &IP) -> OP {
88 OP::from_fn(|i| self.inner.transform(&data.get(i)))
89 }
90}
91
92impl<IP, OP> TaggedPackedTransformationFactory<PairwiseStrategy, OP> for IP
93where
94 IP: PackedBinaryField,
95 OP: PackedBinaryField,
96{
97 type PackedTransformation<Data: AsRef<[OP::Scalar]> + Sync> =
98 PairwiseTransformation<FieldLinearTransformation<OP::Scalar, Data>>;
99
100 fn make_packed_transformation<Data: AsRef<[OP::Scalar]> + Sync>(
101 transformation: FieldLinearTransformation<OP::Scalar, Data>,
102 ) -> Self::PackedTransformation<Data> {
103 PairwiseTransformation::new(transformation)
104 }
105}