1#![no_std]
9#![deny(warnings)]
10
11use core::{fmt, hash::Hash};
12
13pub const MODULUS: u64 = 0xffff_ffff_0000_0001;
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub enum FeltError {
19 InvalidValue,
21}
22
23pub(crate) trait FeltImpl:
28 Copy
29 + Clone
30 + fmt::Debug
31 + fmt::Display
32 + Eq
33 + Ord
34 + Hash
35 + core::ops::Add<Output = Self>
36 + core::ops::Sub<Output = Self>
37 + core::ops::Mul<Output = Self>
38 + core::ops::Div<Output = Self>
39 + core::ops::Neg<Output = Self>
40 + core::ops::AddAssign
41 + core::ops::SubAssign
42 + core::ops::MulAssign
43 + core::ops::DivAssign
44{
45 fn from_u64_unchecked(value: u64) -> Self;
51
52 fn from_u32(value: u32) -> Self;
54
55 fn as_u64(self) -> u64;
57
58 fn is_odd(self) -> bool;
60
61 fn inv(self) -> Self;
63
64 fn pow2(self) -> Self;
66
67 fn exp(self, other: Self) -> Self;
69}
70
71#[cfg(all(target_family = "wasm", miden))]
72mod wasm32;
73#[cfg(all(target_family = "wasm", miden))]
74pub use wasm32::Felt;
75
76#[cfg(not(all(target_family = "wasm", miden)))]
77mod native;
78#[cfg(not(all(target_family = "wasm", miden)))]
79pub use native::Felt;
80
81impl Felt {
82 pub const M: u64 = MODULUS;
84
85 #[inline(always)]
87 pub fn from_u64_unchecked(value: u64) -> Self {
88 <Self as FeltImpl>::from_u64_unchecked(value)
89 }
90
91 #[inline(always)]
93 pub fn from_u32(value: u32) -> Self {
94 <Self as FeltImpl>::from_u32(value)
95 }
96
97 #[inline(always)]
99 pub fn new(value: u64) -> Result<Self, FeltError> {
100 if value >= Self::M {
101 Err(FeltError::InvalidValue)
102 } else {
103 Ok(Self::from_u64_unchecked(value))
104 }
105 }
106
107 #[inline(always)]
109 pub fn as_u64(self) -> u64 {
110 <Self as FeltImpl>::as_u64(self)
111 }
112
113 #[inline(always)]
115 pub fn is_odd(self) -> bool {
116 <Self as FeltImpl>::is_odd(self)
117 }
118
119 #[inline(always)]
121 pub fn inv(self) -> Self {
122 <Self as FeltImpl>::inv(self)
123 }
124
125 #[inline(always)]
127 pub fn pow2(self) -> Self {
128 <Self as FeltImpl>::pow2(self)
129 }
130
131 #[inline(always)]
133 pub fn exp(self, other: Self) -> Self {
134 <Self as FeltImpl>::exp(self, other)
135 }
136}