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