1use core::fmt;
2use core::ops::*;
3use num_traits::cast::ToPrimitive;
4
5mod bigint;
6use bigint::*;
7
8use super::abstraction::*;
9
10#[cfg(feature = "macros")]
11pub use hax_lib_macros::int;
12
13#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
21pub struct Int(BigInt);
22
23impl fmt::Display for Int {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "{}", self.get())
26 }
27}
28
29impl Int {
30 fn new(x: impl Into<num_bigint::BigInt>) -> Self {
31 Int(BigInt::new(&x.into()))
32 }
33 fn get(self) -> num_bigint::BigInt {
34 self.0.get()
35 }
36}
37
38impl Add for Int {
39 type Output = Self;
40
41 fn add(self, other: Self) -> Self::Output {
42 Self::new(self.get() + other.get())
43 }
44}
45
46impl Neg for Int {
47 type Output = Self;
48
49 fn neg(self) -> Self::Output {
50 Self::new(-self.get())
51 }
52}
53
54impl Sub for Int {
55 type Output = Self;
56
57 fn sub(self, other: Self) -> Self::Output {
58 Self::new(self.get() - other.get())
59 }
60}
61
62impl Mul for Int {
63 type Output = Self;
64
65 fn mul(self, other: Self) -> Self::Output {
66 Self::new(self.get() * other.get())
67 }
68}
69
70impl Div for Int {
71 type Output = Self;
72
73 fn div(self, other: Self) -> Self::Output {
74 Self::new(self.get() / other.get())
75 }
76}
77
78impl Int {
79 pub fn pow2(self) -> Self {
81 use num_traits::Pow;
82 let exponent = self
83 .get()
84 .to_biguint()
85 .expect("`Int::pow2`: the exponent must be non-negative");
86 Self::new(Pow::pow(num_bigint::BigInt::from(2u8), exponent))
87 }
88
89 pub fn _unsafe_from_str(s: &str) -> Self {
93 use core::str::FromStr;
94 Self::new(num_bigint::BigInt::from_str(s).unwrap())
95 }
96
97 pub fn rem_euclid(&self, v: Self) -> Self {
98 use num_traits::Euclid;
99 Self::new(self.get().rem_euclid(&v.get()))
100 }
101}
102
103#[cfg(feature = "macros")]
104pub trait ToInt {
105 fn to_int(self) -> Int;
106}
107
108macro_rules! implement_abstraction {
124 ($ty:ident) => {
125 impl Abstraction for $ty {
126 type AbstractType = Int;
127 fn lift(self) -> Self::AbstractType {
128 Int::new(num_bigint::BigInt::from(self))
129 }
130 }
131 impl ToInt for $ty {
132 fn to_int(self) -> Int {
133 self.lift()
134 }
135 }
136 };
137 ($($ty:ident)*) => {
138 $(implement_abstraction!($ty);)*
139 };
140}
141
142implement_abstraction!(u8 u16 u32 u64 u128 usize);
143implement_abstraction!(i8 i16 i32 i64 i128 isize);
144
145macro_rules! implement_concretize {
146 ($ty:ident $method:ident) => {
147 impl Concretization<$ty> for Int {
148 fn concretize(self) -> $ty {
149 let concretized = self.get().$method();
150 debug_assert!(concretized.is_some());
151 concretized.unwrap().into()
152 }
153 }
154 impl Int {
155 pub fn $method(self) -> $ty {
156 self.concretize()
157 }
158 }
159 };
160 ($ty:ident $method:ident, $($tt:tt)*) => {
161 implement_concretize!($ty $method);
162 implement_concretize!($($tt)*);
163 };
164 () => {};
165}
166
167implement_concretize!(
168 u8 to_u8,
169 u16 to_u16,
170 u32 to_u32,
171 u64 to_u64,
172 u128 to_u128,
173 usize to_usize,
174 i8 to_i8,
175 i16 to_i16,
176 i32 to_i32,
177 i64 to_i64,
178 i128 to_i128,
179 isize to_isize,
180);