1use crate::Integer;
18use crate::ext::xmpz;
19use crate::misc;
20use crate::ops::NegAssign;
21use az::{
22 Az, Cast, CheckedCast, OverflowingCast, Round, SaturatingCast, UnwrappedCast, WrappingCast,
23};
24
25macro_rules! cast_int {
26 ($Prim:ty, $fits:path, $get_abs:path) => {
27 impl Cast<Integer> for $Prim {
28 #[inline]
29 fn cast(self) -> Integer {
30 Integer::from(self)
31 }
32 }
33
34 impl Cast<$Prim> for Integer {
35 #[inline]
36 fn cast(self) -> $Prim {
37 (&self).cast()
38 }
39 }
40 impl Cast<$Prim> for &'_ Integer {
41 #[inline]
42 fn cast(self) -> $Prim {
43 let (wrapped, overflow) = self.overflowing_cast();
44 debug_assert!(!overflow, "overflow");
45 wrapped
46 }
47 }
48 impl CheckedCast<$Prim> for Integer {
49 #[inline]
50 fn checked_cast(self) -> Option<$Prim> {
51 (&self).checked_cast()
52 }
53 }
54 impl CheckedCast<$Prim> for &'_ Integer {
55 #[inline]
56 fn checked_cast(self) -> Option<$Prim> {
57 if $fits(self) {
58 Some(self.wrapping_cast())
59 } else {
60 None
61 }
62 }
63 }
64 impl SaturatingCast<$Prim> for Integer {
65 #[inline]
66 fn saturating_cast(self) -> $Prim {
67 (&self).saturating_cast()
68 }
69 }
70 impl SaturatingCast<$Prim> for &'_ Integer {
71 #[inline]
72 fn saturating_cast(self) -> $Prim {
73 if $fits(self) {
74 self.wrapping_cast()
75 } else if self.is_negative() {
76 <$Prim>::MIN
77 } else {
78 <$Prim>::MAX
79 }
80 }
81 }
82 impl WrappingCast<$Prim> for Integer {
83 #[inline]
84 fn wrapping_cast(self) -> $Prim {
85 (&self).wrapping_cast()
86 }
87 }
88 impl WrappingCast<$Prim> for &'_ Integer {
89 #[inline]
90 fn wrapping_cast(self) -> $Prim {
91 let val = $get_abs(self);
92 if self.is_negative() {
93 val.wrapping_neg()
94 } else {
95 val
96 }
97 .wrapping_cast()
98 }
99 }
100 impl OverflowingCast<$Prim> for Integer {
101 #[inline]
102 fn overflowing_cast(self) -> ($Prim, bool) {
103 (&self).overflowing_cast()
104 }
105 }
106 impl OverflowingCast<$Prim> for &'_ Integer {
107 #[inline]
108 fn overflowing_cast(self) -> ($Prim, bool) {
109 (self.wrapping_cast(), !$fits(self))
110 }
111 }
112 impl UnwrappedCast<$Prim> for Integer {
113 #[inline]
114 fn unwrapped_cast(self) -> $Prim {
115 (&self).unwrapped_cast()
116 }
117 }
118 impl UnwrappedCast<$Prim> for &'_ Integer {
119 #[inline]
120 fn unwrapped_cast(self) -> $Prim {
121 if $fits(self) {
122 self.wrapping_cast()
123 } else {
124 panic!("overflow")
125 }
126 }
127 }
128 };
129}
130
131impl Cast<Integer> for bool {
132 #[inline]
133 fn cast(self) -> Integer {
134 if self {
135 Integer::from(1u32)
136 } else {
137 Integer::new()
138 }
139 }
140}
141
142cast_int! { i8, xmpz::fits_i8, xmpz::get_abs_u8 }
143cast_int! { i16, xmpz::fits_i16, xmpz::get_abs_u16 }
144cast_int! { i32, xmpz::fits_i32, xmpz::get_abs_u32 }
145cast_int! { i64, xmpz::fits_i64, xmpz::get_abs_u64 }
146cast_int! { i128, xmpz::fits_i128, xmpz::get_abs_u128 }
147#[cfg(target_pointer_width = "32")]
148cast_int! { isize, xmpz::fits_i32, xmpz::get_abs_u32 }
149#[cfg(target_pointer_width = "64")]
150cast_int! { isize, xmpz::fits_i64, xmpz::get_abs_u64 }
151cast_int! { u8, xmpz::fits_u8, xmpz::get_abs_u8 }
152cast_int! { u16, xmpz::fits_u16, xmpz::get_abs_u16 }
153cast_int! { u32, xmpz::fits_u32, xmpz::get_abs_u32 }
154cast_int! { u64, xmpz::fits_u64, xmpz::get_abs_u64 }
155cast_int! { u128, xmpz::fits_u128, xmpz::get_abs_u128 }
156#[cfg(target_pointer_width = "32")]
157cast_int! { usize, xmpz::fits_u32, xmpz::get_abs_u32 }
158#[cfg(target_pointer_width = "64")]
159cast_int! { usize, xmpz::fits_u64, xmpz::get_abs_u64 }
160
161impl Cast<Integer> for f32 {
162 #[inline]
163 fn cast(self) -> Integer {
164 self.checked_cast().expect("not finite")
165 }
166}
167
168impl CheckedCast<Integer> for f32 {
169 #[inline]
170 fn checked_cast(self) -> Option<Integer> {
171 let bits = self.to_bits();
172 let biased_exp = (bits >> 23) & 0xFF;
173 if biased_exp < 0x7F {
179 Some(Integer::new())
180 } else if biased_exp == 0xFF {
181 None
182 } else {
183 let mantissa_with_one = 0x0080_0000 | (bits & 0x007F_FFFF);
188 let mut val = if biased_exp <= 150 {
189 Integer::from(mantissa_with_one >> (150 - biased_exp))
190 } else {
191 Integer::from(mantissa_with_one) << (biased_exp - 150)
192 };
193 if bits & 0x8000_0000 != 0 {
194 val.neg_assign();
195 }
196 Some(val)
197 }
198 }
199}
200
201impl UnwrappedCast<Integer> for f32 {
202 #[inline]
203 fn unwrapped_cast(self) -> Integer {
204 self.checked_cast().expect("not finite")
205 }
206}
207
208impl Cast<f32> for Integer {
209 #[inline]
210 fn cast(self) -> f32 {
211 (&self).cast()
212 }
213}
214
215impl Cast<f32> for &'_ Integer {
216 #[inline]
217 fn cast(self) -> f32 {
218 misc::trunc_f64_to_f32(self.cast())
219 }
220}
221
222impl Cast<Integer> for f64 {
223 #[inline]
224 fn cast(self) -> Integer {
225 self.checked_cast().expect("not finite")
226 }
227}
228
229impl CheckedCast<Integer> for f64 {
230 #[inline]
231 fn checked_cast(self) -> Option<Integer> {
232 let bits = self.to_bits();
233 let biased_exp = (bits >> 52) & 0x7FF;
234 if biased_exp < 0x3FF {
240 Some(Integer::new())
241 } else if biased_exp == 0x7FF {
242 None
243 } else {
244 let mantissa_with_one = 0x0010_0000_0000_0000 | (bits & 0x000F_FFFF_FFFF_FFFF);
249 let mut val = if biased_exp <= 1075 {
250 Integer::from(mantissa_with_one >> (1075 - biased_exp).az::<u32>())
251 } else {
252 Integer::from(mantissa_with_one) << (biased_exp - 1075).az::<u32>()
253 };
254 if bits & 0x8000_0000_0000_0000 != 0 {
255 val.neg_assign();
256 }
257 Some(val)
258 }
259 }
260}
261
262impl UnwrappedCast<Integer> for f64 {
263 #[inline]
264 fn unwrapped_cast(self) -> Integer {
265 self.checked_cast().expect("not finite")
266 }
267}
268
269impl Cast<f64> for Integer {
270 #[inline]
271 fn cast(self) -> f64 {
272 (&self).cast()
273 }
274}
275
276impl Cast<f64> for &'_ Integer {
277 #[inline]
278 fn cast(self) -> f64 {
279 xmpz::get_f64(self)
280 }
281}
282
283impl Cast<Integer> for Round<f32> {
284 #[inline]
285 fn cast(self) -> Integer {
286 self.checked_cast().expect("not finite")
287 }
288}
289
290impl CheckedCast<Integer> for Round<f32> {
291 #[inline]
292 fn checked_cast(self) -> Option<Integer> {
293 let bits = self.0.to_bits();
294 let biased_exp = (bits >> 23) & 0xFF;
295 if biased_exp < 0x7F {
301 Some(Integer::new())
302 } else if biased_exp == 0xFF {
303 None
304 } else {
305 let mantissa_with_one = 0x0080_0000 | (bits & 0x007F_FFFF);
310 let mut val = if biased_exp <= 150 {
311 let mut round = 1u32 << (150 - biased_exp) >> 1;
312 if mantissa_with_one & round == 0 || mantissa_with_one & (3 * round - 1) == 0 {
319 round = 0;
320 }
321 Integer::from((mantissa_with_one + round) >> (150 - biased_exp))
322 } else {
323 Integer::from(mantissa_with_one) << (biased_exp - 150)
324 };
325 if bits & 0x8000_0000 != 0 {
326 val.neg_assign();
327 }
328 Some(val)
329 }
330 }
331}
332
333impl UnwrappedCast<Integer> for Round<f32> {
334 #[inline]
335 fn unwrapped_cast(self) -> Integer {
336 self.checked_cast().expect("not finite")
337 }
338}
339
340impl Cast<Integer> for Round<f64> {
341 #[inline]
342 fn cast(self) -> Integer {
343 self.checked_cast().expect("not finite")
344 }
345}
346
347impl CheckedCast<Integer> for Round<f64> {
348 #[inline]
349 fn checked_cast(self) -> Option<Integer> {
350 let bits = self.0.to_bits();
351 let biased_exp = (bits >> 52) & 0x7FF;
352 if biased_exp < 0x3FF {
358 Some(Integer::new())
359 } else if biased_exp == 0x7FF {
360 None
361 } else {
362 let mantissa_with_one = 0x0010_0000_0000_0000 | (bits & 0x000F_FFFF_FFFF_FFFF);
367 let mut val = if biased_exp <= 1075 {
368 let mut round = 1u64 << (1075 - biased_exp) >> 1;
369 if mantissa_with_one & round == 0 || mantissa_with_one & (3 * round - 1) == 0 {
376 round = 0;
377 }
378 Integer::from((mantissa_with_one + round) >> (1075 - biased_exp).az::<u32>())
379 } else {
380 Integer::from(mantissa_with_one) << (biased_exp - 1075).az::<u32>()
381 };
382 if bits & 0x8000_0000_0000_0000 != 0 {
383 val.neg_assign();
384 }
385 Some(val)
386 }
387 }
388}
389
390impl UnwrappedCast<Integer> for Round<f64> {
391 #[inline]
392 fn unwrapped_cast(self) -> Integer {
393 self.checked_cast().expect("not finite")
394 }
395}
396
397#[cfg(test)]
398#[allow(clippy::float_cmp)]
399mod tests {
400 use crate::Integer;
401 use az::{
402 Az, Cast, CheckedAs, CheckedCast, OverflowingAs, OverflowingCast, Round, SaturatingAs,
403 SaturatingCast, UnwrappedAs, UnwrappedCast, WrappingAs, WrappingCast,
404 };
405 use core::borrow::Borrow;
406 use core::fmt::Debug;
407 use std::panic;
408
409 #[test]
410 fn check_bool() {
411 let zero = Integer::new();
412 let one = Integer::from(1);
413 assert_eq!(false.az::<Integer>(), zero);
414 assert_eq!(true.az::<Integer>(), one);
415 }
416
417 fn check_there_and_back<T>(min: T, max: T)
418 where
419 T: Copy + Debug + Eq + Cast<Integer>,
420 for<'a> &'a Integer: Cast<T>
421 + CheckedCast<T>
422 + SaturatingCast<T>
423 + WrappingCast<T>
424 + OverflowingCast<T>
425 + UnwrappedCast<T>,
426 {
427 let min_int: Integer = min.az::<Integer>();
428 let max_int: Integer = max.az::<Integer>();
429 assert_eq!(min_int.borrow().az::<T>(), min);
430 assert_eq!(max_int.borrow().az::<T>(), max);
431 assert_eq!(min_int.borrow().checked_as::<T>(), Some(min));
432 assert_eq!(max_int.borrow().checked_as::<T>(), Some(max));
433 assert_eq!(min_int.borrow().saturating_as::<T>(), min);
434 assert_eq!(max_int.borrow().saturating_as::<T>(), max);
435 assert_eq!(min_int.borrow().wrapping_as::<T>(), min);
436 assert_eq!(max_int.borrow().wrapping_as::<T>(), max);
437 assert_eq!(min_int.borrow().overflowing_as::<T>(), (min, false));
438 assert_eq!(max_int.borrow().overflowing_as::<T>(), (max, false));
439 assert_eq!(min_int.borrow().unwrapped_as::<T>(), min);
440 assert_eq!(max_int.borrow().unwrapped_as::<T>(), max);
441
442 let too_small: Integer = min_int - 1;
443 let too_large: Integer = max_int + 1;
444 assert_eq!(too_small.borrow().checked_as::<T>(), None);
445 assert_eq!(too_large.borrow().checked_as::<T>(), None);
446 assert_eq!(too_small.borrow().saturating_as::<T>(), min);
447 assert_eq!(too_large.borrow().saturating_as::<T>(), max);
448 assert_eq!(too_small.borrow().wrapping_as::<T>(), max);
449 assert_eq!(too_large.borrow().wrapping_as::<T>(), min);
450 assert_eq!(too_small.borrow().overflowing_as::<T>(), (max, true));
451 assert_eq!(too_large.borrow().overflowing_as::<T>(), (min, true));
452 assert!(panic::catch_unwind(|| too_small.borrow().unwrapped_as::<T>()).is_err());
453 assert!(panic::catch_unwind(|| too_large.borrow().unwrapped_as::<T>()).is_err());
454 }
455
456 #[test]
457 fn check_integers() {
458 check_there_and_back(i8::MIN, i8::MAX);
459 check_there_and_back(i16::MIN, i16::MAX);
460 check_there_and_back(i32::MIN, i32::MAX);
461 check_there_and_back(i64::MIN, i64::MAX);
462 check_there_and_back(i128::MIN, i128::MAX);
463 check_there_and_back(isize::MIN, isize::MAX);
464 check_there_and_back(u8::MIN, u8::MAX);
465 check_there_and_back(u16::MIN, u16::MAX);
466 check_there_and_back(u32::MIN, u32::MAX);
467 check_there_and_back(u64::MIN, u64::MAX);
468 check_there_and_back(u128::MIN, u128::MAX);
469 check_there_and_back(usize::MIN, usize::MAX);
470 }
471
472 #[test]
473 fn check_floats() {
474 let f32_max: Integer = Integer::from((1u32 << 24) - 1) << (127 - 23);
475 let f64_max: Integer = Integer::from((1u64 << 53) - 1) << (1023 - 52);
476
477 assert_eq!(f32::NAN.checked_as::<Integer>(), None);
478 assert!(panic::catch_unwind(|| f32::NAN.unwrapped_as::<Integer>()).is_err());
479 assert_eq!(f32::NEG_INFINITY.checked_as::<Integer>(), None);
480 assert!(panic::catch_unwind(|| f32::NEG_INFINITY.unwrapped_as::<Integer>()).is_err());
481 assert_eq!((-f32::MAX).az::<Integer>(), *f32_max.as_neg());
482 assert_eq!((-2f32).az::<Integer>(), -2);
483 assert_eq!((-1.99f32).az::<Integer>(), -1);
484 assert_eq!((-1f32).az::<Integer>(), -1);
485 assert_eq!((-0.99f32).az::<Integer>(), 0);
486 assert_eq!(0.99f32.az::<Integer>(), 0);
487 assert_eq!(1f32.az::<Integer>(), 1);
488 assert_eq!(1.99f32.az::<Integer>(), 1);
489 assert_eq!(2f32.az::<Integer>(), 2);
490 assert_eq!(f32::MAX.az::<Integer>(), f32_max);
491 assert_eq!(f32::INFINITY.checked_as::<Integer>(), None);
492 assert!(panic::catch_unwind(|| f32::INFINITY.unwrapped_as::<Integer>()).is_err());
493
494 assert_eq!(f64::NAN.checked_as::<Integer>(), None);
495 assert!(panic::catch_unwind(|| f64::NAN.unwrapped_as::<Integer>()).is_err());
496 assert_eq!(f64::NEG_INFINITY.checked_as::<Integer>(), None);
497 assert!(panic::catch_unwind(|| f64::NEG_INFINITY.unwrapped_as::<Integer>()).is_err());
498 assert_eq!((-f64::MAX).az::<Integer>(), *f64_max.as_neg());
499 assert_eq!((-2f64).az::<Integer>(), -2);
500 assert_eq!((-1.99f64).az::<Integer>(), -1);
501 assert_eq!((-1f64).az::<Integer>(), -1);
502 assert_eq!((-0.99f64).az::<Integer>(), 0);
503 assert_eq!(0.99f64.az::<Integer>(), 0);
504 assert_eq!(1f64.az::<Integer>(), 1);
505 assert_eq!(1.99f64.az::<Integer>(), 1);
506 assert_eq!(2f64.az::<Integer>(), 2);
507 assert_eq!(f64::MAX.az::<Integer>(), f64_max);
508 assert_eq!(f64::INFINITY.checked_as::<Integer>(), None);
509 assert!(panic::catch_unwind(|| f64::INFINITY.unwrapped_as::<Integer>()).is_err());
510
511 let zero: Integer = Integer::new();
512 let one: Integer = Integer::from(1);
513 let two: Integer = Integer::from(2);
514 let f32_overflow: Integer = Integer::from(1) << 128;
515 let f64_overflow: Integer = Integer::from(1) << 1024;
516 let still_f32_max: Integer = f32_overflow.clone() - 1;
517 let still_f64_max: Integer = f64_overflow.clone() - 1;
518
519 assert_eq!(
520 (*f32_overflow.as_neg()).borrow().az::<f32>(),
521 f32::NEG_INFINITY
522 );
523 assert_eq!((*still_f32_max.as_neg()).borrow().az::<f32>(), -f32::MAX);
524 assert_eq!((*f32_max.as_neg()).borrow().az::<f32>(), -f32::MAX);
525 assert_eq!((*two.as_neg()).borrow().az::<f32>(), -2f32);
526 assert_eq!((*one.as_neg()).borrow().az::<f32>(), -1f32);
527 assert_eq!(zero.borrow().az::<f32>(), 0f32);
528 assert_eq!(one.borrow().az::<f32>(), 1f32);
529 assert_eq!(two.borrow().az::<f32>(), 2f32);
530 assert_eq!(f32_max.borrow().az::<f32>(), f32::MAX);
531 assert_eq!(still_f32_max.borrow().az::<f32>(), f32::MAX);
532 assert_eq!(f32_overflow.borrow().az::<f32>(), f32::INFINITY);
533
534 assert_eq!(
535 (*f64_overflow.as_neg()).borrow().az::<f64>(),
536 f64::NEG_INFINITY
537 );
538 assert_eq!((*still_f64_max.as_neg()).borrow().az::<f64>(), -f64::MAX);
539 assert_eq!((*f64_max.as_neg()).borrow().az::<f64>(), -f64::MAX);
540 assert_eq!((*two.as_neg()).borrow().az::<f64>(), -2f64);
541 assert_eq!((*one.as_neg()).borrow().az::<f64>(), -1f64);
542 assert_eq!(zero.borrow().az::<f64>(), 0f64);
543 assert_eq!(one.borrow().az::<f64>(), 1f64);
544 assert_eq!(two.borrow().az::<f64>(), 2f64);
545 assert_eq!(f64_max.borrow().az::<f64>(), f64::MAX);
546 assert_eq!(f64_overflow.borrow().az::<f64>(), f64::INFINITY);
547 }
548
549 #[test]
550 fn check_round_floats() {
551 let f32_max: Integer = Integer::from((1u32 << 24) - 1) << (127 - 23);
552 let f64_max: Integer = Integer::from((1u64 << 53) - 1) << (1023 - 52);
553
554 assert_eq!(Round(f32::NAN).checked_as::<Integer>(), None);
555 assert!(panic::catch_unwind(|| Round(f32::NAN).unwrapped_as::<Integer>()).is_err());
556 assert_eq!(Round(f32::NEG_INFINITY).checked_as::<Integer>(), None);
557 assert!(
558 panic::catch_unwind(|| Round(f32::NEG_INFINITY).unwrapped_as::<Integer>()).is_err()
559 );
560 assert_eq!(Round(-f32::MAX).az::<Integer>(), *f32_max.as_neg());
561 assert_eq!(Round(-4f32).az::<Integer>(), -4);
562 assert_eq!(Round(-3.5f32).az::<Integer>(), -4);
563 assert_eq!(Round(-3.49f32).az::<Integer>(), -3);
564 assert_eq!(Round(-2.51f32).az::<Integer>(), -3);
565 assert_eq!(Round(-2.5f32).az::<Integer>(), -2);
566 assert_eq!(Round(-2f32).az::<Integer>(), -2);
567 assert_eq!(Round(-1.5f32).az::<Integer>(), -2);
568 assert_eq!(Round(-1.49f32).az::<Integer>(), -1);
569 assert_eq!(Round(-1f32).az::<Integer>(), -1);
570 assert_eq!(Round(-0.5f32).az::<Integer>(), 0);
571 assert_eq!(Round(0.5f32).az::<Integer>(), 0);
572 assert_eq!(Round(1f32).az::<Integer>(), 1);
573 assert_eq!(Round(1.49f32).az::<Integer>(), 1);
574 assert_eq!(Round(1.5f32).az::<Integer>(), 2);
575 assert_eq!(Round(2f32).az::<Integer>(), 2);
576 assert_eq!(Round(2.5f32).az::<Integer>(), 2);
577 assert_eq!(Round(2.51f32).az::<Integer>(), 3);
578 assert_eq!(Round(3.49f32).az::<Integer>(), 3);
579 assert_eq!(Round(3.5f32).az::<Integer>(), 4);
580 assert_eq!(Round(4f32).az::<Integer>(), 4);
581 assert_eq!(Round(f32::MAX).az::<Integer>(), f32_max);
582 assert_eq!(Round(f32::INFINITY).checked_as::<Integer>(), None);
583 assert!(panic::catch_unwind(|| Round(f32::INFINITY).unwrapped_as::<Integer>()).is_err());
584
585 assert_eq!(Round(f64::NAN).checked_as::<Integer>(), None);
586 assert!(panic::catch_unwind(|| Round(f64::NAN).unwrapped_as::<Integer>()).is_err());
587 assert_eq!(Round(f64::NEG_INFINITY).checked_as::<Integer>(), None);
588 assert!(
589 panic::catch_unwind(|| Round(f64::NEG_INFINITY).unwrapped_as::<Integer>()).is_err()
590 );
591 assert_eq!(Round(-f64::MAX).az::<Integer>(), *f64_max.as_neg());
592 assert_eq!(Round(-4f64).az::<Integer>(), -4);
593 assert_eq!(Round(-3.5f64).az::<Integer>(), -4);
594 assert_eq!(Round(-3.49f64).az::<Integer>(), -3);
595 assert_eq!(Round(-2.51f64).az::<Integer>(), -3);
596 assert_eq!(Round(-2.5f64).az::<Integer>(), -2);
597 assert_eq!(Round(-2f64).az::<Integer>(), -2);
598 assert_eq!(Round(-1.5f64).az::<Integer>(), -2);
599 assert_eq!(Round(-1.49f64).az::<Integer>(), -1);
600 assert_eq!(Round(-1f64).az::<Integer>(), -1);
601 assert_eq!(Round(-0.5f64).az::<Integer>(), 0);
602 assert_eq!(Round(0.5f64).az::<Integer>(), 0);
603 assert_eq!(Round(1f64).az::<Integer>(), 1);
604 assert_eq!(Round(1.49f64).az::<Integer>(), 1);
605 assert_eq!(Round(1.5f64).az::<Integer>(), 2);
606 assert_eq!(Round(2f64).az::<Integer>(), 2);
607 assert_eq!(Round(2.5f64).az::<Integer>(), 2);
608 assert_eq!(Round(2.51f64).az::<Integer>(), 3);
609 assert_eq!(Round(3.49f64).az::<Integer>(), 3);
610 assert_eq!(Round(3.5f64).az::<Integer>(), 4);
611 assert_eq!(Round(4f64).az::<Integer>(), 4);
612 assert_eq!(Round(f64::MAX).az::<Integer>(), f64_max);
613 assert_eq!(Round(f64::INFINITY).checked_as::<Integer>(), None);
614 assert!(panic::catch_unwind(|| Round(f64::INFINITY).unwrapped_as::<Integer>()).is_err());
615 }
616}