1use crate::packable::PackedFlat;
19use crate::{PackableField, TowerField};
20use core::fmt::{self, Debug, Formatter};
21use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
22use zeroize::Zeroize;
23
24pub trait HardwareField: TowerField + PackableField {
26 fn to_hardware(self) -> Flat<Self>;
29
30 fn from_hardware(value: Flat<Self>) -> Self;
32
33 fn add_hardware(lhs: Flat<Self>, rhs: Flat<Self>) -> Flat<Self>;
36
37 fn add_hardware_packed(lhs: PackedFlat<Self>, rhs: PackedFlat<Self>) -> PackedFlat<Self>;
39
40 fn mul_hardware(lhs: Flat<Self>, rhs: Flat<Self>) -> Flat<Self>;
43
44 fn mul_hardware_packed(lhs: PackedFlat<Self>, rhs: PackedFlat<Self>) -> PackedFlat<Self>;
46
47 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)]
66 pub fn from_raw(raw: F) -> Self {
67 Self(raw)
68 }
69
70 #[inline(always)]
71 pub fn into_raw(self) -> F {
72 self.0
73 }
74
75 #[inline(always)]
76 pub fn as_raw(&self) -> &F {
77 &self.0
78 }
79}
80
81impl<F: Debug> Debug for Flat<F> {
82 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
83 f.debug_tuple("Flat").field(&self.0).finish()
84 }
85}
86
87impl<F: HardwareField> Flat<F> {
88 #[inline(always)]
89 pub fn to_tower(self) -> F {
90 F::from_hardware(self)
91 }
92
93 #[inline(always)]
94 pub fn tower_bit(self, bit_idx: usize) -> u8 {
95 F::tower_bit_from_hardware(self, bit_idx)
96 }
97}
98
99impl<F: HardwareField> Add for Flat<F> {
100 type Output = Self;
101
102 #[inline(always)]
103 fn add(self, rhs: Self) -> Self::Output {
104 F::add_hardware(self, rhs)
105 }
106}
107
108impl<F: HardwareField> AddAssign for Flat<F> {
109 #[inline(always)]
110 fn add_assign(&mut self, rhs: Self) {
111 *self = *self + rhs;
112 }
113}
114
115impl<F: HardwareField> Sub for Flat<F> {
116 type Output = Self;
117
118 #[inline(always)]
119 fn sub(self, rhs: Self) -> Self::Output {
120 F::add_hardware(self, rhs)
121 }
122}
123
124impl<F: HardwareField> SubAssign for Flat<F> {
125 #[inline(always)]
126 fn sub_assign(&mut self, rhs: Self) {
127 *self = *self - rhs;
128 }
129}
130
131impl<F: HardwareField> Mul for Flat<F> {
132 type Output = Self;
133
134 #[inline(always)]
135 fn mul(self, rhs: Self) -> Self::Output {
136 F::mul_hardware(self, rhs)
137 }
138}
139
140impl<F: HardwareField> MulAssign for Flat<F> {
141 #[inline(always)]
142 fn mul_assign(&mut self, rhs: Self) {
143 *self = *self * rhs;
144 }
145}
146
147pub trait FlatPromote<FromF>: HardwareField
151where
152 FromF: HardwareField,
153{
154 fn promote_flat(val: Flat<FromF>) -> Flat<Self>;
155
156 fn promote_flat_batch(input: &[Flat<FromF>], output: &mut [Flat<Self>]) {
162 for (o, v) in output.iter_mut().zip(input.iter()) {
163 *o = Self::promote_flat(*v);
164 }
165 }
166}
167
168impl<F: HardwareField> FlatPromote<F> for F {
169 #[inline(always)]
170 fn promote_flat(val: Flat<F>) -> Flat<Self> {
171 val
172 }
173}