1use crate::packable::PackedFlat;
22use crate::{PackableField, TowerField};
23use core::fmt::{self, Debug, Formatter};
24use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
25use zeroize::Zeroize;
26
27pub trait HardwareField: TowerField + PackableField {
30 fn to_hardware(self) -> Flat<Self>;
32
33 fn from_hardware(value: Flat<Self>) -> Self;
35
36 fn add_hardware(lhs: Flat<Self>, rhs: Flat<Self>) -> Flat<Self>;
38
39 fn add_hardware_packed(lhs: PackedFlat<Self>, rhs: PackedFlat<Self>) -> PackedFlat<Self>;
41
42 fn mul_hardware(lhs: Flat<Self>, rhs: Flat<Self>) -> Flat<Self>;
44
45 fn mul_hardware_packed(lhs: PackedFlat<Self>, rhs: PackedFlat<Self>) -> PackedFlat<Self>;
47
48 fn mul_hardware_scalar_packed(lhs: PackedFlat<Self>, rhs: Flat<Self>) -> PackedFlat<Self>;
50
51 fn tower_bit_from_hardware(value: Flat<Self>, bit_idx: usize) -> u8;
57}
58
59#[derive(Copy, Clone, Default, PartialEq, Eq, Zeroize)]
61#[repr(transparent)]
62pub struct Flat<F>(F);
63
64impl<F> Flat<F> {
65 #[inline(always)]
67 pub fn from_raw(raw: F) -> Self {
68 Self(raw)
69 }
70
71 #[inline(always)]
73 pub fn into_raw(self) -> F {
74 self.0
75 }
76
77 #[inline(always)]
79 pub fn as_raw(&self) -> &F {
80 &self.0
81 }
82}
83
84impl<F: Debug> Debug for Flat<F> {
85 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86 f.debug_tuple("Flat").field(&self.0).finish()
87 }
88}
89
90impl<F: HardwareField> Flat<F> {
91 #[inline(always)]
93 pub fn to_tower(self) -> F {
94 F::from_hardware(self)
95 }
96
97 #[inline(always)]
102 pub fn tower_bit(self, bit_idx: usize) -> u8 {
103 F::tower_bit_from_hardware(self, bit_idx)
104 }
105}
106
107impl<F: HardwareField> Add for Flat<F> {
108 type Output = Self;
109
110 #[inline(always)]
111 fn add(self, rhs: Self) -> Self::Output {
112 F::add_hardware(self, rhs)
113 }
114}
115
116impl<F: HardwareField> AddAssign for Flat<F> {
117 #[inline(always)]
118 fn add_assign(&mut self, rhs: Self) {
119 *self = *self + rhs;
120 }
121}
122
123impl<F: HardwareField> Sub for Flat<F> {
124 type Output = Self;
125
126 #[inline(always)]
127 fn sub(self, rhs: Self) -> Self::Output {
128 F::add_hardware(self, rhs)
129 }
130}
131
132impl<F: HardwareField> SubAssign for Flat<F> {
133 #[inline(always)]
134 fn sub_assign(&mut self, rhs: Self) {
135 *self = *self - rhs;
136 }
137}
138
139impl<F: HardwareField> Mul for Flat<F> {
140 type Output = Self;
141
142 #[inline(always)]
143 fn mul(self, rhs: Self) -> Self::Output {
144 F::mul_hardware(self, rhs)
145 }
146}
147
148impl<F: HardwareField> MulAssign for Flat<F> {
149 #[inline(always)]
150 fn mul_assign(&mut self, rhs: Self) {
151 *self = *self * rhs;
152 }
153}
154
155pub trait FlatPromote<FromF>: HardwareField
158where
159 FromF: HardwareField,
160{
161 fn promote_flat(val: Flat<FromF>) -> Flat<Self>;
163
164 fn promote_flat_batch(input: &[Flat<FromF>], output: &mut [Flat<Self>]) {
167 for (o, v) in output.iter_mut().zip(input.iter()) {
168 *o = Self::promote_flat(*v);
169 }
170 }
171}
172
173impl<F: HardwareField> FlatPromote<F> for F {
174 #[inline(always)]
175 fn promote_flat(val: Flat<F>) -> Flat<Self> {
176 val
177 }
178}