1use crate::DafnyPrint;
2use crate::Rc;
3use num::bigint::BigInt;
4use num::rational::BigRational;
5use num::FromPrimitive;
6use num::ToPrimitive;
7use num::{bigint::ParseBigIntError, Integer, Num, One, Signed, Zero};
8use std::{
9 clone::Clone,
10 cmp::Ordering,
11 convert::From,
12 fmt::Formatter,
13 hash::Hash,
14 ops::{Add, Div, Mul, Neg, Rem, Sub},
15};
16
17#[derive(Clone)]
20pub struct DafnyInt {
21 data: Rc<BigInt>,
22}
23
24impl DafnyInt {
25 pub fn new(data: Rc<BigInt>) -> DafnyInt {
26 DafnyInt { data }
27 }
28 pub fn strong_count(&self) -> usize {
29 Rc::strong_count(&self.data)
30 }
31}
32
33impl AsRef<BigInt> for DafnyInt {
34 fn as_ref(&self) -> &BigInt {
35 &self.data
36 }
37}
38
39impl Default for DafnyInt {
40 fn default() -> Self {
41 DafnyInt::new(Rc::new(BigInt::zero()))
42 }
43}
44
45pub fn dafny_int_to_bigint(i: &DafnyInt) -> BigInt {
46 i.data.as_ref().clone()
47}
48pub fn bigint_to_dafny_int(i: &BigInt) -> DafnyInt {
49 DafnyInt {
50 data: Rc::new(i.clone()),
51 }
52}
53
54impl Zero for DafnyInt {
55 #[inline]
56 fn zero() -> Self {
57 DafnyInt {
58 data: Rc::new(BigInt::zero()),
59 }
60 }
61 #[inline]
62 fn is_zero(&self) -> bool {
63 self.data.is_zero()
64 }
65}
66impl One for DafnyInt {
67 #[inline]
68 fn one() -> Self {
69 DafnyInt {
70 data: Rc::new(BigInt::one()),
71 }
72 }
73}
74impl Num for DafnyInt {
75 type FromStrRadixErr = ParseBigIntError;
76
77 #[inline]
78 fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
79 Ok(DafnyInt {
80 data: Rc::new(BigInt::from_str_radix(s, radix)?),
81 })
82 }
83}
84impl Ord for DafnyInt {
85 #[inline]
86 fn cmp(&self, other: &Self) -> Ordering {
87 self.data.cmp(&other.data)
88 }
89}
90impl Signed for DafnyInt {
91 #[inline]
92 fn abs(&self) -> Self {
93 DafnyInt {
94 data: Rc::new(self.data.as_ref().abs()),
95 }
96 }
97
98 #[inline]
99 fn abs_sub(&self, other: &Self) -> Self {
100 DafnyInt {
101 data: Rc::new(self.data.as_ref().abs_sub(other.data.as_ref())),
102 }
103 }
104
105 #[inline]
106 fn signum(&self) -> Self {
107 DafnyInt {
108 data: Rc::new(self.data.as_ref().signum()),
109 }
110 }
111
112 #[inline]
113 fn is_positive(&self) -> bool {
114 self.data.as_ref().is_positive()
115 }
116
117 #[inline]
118 fn is_negative(&self) -> bool {
119 self.data.as_ref().is_negative()
120 }
121}
122
123impl PartialOrd<DafnyInt> for DafnyInt {
125 #[inline]
126 fn partial_cmp(&self, other: &DafnyInt) -> Option<Ordering> {
127 Some(self.cmp(other))
128 }
129}
130
131impl DafnyInt {
132 #[inline]
133 pub fn parse_bytes(number: &[u8], radix: u32) -> DafnyInt {
134 DafnyInt {
135 data: Rc::new(BigInt::parse_bytes(number, radix).unwrap()),
136 }
137 }
138 pub fn from_usize(usize: usize) -> DafnyInt {
139 DafnyInt {
140 data: Rc::new(BigInt::from(usize)),
141 }
142 }
143 pub fn from_i32(i: i32) -> DafnyInt {
144 DafnyInt {
145 data: Rc::new(BigInt::from(i)),
146 }
147 }
148}
149
150impl DafnyPrint for BigInt {
155 fn fmt_print(&self, f: &mut Formatter<'_>, _in_seq: bool) -> std::fmt::Result {
156 write!(f, "{}", self)
157 }
158}
159
160fn divides_a_power_of_10(mut i: BigInt) -> (bool, BigInt, usize) {
161 let one: BigInt = One::one();
162
163 let mut factor = one.clone();
164 let mut log10 = 0;
165
166 let zero = Zero::zero();
167 let ten = BigInt::from_i32(10).unwrap();
168
169 if i <= zero {
170 return (false, factor, log10);
171 }
172
173 while i.is_multiple_of(&ten) {
174 i /= BigInt::from_i32(10).unwrap();
175 log10 += 1;
176 }
177
178 let two = BigInt::from_i32(2).unwrap();
179 let five = BigInt::from_i32(5).unwrap();
180
181 while i.is_multiple_of(&five) {
182 i /= &five;
183 factor *= &two;
184 log10 += 1;
185 }
186
187 while i.is_multiple_of(&two) {
188 i /= &two;
189 factor *= &two;
190 log10 += 1;
191 }
192
193 (i == one, factor, log10)
194}
195
196impl DafnyPrint for BigRational {
197 fn fmt_print(&self, f: &mut Formatter<'_>, _in_seq: bool) -> std::fmt::Result {
198 if self.denom() == &One::one() || self.numer() == &Zero::zero() {
199 write!(f, "{}.0", self.numer())
200 } else {
201 let (divides, factor, log10) = divides_a_power_of_10(self.denom().clone());
202 if divides {
203 let mut num = self.numer().clone();
204 num *= factor;
205
206 if num.is_negative() {
207 write!(f, "-")?;
208 num = -num;
209 }
210
211 let digits = num.to_string();
212
213 if log10 < digits.len() {
214 let digit_count = digits.len() - log10;
215 write!(f, "{}", &digits[..digit_count])?;
216 write!(f, ".")?;
217 write!(f, "{}", &digits[digit_count..])
218 } else {
219 let z = log10 - digits.len();
220 write!(f, "0.")?;
221 for _ in 0..z {
222 write!(f, "0")?;
223 }
224 write!(f, "{}", digits)
225 }
226 } else {
227 write!(f, "({}.0 / {}.0)", self.numer(), self.denom())
228 }
229 }
230 }
231}
232
233impl From<DafnyInt> for u8 {
234 fn from(val: DafnyInt) -> Self {
235 val.data.to_u8().unwrap()
236 }
237}
238impl From<DafnyInt> for u16 {
239 fn from(val: DafnyInt) -> Self {
240 val.data.to_u16().unwrap()
241 }
242}
243impl From<DafnyInt> for u32 {
244 fn from(val: DafnyInt) -> Self {
245 val.data.to_u32().unwrap()
246 }
247}
248impl From<DafnyInt> for u64 {
249 fn from(val: DafnyInt) -> Self {
250 val.data.to_u64().unwrap()
251 }
252}
253impl From<DafnyInt> for u128 {
254 fn from(val: DafnyInt) -> Self {
255 val.data.to_u128().unwrap()
256 }
257}
258impl From<DafnyInt> for i8 {
259 fn from(val: DafnyInt) -> Self {
260 val.data.to_i8().unwrap()
261 }
262}
263impl From<DafnyInt> for i16 {
264 fn from(val: DafnyInt) -> Self {
265 val.data.to_i16().unwrap()
266 }
267}
268impl From<DafnyInt> for i32 {
269 fn from(val: DafnyInt) -> Self {
270 val.data.to_i32().unwrap()
271 }
272}
273impl From<DafnyInt> for i64 {
274 fn from(val: DafnyInt) -> Self {
275 val.data.to_i64().unwrap()
276 }
277}
278impl From<DafnyInt> for i128 {
279 fn from(val: DafnyInt) -> Self {
280 val.data.to_i128().unwrap()
281 }
282}
283impl From<DafnyInt> for usize {
284 fn from(val: DafnyInt) -> Self {
285 val.data.to_usize().unwrap()
286 }
287}
288
289impl ToPrimitive for DafnyInt {
290 fn to_i64(&self) -> Option<i64> {
291 self.data.to_i64()
292 }
293
294 fn to_u64(&self) -> Option<u64> {
295 self.data.to_u64()
296 }
297
298 fn to_u128(&self) -> Option<u128> {
300 self.data.to_u128()
301 }
302
303 fn to_i128(&self) -> Option<i128> {
304 self.data.to_i128()
305 }
306}
307
308impl PartialEq<DafnyInt> for DafnyInt {
309 fn eq(&self, other: &DafnyInt) -> bool {
310 self.data.eq(&other.data)
311 }
312}
313impl Eq for DafnyInt {}
314impl Hash for DafnyInt {
315 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
316 self.data.hash(state);
317 }
318}
319
320impl DafnyPrint for DafnyInt {
321 fn fmt_print(&self, f: &mut Formatter<'_>, _in_seq: bool) -> std::fmt::Result {
322 write!(f, "{}", self.data)
323 }
324}
325
326impl ::std::fmt::Debug for DafnyInt {
327 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
328 write!(f, "{}", self.data)
329 }
330}
331
332impl Add<DafnyInt> for DafnyInt {
333 type Output = DafnyInt;
334
335 fn add(self, rhs: DafnyInt) -> Self::Output {
336 DafnyInt {
337 data: Rc::new(self.data.as_ref() + rhs.data.as_ref()),
338 }
339 }
340}
341
342impl Mul<DafnyInt> for DafnyInt {
343 type Output = DafnyInt;
344
345 fn mul(self, rhs: DafnyInt) -> Self::Output {
346 DafnyInt {
347 data: Rc::new(self.data.as_ref() * rhs.data.as_ref()),
348 }
349 }
350}
351
352impl Div<DafnyInt> for DafnyInt {
353 type Output = DafnyInt;
354
355 fn div(self, rhs: DafnyInt) -> Self::Output {
356 DafnyInt {
357 data: Rc::new(self.data.as_ref() / rhs.data.as_ref()),
358 }
359 }
360}
361
362impl Sub<DafnyInt> for DafnyInt {
363 type Output = DafnyInt;
364
365 fn sub(self, rhs: DafnyInt) -> Self::Output {
366 DafnyInt {
367 data: Rc::new(self.data.as_ref() - rhs.data.as_ref()),
368 }
369 }
370}
371impl Rem<DafnyInt> for DafnyInt {
372 type Output = DafnyInt;
373
374 fn rem(self, rhs: DafnyInt) -> Self::Output {
375 DafnyInt {
376 data: Rc::new(self.data.as_ref() % rhs.data.as_ref()),
377 }
378 }
379}
380impl Neg for DafnyInt {
381 type Output = DafnyInt;
382
383 #[inline]
384 fn neg(self) -> Self::Output {
385 DafnyInt {
386 data: Rc::new(-self.data.as_ref()),
387 }
388 }
389}
390
391macro_rules! impl_dafnyint_from {
392 () => {};
393 ($type:ident) => {
394 impl ::std::convert::From<$type> for $crate::DafnyInt {
395 fn from(n: $type) -> Self {
396 $crate::DafnyInt {
397 data: $crate::Rc::new(n.into()),
398 }
399 }
400 }
401 #[allow(trivial_numeric_casts)]
402 impl $crate::DafnyUsize for $type {
403 fn into_usize(self) -> usize {
404 self as usize
405 }
406 }
407 };
408}
409
410impl_dafnyint_from! { u8 }
411impl_dafnyint_from! { u16 }
412impl_dafnyint_from! { u32 }
413impl_dafnyint_from! { u64 }
414impl_dafnyint_from! { u128 }
415impl_dafnyint_from! { i8 }
416impl_dafnyint_from! { i16 }
417impl_dafnyint_from! { i32 }
418impl_dafnyint_from! { i64 }
419impl_dafnyint_from! { i128 }
420impl_dafnyint_from! { usize }