Skip to main content

binius_field/arch/portable/
pairwise_arithmetic.rs

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