miden_stdlib_sys/intrinsics/
felt.rs1use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3unsafe extern "C" {
4 #[link_name = "intrinsics::felt::from_u64_unchecked"]
5 fn extern_from_u64_unchecked(value: u64) -> Felt;
6
7 #[link_name = "intrinsics::felt::from_u32"]
8 fn extern_from_u32(value: u32) -> Felt;
9
10 #[link_name = "intrinsics::felt::as_u64"]
11 fn extern_as_u64(felt: Felt) -> u64;
12
13 #[link_name = "intrinsics::felt::sub"]
14 fn extern_sub(a: Felt, b: Felt) -> Felt;
15
16 #[link_name = "intrinsics::felt::mul"]
17 fn extern_mul(a: Felt, b: Felt) -> Felt;
18
19 #[link_name = "intrinsics::felt::div"]
20 fn extern_div(a: Felt, b: Felt) -> Felt;
21
22 #[link_name = "intrinsics::felt::neg"]
23 fn extern_neg(a: Felt) -> Felt;
24
25 #[link_name = "intrinsics::felt::inv"]
26 fn extern_inv(a: Felt) -> Felt;
27
28 #[link_name = "intrinsics::felt::pow2"]
29 fn extern_pow2(a: Felt) -> Felt;
30
31 #[link_name = "intrinsics::felt::exp"]
32 fn extern_exp(a: Felt, b: Felt) -> Felt;
33
34 #[link_name = "intrinsics::felt::eq"]
35 fn extern_eq(a: Felt, b: Felt) -> i32;
36
37 #[link_name = "intrinsics::felt::gt"]
38 fn extern_gt(a: Felt, b: Felt) -> i32;
39
40 #[link_name = "intrinsics::felt::lt"]
41 fn extern_lt(a: Felt, b: Felt) -> i32;
42
43 #[link_name = "intrinsics::felt::ge"]
44 fn extern_ge(a: Felt, b: Felt) -> i32;
45
46 #[link_name = "intrinsics::felt::le"]
47 fn extern_le(a: Felt, b: Felt) -> i32;
48
49 #[link_name = "intrinsics::felt::is_odd"]
50 fn extern_is_odd(a: Felt) -> i32;
51
52 #[link_name = "intrinsics::felt::assert"]
53 fn extern_assert(a: Felt);
54
55 #[link_name = "intrinsics::felt::assertz"]
56 fn extern_assertz(a: Felt);
57
58 #[link_name = "intrinsics::felt::assert_eq"]
59 fn extern_assert_eq(a: Felt, b: Felt);
60
61 #[link_name = "intrinsics::felt::add"]
62 fn extern_add(a: Felt, b: Felt) -> Felt;
63}
64
65#[macro_export]
68macro_rules! felt {
69 ($value:literal) => {{
71 const VALUE: u64 = $value as u64;
72 assert!(VALUE <= u32::MAX as u64, "Invalid value, must be >= 0 and <= 2^32");
76 const VALUE_U32: u32 = $value as u32;
77 Felt::from_u32(VALUE_U32)
78 }};
79}
80
81#[derive(Debug)]
82pub enum FeltError {
83 InvalidValue,
84}
85
86#[repr(transparent)]
87#[derive(Copy, Clone, Debug)]
88pub struct Felt {
89 pub inner: f32,
90}
91
92impl Felt {
93 pub const M: u64 = 0xffffffff00000001;
95
96 #[inline(always)]
97 pub fn from_u64_unchecked(value: u64) -> Self {
98 unsafe { extern_from_u64_unchecked(value) }
99 }
100
101 #[inline(always)]
102 pub fn from_u32(value: u32) -> Self {
103 unsafe { extern_from_u32(value) }
104 }
105
106 #[inline(always)]
107 pub fn new(value: u64) -> Result<Self, FeltError> {
108 if value > Self::M {
109 Err(FeltError::InvalidValue)
110 } else {
111 Ok(Self::from_u64_unchecked(value))
112 }
113 }
114
115 #[inline(always)]
116 pub fn as_u64(self) -> u64 {
117 unsafe { extern_as_u64(self) }
118 }
119
120 #[inline(always)]
122 pub fn is_odd(self) -> bool {
123 unsafe { extern_is_odd(self) != 0 }
124 }
125
126 #[inline(always)]
129 pub fn inv(self) -> Felt {
130 unsafe { extern_inv(self) }
131 }
132
133 #[inline(always)]
136 pub fn pow2(self) -> Felt {
137 unsafe { extern_pow2(self) }
138 }
139
140 #[inline(always)]
142 pub fn exp(self, other: Felt) -> Felt {
143 unsafe { extern_exp(self, other) }
144 }
145}
146
147impl From<Felt> for u64 {
148 fn from(felt: Felt) -> u64 {
149 felt.as_u64()
150 }
151}
152
153impl From<u32> for Felt {
154 fn from(value: u32) -> Self {
155 Self {
156 inner: f32::from_bits(value),
157 }
158 }
159}
160
161impl From<u16> for Felt {
162 fn from(value: u16) -> Self {
163 Self {
164 inner: f32::from_bits(value as u32),
165 }
166 }
167}
168
169impl From<u8> for Felt {
170 fn from(value: u8) -> Self {
171 Self {
172 inner: f32::from_bits(value as u32),
173 }
174 }
175}
176
177#[cfg(target_pointer_width = "32")]
178impl From<usize> for Felt {
179 fn from(value: usize) -> Self {
180 Self {
181 inner: f32::from_bits(value as u32),
182 }
183 }
184}
185
186impl Add for Felt {
187 type Output = Self;
188
189 #[inline(always)]
190 fn add(self, other: Self) -> Self {
191 unsafe { extern_add(self, other) }
192 }
193}
194
195impl AddAssign for Felt {
196 #[inline(always)]
197 fn add_assign(&mut self, other: Self) {
198 *self = *self + other;
199 }
200}
201
202impl Sub for Felt {
203 type Output = Self;
204
205 #[inline(always)]
206 fn sub(self, other: Self) -> Self {
207 unsafe { extern_sub(self, other) }
208 }
209}
210
211impl SubAssign for Felt {
212 #[inline(always)]
213 fn sub_assign(&mut self, other: Self) {
214 *self = *self - other;
215 }
216}
217
218impl Mul for Felt {
219 type Output = Self;
220
221 #[inline(always)]
222 fn mul(self, other: Self) -> Self {
223 unsafe { extern_mul(self, other) }
224 }
225}
226
227impl MulAssign for Felt {
228 #[inline(always)]
229 fn mul_assign(&mut self, other: Self) {
230 *self = *self * other;
231 }
232}
233
234impl Div for Felt {
235 type Output = Self;
236
237 #[inline(always)]
238 fn div(self, other: Self) -> Self {
239 unsafe { extern_div(self, other) }
240 }
241}
242
243impl DivAssign for Felt {
244 #[inline(always)]
245 fn div_assign(&mut self, other: Self) {
246 *self = *self / other;
247 }
248}
249
250impl Neg for Felt {
251 type Output = Self;
252
253 #[inline(always)]
254 fn neg(self) -> Self {
255 unsafe { extern_neg(self) }
256 }
257}
258
259impl PartialEq for Felt {
260 #[inline(always)]
261 fn eq(&self, other: &Self) -> bool {
262 unsafe { extern_eq(*self, *other) == 1 }
263 }
264}
265
266impl Eq for Felt {}
267
268impl PartialOrd for Felt {
269 #[inline(always)]
270 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
271 Some(self.cmp(other))
272 }
273
274 #[inline(always)]
275 fn gt(&self, other: &Self) -> bool {
276 unsafe { extern_gt(*self, *other) != 0 }
277 }
278
279 #[inline(always)]
280 fn ge(&self, other: &Self) -> bool {
281 unsafe { extern_ge(*self, *other) != 0 }
282 }
283
284 #[inline(always)]
285 fn lt(&self, other: &Self) -> bool {
286 unsafe { extern_lt(*other, *self) != 0 }
287 }
288
289 #[inline(always)]
290 fn le(&self, other: &Self) -> bool {
291 unsafe { extern_le(*other, *self) != 0 }
292 }
293}
294
295impl Ord for Felt {
296 #[inline(always)]
297 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
298 if self.lt(other) {
299 core::cmp::Ordering::Less
300 } else if self.gt(other) {
301 core::cmp::Ordering::Greater
302 } else {
303 core::cmp::Ordering::Equal
304 }
305 }
306}
307
308#[inline(always)]
310pub fn assert(a: Felt) {
311 unsafe {
312 extern_assert(a);
313 }
314}
315
316#[inline(always)]
318pub fn assertz(a: Felt) {
319 unsafe {
320 extern_assertz(a);
321 }
322}
323
324#[inline(always)]
326pub fn assert_eq(a: Felt, b: Felt) {
327 unsafe {
328 extern_assert_eq(a, b);
329 }
330}
331
332