binius_field/arch/portable/
pairwise_arithmetic.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use crate::{
4	arch::PairwiseStrategy,
5	arithmetic_traits::{
6		InvertOrZero, MulAlpha, Square, TaggedInvertOrZero, TaggedMul, TaggedMulAlpha, TaggedSquare,
7	},
8	linear_transformation::Transformation,
9	packed::PackedField,
10};
11
12impl<PT: PackedField> TaggedMul<PairwiseStrategy> for PT {
13	#[inline]
14	fn mul(self, b: Self) -> Self {
15		if PT::WIDTH == 1 {
16			// fallback to be able to benchmark this strategy
17			self * b
18		} else {
19			Self::from_fn(|i| self.get(i) * b.get(i))
20		}
21	}
22}
23
24impl<PT: PackedField> TaggedSquare<PairwiseStrategy> for PT
25where
26	PT::Scalar: Square,
27{
28	#[inline]
29	fn square(self) -> Self {
30		if PT::WIDTH == 1 {
31			// fallback to be able to benchmark this strategy
32			PackedField::square(self)
33		} else {
34			Self::from_fn(|i| Square::square(self.get(i)))
35		}
36	}
37}
38
39impl<PT: PackedField> TaggedInvertOrZero<PairwiseStrategy> for PT
40where
41	PT::Scalar: InvertOrZero,
42{
43	#[inline]
44	fn invert_or_zero(self) -> Self {
45		if PT::WIDTH == 1 {
46			// fallback to be able to benchmark this strategy
47			PackedField::invert_or_zero(self)
48		} else {
49			Self::from_fn(|i| InvertOrZero::invert_or_zero(self.get(i)))
50		}
51	}
52}
53
54impl<PT: PackedField + MulAlpha> TaggedMulAlpha<PairwiseStrategy> for PT
55where
56	PT::Scalar: MulAlpha,
57{
58	#[inline]
59	fn mul_alpha(self) -> Self {
60		if PT::WIDTH == 1 {
61			// fallback to be able to benchmark this strategy
62			MulAlpha::mul_alpha(self)
63		} else {
64			Self::from_fn(|i| MulAlpha::mul_alpha(self.get(i)))
65		}
66	}
67}
68
69/// Per element transformation
70pub struct PairwiseTransformation<I> {
71	inner: I,
72}
73
74impl<I> PairwiseTransformation<I> {
75	pub const fn new(inner: I) -> Self {
76		Self { inner }
77	}
78}
79
80impl<IP, OP, IF, OF, I> Transformation<IP, OP> for PairwiseTransformation<I>
81where
82	IP: PackedField<Scalar = IF>,
83	OP: PackedField<Scalar = OF>,
84	I: Transformation<IF, OF>,
85{
86	fn transform(&self, data: &IP) -> OP {
87		OP::from_fn(|i| self.inner.transform(&data.get(i)))
88	}
89}