binius_field/arch/portable/
scaled_arithmetic.rs

1// Copyright 2025 The Binius Developers
2
3use std::array;
4
5use bytemuck::{Pod, TransparentWrapper};
6
7use super::packed::PackedPrimitiveType;
8use crate::{
9	BinaryField,
10	arch::ScaledStrategy,
11	arithmetic_traits::{
12		InvertOrZero, MulAlpha, Square, TaggedInvertOrZero, TaggedMul, TaggedMulAlpha, TaggedSquare,
13	},
14	underlier::{ScaledUnderlier, UnderlierType},
15};
16
17impl<U: UnderlierType + Pod, Scalar: BinaryField, const N: usize> TaggedMul<ScaledStrategy>
18	for PackedPrimitiveType<ScaledUnderlier<U, N>, Scalar>
19where
20	PackedPrimitiveType<U, Scalar>: std::ops::Mul<Output = PackedPrimitiveType<U, Scalar>>,
21{
22	fn mul(self, rhs: Self) -> Self {
23		Self::wrap(ScaledUnderlier(array::from_fn(|i| {
24			let lhs_i = self.0.0[i];
25			let rhs_i = rhs.0.0[i];
26			PackedPrimitiveType::peel(
27				PackedPrimitiveType::wrap(lhs_i) * PackedPrimitiveType::wrap(rhs_i),
28			)
29		})))
30	}
31}
32
33impl<U: UnderlierType + Pod, Scalar: BinaryField, const N: usize> TaggedMulAlpha<ScaledStrategy>
34	for PackedPrimitiveType<ScaledUnderlier<U, N>, Scalar>
35where
36	PackedPrimitiveType<U, Scalar>: MulAlpha,
37{
38	fn mul_alpha(self) -> Self {
39		Self::wrap(ScaledUnderlier(self.0.0.map(|sub_underlier| {
40			PackedPrimitiveType::peel(PackedPrimitiveType::wrap(sub_underlier).mul_alpha())
41		})))
42	}
43}
44
45impl<U: UnderlierType + Pod, Scalar: BinaryField, const N: usize> TaggedSquare<ScaledStrategy>
46	for PackedPrimitiveType<ScaledUnderlier<U, N>, Scalar>
47where
48	PackedPrimitiveType<U, Scalar>: Square,
49{
50	fn square(self) -> Self {
51		Self::wrap(ScaledUnderlier(self.0.0.map(|sub_underlier| {
52			PackedPrimitiveType::peel(PackedPrimitiveType::wrap(sub_underlier).square())
53		})))
54	}
55}
56
57impl<U: UnderlierType + Pod, Scalar: BinaryField, const N: usize> TaggedInvertOrZero<ScaledStrategy>
58	for PackedPrimitiveType<ScaledUnderlier<U, N>, Scalar>
59where
60	PackedPrimitiveType<U, Scalar>: InvertOrZero,
61{
62	fn invert_or_zero(self) -> Self {
63		Self::wrap(ScaledUnderlier(self.0.0.map(|sub_underlier| {
64			PackedPrimitiveType::peel(PackedPrimitiveType::wrap(sub_underlier).invert_or_zero())
65		})))
66	}
67}