binius_field/underlier/
underlier_type.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use std::fmt::Debug;
4
5use bytemuck::{NoUninit, Zeroable};
6use rand::{
7	distributions::{Distribution, Standard},
8	Rng, RngCore,
9};
10use subtle::ConstantTimeEq;
11
12/// Primitive integer underlying a binary field or packed binary field implementation.
13/// Note that this type is not guaranteed to be POD, U1, U2 and U4 have some unused bits.
14pub trait UnderlierType:
15	Debug
16	+ Default
17	+ PartialEq
18	+ Eq
19	+ PartialOrd
20	+ Ord
21	+ ConstantTimeEq
22	+ Copy
23	+ Random
24	+ NoUninit
25	+ Zeroable
26	+ Sized
27	+ Send
28	+ Sync
29	+ 'static
30{
31	/// Number of bits in value
32	const LOG_BITS: usize;
33	/// Number of bits used to represent a value.
34	/// This may not be equal to the number of bits in a type instance.
35	const BITS: usize = 1 << Self::LOG_BITS;
36}
37
38/// A type that is transparently backed by an underlier.
39///
40/// This trait is needed to make it possible getting the underlier type from already defined type.
41/// Bidirectional `From` trait implementations are not enough, because they do not allow getting underlier type
42/// in a generic code.
43///
44/// # Safety
45/// `WithUnderlier` can be implemented for a type only if it's representation is a transparent `Underlier`'s representation.
46/// That's allows us casting references of type and it's underlier in both directions.
47pub unsafe trait WithUnderlier: Sized + Zeroable + Copy + Send + Sync + 'static {
48	/// Underlier primitive type
49	type Underlier: UnderlierType;
50
51	/// Convert value to underlier.
52	fn to_underlier(self) -> Self::Underlier;
53
54	fn to_underlier_ref(&self) -> &Self::Underlier;
55
56	fn to_underlier_ref_mut(&mut self) -> &mut Self::Underlier;
57
58	fn to_underliers_ref(val: &[Self]) -> &[Self::Underlier];
59
60	fn to_underliers_ref_mut(val: &mut [Self]) -> &mut [Self::Underlier];
61
62	fn from_underlier(val: Self::Underlier) -> Self;
63
64	fn from_underlier_ref(val: &Self::Underlier) -> &Self;
65
66	fn from_underlier_ref_mut(val: &mut Self::Underlier) -> &mut Self;
67
68	fn from_underliers_ref(val: &[Self::Underlier]) -> &[Self];
69
70	fn from_underliers_ref_mut(val: &mut [Self::Underlier]) -> &mut [Self];
71
72	#[inline]
73	fn mutate_underlier(self, f: impl FnOnce(Self::Underlier) -> Self::Underlier) -> Self {
74		Self::from_underlier(f(self.to_underlier()))
75	}
76}
77
78unsafe impl<U: UnderlierType> WithUnderlier for U {
79	type Underlier = U;
80
81	#[inline]
82	fn to_underlier(self) -> Self::Underlier {
83		self
84	}
85
86	#[inline]
87	fn to_underlier_ref(&self) -> &Self::Underlier {
88		self
89	}
90
91	#[inline]
92	fn to_underlier_ref_mut(&mut self) -> &mut Self::Underlier {
93		self
94	}
95
96	#[inline]
97	fn to_underliers_ref(val: &[Self]) -> &[Self::Underlier] {
98		val
99	}
100
101	#[inline]
102	fn to_underliers_ref_mut(val: &mut [Self]) -> &mut [Self::Underlier] {
103		val
104	}
105
106	#[inline]
107	fn from_underlier(val: Self::Underlier) -> Self {
108		val
109	}
110
111	#[inline]
112	fn from_underlier_ref(val: &Self::Underlier) -> &Self {
113		val
114	}
115
116	#[inline]
117	fn from_underlier_ref_mut(val: &mut Self::Underlier) -> &mut Self {
118		val
119	}
120
121	#[inline]
122	fn from_underliers_ref(val: &[Self::Underlier]) -> &[Self] {
123		val
124	}
125
126	#[inline]
127	fn from_underliers_ref_mut(val: &mut [Self::Underlier]) -> &mut [Self] {
128		val
129	}
130}
131
132/// A value that can be randomly generated
133pub trait Random {
134	/// Generate random value
135	fn random(rng: impl RngCore) -> Self;
136}
137
138impl<T> Random for T
139where
140	Standard: Distribution<T>,
141{
142	fn random(mut rng: impl RngCore) -> Self {
143		rng.gen()
144	}
145}
146
147/// A trait that represents potentially lossy numeric cast.
148/// Is a drop-in replacement of `as _` in a generic code.
149pub trait NumCast<From> {
150	fn num_cast_from(val: From) -> Self;
151}
152
153impl<U: UnderlierType> NumCast<U> for U {
154	#[inline(always)]
155	fn num_cast_from(val: U) -> Self {
156		val
157	}
158}