Skip to main content

binius_field/
binary_field_arithmetic.rs

1// Copyright 2023-2025 Irreducible Inc.
2
3use std::ops::Mul;
4
5use super::{
6	arithmetic_traits::{InvertOrZero, Square},
7	binary_field::BinaryField1b,
8};
9use crate::PackedField;
10
11macro_rules! impl_arithmetic_using_packed {
12	($name:ident) => {
13		impl InvertOrZero for $name {
14			#[inline]
15			fn invert_or_zero(self) -> Self {
16				use $crate::packed_extension::PackedSubfield;
17
18				$crate::binary_field_arithmetic::invert_or_zero_using_packed::<
19					PackedSubfield<Self, Self>,
20				>(self)
21			}
22		}
23
24		impl ::core::ops::Mul<$name> for $name {
25			type Output = $name;
26
27			#[inline]
28			fn mul(self, rhs: $name) -> $name {
29				use $crate::packed_extension::PackedSubfield;
30
31				$crate::tracing::trace_multiplication!($name);
32				$crate::binary_field_arithmetic::multiple_using_packed::<PackedSubfield<Self, Self>>(
33					self, rhs,
34				)
35			}
36		}
37
38		impl $crate::arithmetic_traits::Square for $name {
39			#[inline]
40			fn square(self) -> Self {
41				use $crate::packed_extension::PackedSubfield;
42
43				$crate::binary_field_arithmetic::square_using_packed::<PackedSubfield<Self, Self>>(
44					self,
45				)
46			}
47		}
48	};
49}
50
51pub(crate) use impl_arithmetic_using_packed;
52
53impl InvertOrZero for BinaryField1b {
54	#[inline]
55	fn invert_or_zero(self) -> Self {
56		self
57	}
58}
59
60#[allow(clippy::suspicious_arithmetic_impl)]
61impl Mul<BinaryField1b> for BinaryField1b {
62	type Output = Self;
63
64	#[inline]
65	fn mul(self, rhs: Self) -> Self::Output {
66		crate::tracing::trace_multiplication!(BinaryField1b);
67		Self(self.0 & rhs.0)
68	}
69}
70
71impl Square for BinaryField1b {
72	#[inline]
73	fn square(self) -> Self {
74		self
75	}
76}
77
78/// For some architectures it may be faster to used SIM versions for packed fields than to use
79/// portable single-element arithmetics. That's why we need these functions
80#[inline]
81pub(super) fn multiple_using_packed<P: PackedField>(lhs: P::Scalar, rhs: P::Scalar) -> P::Scalar {
82	(P::set_single(lhs) * P::set_single(rhs)).get(0)
83}
84
85#[inline]
86pub(super) fn square_using_packed<P: PackedField>(value: P::Scalar) -> P::Scalar {
87	P::set_single(value).square().get(0)
88}
89
90#[inline]
91pub(super) fn invert_or_zero_using_packed<P: PackedField>(value: P::Scalar) -> P::Scalar {
92	P::set_single(value).invert_or_zero().get(0)
93}