binius_field/
arithmetic_traits.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use crate::{
4	linear_transformation::{FieldLinearTransformation, Transformation},
5	packed::PackedBinaryField,
6};
7
8/// Value that can be multiplied by itself
9pub trait Square {
10	/// Returns the value multiplied by itself
11	fn square(self) -> Self;
12}
13
14/// Value that can be inverted
15pub trait InvertOrZero {
16	/// Returns the inverted value or zero in case when `self` is zero
17	fn invert_or_zero(self) -> Self;
18}
19
20/// Value that can be multiplied by alpha
21pub trait MulAlpha {
22	/// Multiply self by alpha
23	fn mul_alpha(self) -> Self;
24}
25
26/// Value that can be filled with `Scalar`
27pub trait Broadcast<Scalar> {
28	/// Set `scalar`` value to all the positions
29	fn broadcast(scalar: Scalar) -> Self;
30}
31
32/// Multiplication that is parameterized with some some strategy.
33pub trait TaggedMul<Strategy> {
34	fn mul(self, rhs: Self) -> Self;
35}
36
37macro_rules! impl_mul_with {
38	($name:ident @ $strategy:ty) => {
39		impl std::ops::Mul for $name {
40			type Output = Self;
41
42			#[inline]
43			fn mul(self, rhs: Self) -> Self {
44				$crate::tracing::trace_multiplication!($name);
45
46				$crate::arithmetic_traits::TaggedMul::<$strategy>::mul(self, rhs)
47			}
48		}
49	};
50	($name:ty => $bigger:ty) => {
51		impl std::ops::Mul for $name {
52			type Output = Self;
53
54			#[inline]
55			fn mul(self, rhs: Self) -> Self {
56				$crate::arch::portable::packed::mul_as_bigger_type::<_, $bigger>(self, rhs)
57			}
58		}
59	};
60}
61
62pub(crate) use impl_mul_with;
63
64/// Square operation that is parameterized with some some strategy.
65pub trait TaggedSquare<Strategy> {
66	fn square(self) -> Self;
67}
68
69macro_rules! impl_square_with {
70	($name:ident @ $strategy:ty) => {
71		impl $crate::arithmetic_traits::Square for $name {
72			#[inline]
73			fn square(self) -> Self {
74				$crate::arithmetic_traits::TaggedSquare::<$strategy>::square(self)
75			}
76		}
77	};
78	($name:ty => $bigger:ty) => {
79		impl $crate::arithmetic_traits::Square for $name {
80			#[inline]
81			fn square(self) -> Self {
82				$crate::arch::portable::packed::square_as_bigger_type::<_, $bigger>(self)
83			}
84		}
85	};
86}
87
88pub(crate) use impl_square_with;
89
90/// Invert or zero operation that is parameterized with some some strategy.
91pub trait TaggedInvertOrZero<Strategy> {
92	fn invert_or_zero(self) -> Self;
93}
94
95macro_rules! impl_invert_with {
96	($name:ident @ $strategy:ty) => {
97		impl $crate::arithmetic_traits::InvertOrZero for $name {
98			#[inline]
99			fn invert_or_zero(self) -> Self {
100				$crate::arithmetic_traits::TaggedInvertOrZero::<$strategy>::invert_or_zero(self)
101			}
102		}
103	};
104	($name:ty => $bigger:ty) => {
105		impl $crate::arithmetic_traits::InvertOrZero for $name {
106			#[inline]
107			fn invert_or_zero(self) -> Self {
108				$crate::arch::portable::packed::invert_as_bigger_type::<_, $bigger>(self)
109			}
110		}
111	};
112}
113
114pub(crate) use impl_invert_with;
115
116/// Multiply by alpha operation that is parameterized with some some strategy.
117pub trait TaggedMulAlpha<Strategy> {
118	fn mul_alpha(self) -> Self;
119}
120
121macro_rules! impl_mul_alpha_with {
122	($name:ident @ $strategy:ty) => {
123		impl $crate::arithmetic_traits::MulAlpha for $name {
124			#[inline]
125			fn mul_alpha(self) -> Self {
126				$crate::arithmetic_traits::TaggedMulAlpha::<$strategy>::mul_alpha(self)
127			}
128		}
129	};
130	($name:ty => $bigger:ty) => {
131		impl $crate::arithmetic_traits::MulAlpha for $name {
132			#[inline]
133			fn mul_alpha(self) -> Self {
134				$crate::arch::portable::packed::mul_alpha_as_bigger_type::<_, $bigger>(self)
135			}
136		}
137	};
138}
139
140pub(crate) use impl_mul_alpha_with;
141
142/// Linear transformation factory that is parameterized with some strategy.
143#[allow(private_bounds)]
144pub trait TaggedPackedTransformationFactory<Strategy, OP>: PackedBinaryField
145where
146	OP: PackedBinaryField,
147{
148	type PackedTransformation<Data: AsRef<[OP::Scalar]> + Sync>: Transformation<Self, OP>;
149
150	fn make_packed_transformation<Data: AsRef<[OP::Scalar]> + Sync>(
151		transformation: FieldLinearTransformation<OP::Scalar, Data>,
152	) -> Self::PackedTransformation<Data>;
153}
154
155macro_rules! impl_transformation_with_strategy {
156	($name:ty, $strategy:ty) => {
157		impl<OP> $crate::linear_transformation::PackedTransformationFactory<OP> for $name
158		where
159			OP: $crate::packed::PackedBinaryField
160				+ $crate::underlier::WithUnderlier<
161					Underlier = <$name as $crate::underlier::WithUnderlier>::Underlier,
162				>,
163			Self: $crate::arithmetic_traits::TaggedPackedTransformationFactory<$strategy, OP>,
164		{
165			type PackedTransformation<Data: AsRef<[OP::Scalar]> + Sync> =
166				<Self as $crate::arithmetic_traits::TaggedPackedTransformationFactory<
167					$strategy,
168					OP,
169				>>::PackedTransformation<Data>;
170
171			fn make_packed_transformation<Data: AsRef<[OP::Scalar]> + Sync>(
172				transformation: $crate::linear_transformation::FieldLinearTransformation<
173					OP::Scalar,
174					Data,
175				>,
176			) -> Self::PackedTransformation<Data> {
177				<Self as $crate::arithmetic_traits::TaggedPackedTransformationFactory<
178					$strategy,
179					OP,
180				>>::make_packed_transformation(transformation)
181			}
182		}
183	};
184}
185
186pub(crate) use impl_transformation_with_strategy;