binius_field/
binary_field_arithmetic.rs

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