1use std::{fmt, mem};
2use std::cmp::{min, Ordering};
3use std::convert::TryFrom;
4use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
5use std::num::{NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
6use std::str::FromStr;
7
8use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
9use smallvec::{smallvec, SmallVec};
10
11use crate::{NonZero, NonZeroSign, Ubig};
12use crate::integer::big::{BITS_PER_WORD, NonZeroUbig};
13use crate::integer::big::io::{highest_word, words_to_u128};
14use crate::integer::big::ops::div::div;
15use crate::integer::big::ops::non_zero::is_one_non_zero;
16use crate::integer::big::ops::normalize::{gcd_scalar, simplify_fraction_without_info};
17use crate::integer::big::properties::cmp;
18use crate::rational::big::{Big, NonZeroBig};
19use crate::rational::{Rational128, RationalUsize};
20use crate::rational::small::ops::building_blocks::{simplify128, simplify16, simplify32, simplify64, simplify8, simplify_usize};
21use crate::sign::Sign;
22use crate::sign::Signed;
23
24impl<const S: usize> Big<S> {
25 pub fn new(numerator: i64, denominator: u64) -> Option<Self> {
26 if 0 != denominator {
27 Some({
28 let mut numerator_abs = numerator.unsigned_abs() as usize;
29 let mut denominator = denominator as usize;
30 if numerator == 0 {
31 Self::zero()
32 } else if numerator_abs == denominator {
33 Self {
34 sign: Signed::signum(&numerator),
35 numerator: Ubig::one(),
36 denominator: NonZeroUbig::one(),
37 }
38 } else {
39 if numerator_abs != 1 && denominator != 1 {
40 let gcd = gcd_scalar(numerator_abs, denominator);
41
42 numerator_abs /= gcd;
43 denominator /= gcd;
44 }
45
46 Self {
47 sign: Signed::signum(&numerator),
48 numerator: Ubig::new(numerator_abs),
49 denominator: unsafe { NonZeroUbig::new_unchecked(denominator) },
50 }
51 }
52 })
53 } else {
54 None
55 }
56 }
57}
58
59impl<const S: usize> Default for Big<S> {
60 fn default() -> Self {
61 Self::zero()
62 }
63}
64
65impl<const S: usize> fmt::Debug for Big<S> {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 fmt::Display::fmt(self, f)
69 }
70}
71
72macro_rules! forwards {
73 ($ty:ty) => {
74 impl<const S: usize> From<&$ty> for Big<S> {
75 fn from(other: &$ty) -> Self {
76 From::from(*other)
77 }
78 }
79 }
80}
81
82forwards!(u8);
83forwards!(u16);
84forwards!(u32);
85forwards!(u64);
86forwards!(NonZeroU8);
87forwards!(NonZeroU16);
88forwards!(NonZeroU32);
89forwards!(NonZeroU64);
90forwards!(i8);
91forwards!(i16);
92forwards!(i32);
93forwards!(i64);
94forwards!(NonZeroI8);
95forwards!(NonZeroI16);
96forwards!(NonZeroI32);
97forwards!(NonZeroI64);
98
99macro_rules! from_integer_unsigned {
100 ($ty:ty) => {
101 impl<const S: usize> From<$ty> for Big<S> {
102 fn from(value: $ty) -> Self {
103 Self {
104 sign: Signed::signum(&value),
105 numerator: Ubig::from(value as usize),
106 denominator: NonZeroUbig::one(),
107 }
108 }
109 }
110 }
111}
112
113from_integer_unsigned!(u8);
114from_integer_unsigned!(u16);
115from_integer_unsigned!(u32);
116from_integer_unsigned!(u64);
117from_integer_unsigned!(usize);
118
119macro_rules! from_integer_unsigned_non_zero {
120 ($ty:ty) => {
121 impl<const S: usize> From<$ty> for Big<S> {
122 fn from(value: $ty) -> Self {
123 Self {
124 sign: Signed::signum(&value),
125 numerator: Ubig::from(value.get() as usize),
126 denominator: NonZeroUbig::one(),
127 }
128 }
129 }
130 }
131}
132
133from_integer_unsigned_non_zero!(NonZeroU8);
134from_integer_unsigned_non_zero!(NonZeroU16);
135from_integer_unsigned_non_zero!(NonZeroU32);
136from_integer_unsigned_non_zero!(NonZeroU64);
137from_integer_unsigned_non_zero!(NonZeroUsize);
138
139macro_rules! from_integer_signed {
140 ($ty:ty) => {
141 impl<const S: usize> From<$ty> for Big<S> {
142 fn from(value: $ty) -> Self {
143 Self {
144 sign: Signed::signum(&value),
145 numerator: Ubig::new(value.unsigned_abs() as usize),
146 denominator: NonZeroUbig::one(),
147 }
148 }
149 }
150 }
151}
152
153from_integer_signed!(i8);
154from_integer_signed!(i16);
155from_integer_signed!(i32);
156from_integer_signed!(i64);
157from_integer_signed!(isize);
158
159macro_rules! from_integer_signed_non_zero {
160 ($ty:ty) => {
161 impl<const S: usize> From<$ty> for Big<S> {
162 fn from(value: $ty) -> Self {
163 Self {
164 sign: Signed::signum(&value),
165 numerator: Ubig::from(value.get().unsigned_abs() as usize),
166 denominator: NonZeroUbig::one(),
167 }
168 }
169 }
170 }
171}
172
173from_integer_signed_non_zero!(NonZeroI8);
174from_integer_signed_non_zero!(NonZeroI16);
175from_integer_signed_non_zero!(NonZeroI32);
176from_integer_signed_non_zero!(NonZeroI64);
177from_integer_signed_non_zero!(NonZeroIsize);
178
179macro_rules! impl_from_iu {
180 ($numerator:ty, $denominator:ty, $simplify:ident) => {
181 impl<const S: usize> From<($numerator, $denominator)> for Big<S> {
182 #[inline]
183 fn from((numerator, denominator): ($numerator, $denominator)) -> Self {
184 assert!(denominator.is_not_zero());
186
187 if mem::size_of::<$numerator>() > mem::size_of::<usize>() {
188 debug_assert!(numerator.abs() <= usize::MAX as $numerator);
189 }
190 if mem::size_of::<$denominator>() > mem::size_of::<usize>() {
191 debug_assert!(denominator <= usize::MAX as $denominator);
192 }
193
194 if numerator == 0 {
195 <Self as num_traits::Zero>::zero()
196 } else {
197 let sign = <$numerator as Signed>::signum(&numerator);
198 let (numerator, denominator) = $simplify(numerator.unsigned_abs(), denominator);
199
200 Self {
201 sign,
202 numerator: Ubig::new(numerator as usize),
203 denominator: NonZeroUbig::new(denominator as usize).unwrap(),
204 }
205 }
206 }
207 }
208 }
209}
210
211impl_from_iu!(i8, u8, simplify8);
212impl_from_iu!(i16, u16, simplify16);
213impl_from_iu!(i32, u32, simplify32);
214impl_from_iu!(i64, u64, simplify64);
215impl_from_iu!(i128, u128, simplify128);
216
217macro_rules! impl_from_ii {
218 ($ty:ty, $simplify:ident) => {
219 impl<const S: usize> From<($ty, $ty)> for Big<S> {
220 #[inline]
221 fn from((numerator, denominator): ($ty, $ty)) -> Self {
222 assert!(denominator.is_not_zero());
224
225 if mem::size_of::<$ty>() > mem::size_of::<usize>() {
226 debug_assert!(numerator.unsigned_abs() as u128 <= usize::MAX as u128);
227 debug_assert!(denominator.unsigned_abs() as u128 <= usize::MAX as u128);
228 }
229
230 if numerator == 0 {
231 <Self as num_traits::Zero>::zero()
232 } else {
233 let sign = <$ty as Signed>::signum(&numerator) * <$ty as Signed>::signum(&denominator);
234 debug_assert_ne!(sign, Sign::Zero);
235
236 let (numerator, denominator) = $simplify(
237 numerator.unsigned_abs(), denominator.unsigned_abs(),
238 );
239
240 Self {
241 sign,
242 numerator: Ubig::new(numerator as usize),
243 denominator: NonZeroUbig::new(denominator as usize).unwrap(),
244 }
245 }
246 }
247 }
248 }
249}
250
251impl_from_ii!(i8, simplify8);
252impl_from_ii!(i16, simplify16);
253impl_from_ii!(i32, simplify32);
254impl_from_ii!(i64, simplify64);
255impl_from_ii!(i128, simplify128);
256impl_from_ii!(isize, simplify_usize);
257
258macro_rules! from_small_rational {
263 ($small:ident, $new_numerator:path, $new_denominator_unchecked:path) => {
264 impl<const S: usize> From<$small> for Big<S> {
265 #[inline]
266 fn from(value: $small) -> Self {
267 match value.sign {
268 Sign::Zero => {
269 debug_assert_eq!(value.numerator, 0);
270
271 <Self as num_traits::Zero>::zero()
272 }
273 Sign::Positive | Sign::Negative => Self {
274 sign: value.sign,
275 numerator: $new_numerator(value.numerator),
277 denominator: unsafe {
278 $new_denominator_unchecked(value.denominator)
280 },
281 },
282 }
283 }
284 }
285
286 impl<const S: usize> From<&$small> for Big<S> {
287 #[inline]
288 fn from(value: &$small) -> Self {
289 From::from(*value)
290 }
291 }
292 }
293}
294
295from_small_rational!(Rational128, Ubig::new_u128, NonZeroUbig::new_u128_unchecked);
296from_small_rational!(RationalUsize, Ubig::new, NonZeroUbig::new_unchecked);
297
298const ONES_32: u32 = (1 << 8) - 1;
299const ONES_64: u64 = (1 << 11) - 1;
300
301impl<const S: usize> FromPrimitive for Big<S> {
302 fn from_i64(n: i64) -> Option<Self> {
303 Some(Self {
304 sign: Signed::signum(&n),
305 numerator: Ubig::new(n.unsigned_abs() as usize),
306 denominator: NonZeroUbig::one(),
307 })
308 }
309
310 fn from_u64(n: u64) -> Option<Self> {
311 Some(Self {
312 sign: if n != 0 { Sign::Positive } else { Sign::Zero },
313 numerator: Ubig::new(n as usize),
314 denominator: NonZeroUbig::one(),
315 })
316 }
317
318 fn from_f32(n: f32) -> Option<Self> {
319 Self::from_float_kind(f32_kind(n))
320 }
321
322 fn from_f64(n: f64) -> Option<Self> {
323 Self::from_float_kind(f64_kind(n))
324 }
325}
326
327pub enum FloatKind {
329 Zero,
330 Subnormal(FloatAsRatio),
331 Infinity,
332 NaN,
333 Normal(FloatAsRatio),
334}
335
336pub struct FloatAsRatio {
337 pub sign: u64,
338 pub exponent: i32,
339 pub fraction: NonZeroU64,
340}
341
342pub fn f32_kind(n: f32) -> FloatKind {
343 let n = n.to_bits();
344 let sign = (n & 0b1000_0000_0000_0000_0000_0000_0000_0000) >> (32 - 1);
345 let exponent = (n & 0b0111_1111_1000_0000_0000_0000_0000_0000) >> (32 - 1 - 8);
346 let fraction = n & 0b0000_0000_0111_1111_1111_1111_1111_1111;
347
348 match (exponent, fraction) {
349 (0, 0) => FloatKind::Zero,
350 (0, _) => FloatKind::Subnormal(FloatAsRatio {
351 sign: sign as u64,
352 exponent: 1 - 127 - 23,
353 fraction: unsafe {
354 NonZeroU64::new_unchecked(fraction as u64)
356 },
357 }),
358 (ONES_32, 0) => FloatKind::Infinity,
359 (ONES_32, _) => FloatKind::NaN,
360 _ => FloatKind::Normal(FloatAsRatio {
361 sign: sign as u64,
362 exponent: exponent as i32 - 127 - 23,
363 fraction: unsafe {
364 NonZeroU64::new_unchecked((fraction + (1 << 23)) as u64)
366 },
368 }),
369 }
370}
371
372pub fn f64_kind(n: f64) -> FloatKind {
373 let n = n.to_bits();
374 let sign = (n & 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000) >> (64 - 1);
375 let exponent = (n & 0b0111_1111_1111_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000) >> (64 - 1 - 11);
376 let fraction = n & 0b0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111;
377
378 assert_eq!(mem::size_of::<usize>(), mem::size_of::<u64>());
379
380 match (exponent, fraction) {
381 (0, 0) => FloatKind::Zero,
382 (0, _) => FloatKind::Subnormal(FloatAsRatio {
383 sign,
384 exponent: 1 - 1023 - 52,
385 fraction: unsafe {
386 NonZeroU64::new_unchecked(fraction)
388 },
389 }),
390 (ONES_64, 0) => FloatKind::Infinity,
391 (ONES_64, _) => FloatKind::NaN,
392 _ => FloatKind::Normal(FloatAsRatio {
393 sign,
394 exponent: exponent as i32 - 1023 - 52,
395 fraction: unsafe {
396 NonZeroU64::new_unchecked(fraction + (1 << 52))
398 },
399 }),
400 }
401}
402
403impl<const S: usize> Big<S> {
404 fn from_float_kind(kind: FloatKind) -> Option<Self> {
405 match kind {
406 FloatKind::Subnormal(as_ratio) | FloatKind::Normal(as_ratio) => {
407 let (numerator, denominator) = from_float_helper(as_ratio.exponent, as_ratio.fraction);
408
409 Some(Self {
410 sign: if as_ratio.sign > 0 { Sign::Negative } else { Sign::Positive },
411 numerator,
412 denominator,
413 })
414 }
415 FloatKind::Zero => Some(Self::zero()),
416 _ => None,
417 }
418 }
419}
420
421pub fn from_float_helper<const S: usize>(power: i32, fraction: NonZeroU64) -> (Ubig<S>, NonZeroUbig<S>) {
422 match power.cmp(&0) {
423 Ordering::Less => {
424 let numerator_zeros = fraction.trailing_zeros();
425 let shift = power.unsigned_abs();
426
427 let numerator_shift = min(numerator_zeros, shift);
428 let denominator_shift = shift - numerator_shift;
429
430 let words_shift = denominator_shift / BITS_PER_WORD;
431 let bits_shift = denominator_shift % BITS_PER_WORD;
432 let size = words_shift + 1;
433 let mut denominator = SmallVec::with_capacity(size as usize);
434
435 denominator.extend(std::iter::repeat_n(0, words_shift as usize));
436 denominator.push(1 << bits_shift);
437
438 let numerator = unsafe {
439 Ubig::from_inner_unchecked(smallvec![fraction.get() as usize >> numerator_shift])
441 };
442
443 (numerator, unsafe { NonZeroUbig::from_inner_unchecked(denominator) })
444 }
445 Ordering::Equal => {
446 (unsafe {
447 Ubig::from_inner_unchecked(smallvec![fraction.get() as usize])
449 }, NonZeroUbig::one())
450 }
451 Ordering::Greater => {
452 let shift = power.unsigned_abs();
453 let words_shift = shift / BITS_PER_WORD;
454 let bits_shift = shift % BITS_PER_WORD;
455
456 let overflows = fraction.leading_zeros() < bits_shift;
457 let size = 1 + words_shift + if overflows { 1 } else { 0 };
458 let mut numerator = SmallVec::with_capacity(size as usize);
459
460 numerator.extend(std::iter::repeat_n(0, words_shift as usize));
461
462 numerator.push((fraction.get() as usize) << bits_shift);
463 if overflows {
464 numerator.push(fraction.get() as usize >> (BITS_PER_WORD - bits_shift));
465 }
466
467 (
468 unsafe {
469 Ubig::from_inner_unchecked(numerator)
471 },
472 NonZeroUbig::one(),
473 )
474 }
475 }
476}
477
478impl<const S: usize> Big<S> {
479 #[cfg(test)]
486 pub(crate) fn from_raw_limbs<const I1: usize, const I2: usize>(
487 sign: Sign,
488 numerator: [usize; I1],
489 denominator: [usize; I2],
490 ) -> Self {
491 let numerator = Ubig::try_from(numerator).expect("well formed numerator");
492 let denominator = NonZeroUbig::try_from(denominator).expect("well formed denominator");
493 debug_assert_eq!(sign == Sign::Zero, numerator.is_zero());
494
495 Self { sign, numerator, denominator }
496 }
497}
498
499impl<const S: usize, const I1: usize, const I2: usize> TryFrom<(Sign, [usize; I1], [usize; I2])> for Big<S> {
500 type Error = ();
502
503 fn try_from((sign, numerator, denominator): (Sign, [usize; I1], [usize; I2])) -> Result<Self, Self::Error> {
504 match (sign, Ubig::try_from(numerator), NonZeroUbig::try_from(denominator)) {
505 (Sign::Positive | Sign::Negative, Ok(numerator), Ok(denominator)) if !numerator.is_zero() => {
506 let mut numerator = numerator;
512 let mut denominator = denominator;
513
514 unsafe {
518 simplify_fraction_without_info(numerator.inner_mut(), denominator.inner_mut());
519 }
520
521 Ok(Self { sign, numerator, denominator })
522 }
523 (Sign::Zero, Ok(numerator), Ok(_)) if numerator.is_zero() => Ok(Self::zero()),
524 _ => Err(()),
525 }
526 }
527}
528
529impl<const S: usize> From<&Big<S>> for Big<S> {
530 fn from(reference: &Big<S>) -> Self {
531 reference.clone()
532 }
533}
534
535impl<const S: usize> num_traits::Zero for Big<S> {
536 fn zero() -> Self {
537 Self {
538 sign: Sign::Zero,
539 numerator: Ubig::zero(),
540 denominator: NonZeroUbig::one(),
541 }
542 }
543
544 fn set_zero(&mut self) {
545 self.sign = Sign::Zero;
546 self.numerator.set_zero();
547 self.denominator.set_one();
548 }
549
550 fn is_zero(&self) -> bool {
551 self.sign == Sign::Zero
552 }
553}
554
555impl<const S: usize> num_traits::One for Big<S> {
556 fn one() -> Self {
557 Self {
558 sign: Sign::Positive,
559 numerator: Ubig::one(),
560 denominator: NonZeroUbig::one(),
561 }
562 }
563
564 fn set_one(&mut self) {
565 self.sign = Sign::Positive;
566 self.numerator.set_one();
567 self.denominator.set_one();
568 }
569
570 fn is_one(&self) -> bool {
571 self.sign == Sign::Positive &&
572 self.denominator[0] == 1 && self.numerator.len() == 1 &&
573 self.numerator[0] == 1 && self.denominator.len() == 1
574 }
575}
576
577impl<const S: usize> num_traits::One for NonZeroBig<S> {
578 fn one() -> Self {
579 Self {
580 sign: NonZeroSign::Positive,
581 numerator: NonZeroUbig::one(),
582 denominator: NonZeroUbig::one(),
583 }
584 }
585
586 fn set_one(&mut self) {
587 self.sign = NonZeroSign::Positive;
588 self.numerator.set_one();
589 self.denominator.set_one();
590 }
591
592 fn is_one(&self) -> bool {
593 self.sign == NonZeroSign::Positive &&
594 self.numerator[0] == 1 && self.denominator[0] == 1 &&
595 self.numerator.len() == 1 && self.denominator.len() == 1
596 }
597}
598
599impl<const S: usize> Big<S> {
600 pub fn new_signed<T: Into<Sign>>(sign: T, numerator: u64, denominator: u64) -> Option<Self> {
601 if denominator != 0 {
602 let sign = sign.into();
603
604 match (sign, numerator) {
605 (Sign::Positive | Sign::Negative, n) if n != 0 => {
606 let (numerator, denominator) = simplify64(numerator, denominator);
607
608 Some(Self {
609 sign,
610 numerator: Ubig::new(numerator as usize),
611 denominator: unsafe { NonZeroUbig::new_unchecked(denominator as usize) },
612 })
613 }
614 (Sign::Zero, 0) => Some(Self::zero()),
615 _ => None,
616 }
617 } else {
618 None
619 }
620 }
621}
622
623impl<const S: usize> FromStr for Big<S> {
624 type Err = &'static str;
625
626 fn from_str(s: &str) -> Result<Self, Self::Err> {
627 let _radix = 10;
628
629 if s.contains('.') || s.contains(',') {
630 return Err("Decimal separators are not supported");
631 }
632
633 match s.len() {
634 0 => Err("Empty string"),
635 _ => {
636 let (sign, s) = match s.as_bytes().first() {
639 Some(b'+') => (Sign::Positive, &s[1..]),
640 Some(b'-') => (Sign::Negative, &s[1..]),
641 _ => (Sign::Positive, s),
642 };
643
644 match s.find('/') {
645 None => {
646 let numerator = Ubig::from_str(s)?;
647
648 Ok(Big {
649 sign: if numerator.is_not_zero() { sign } else { Sign::Zero },
650 numerator,
651 denominator: NonZeroUbig::one(),
652 })
653 }
654 Some(index) => {
655 let (numerator_text, denominator_text) = (&s[..index], &s[(index + 1)..]);
657 let mut numerator = Ubig::from_str(numerator_text)?;
658 let mut denominator = NonZeroUbig::from_str(denominator_text)
659 .map_err(|value| {
660 match value {
661 "Zero value" => "Zero division",
662 other => other,
663 }
664 })?;
665
666 Ok(if numerator.is_not_zero() {
667 unsafe {
668 simplify_fraction_without_info(numerator.inner_mut(), denominator.inner_mut());
670 }
671
672 Big {
673 sign,
674 numerator,
675 denominator,
676 }
677 } else {
678 Zero::zero()
679 })
680 }
681 }
682 }
683 }
684 }
685}
686
687impl<const S: usize> fmt::Display for Big<S> {
688 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
689 match self.sign {
690 Sign::Positive => {}
691 Sign::Zero => return f.write_str("0"),
692 Sign::Negative => f.write_str("-")?,
693 }
694
695 fmt::Display::fmt(&self.numerator, f)?;
696
697 if !self.denominator.is_one() {
698 f.write_str("/")?;
699 fmt::Display::fmt(&self.denominator, f)?;
700 }
701
702 fmt::Result::Ok(())
703 }
704}
705
706macro_rules! integer_magnitude {
712 ($value:expr) => {
713 {
714 if unsafe { !is_one_non_zero(&$value.denominator) } {
715 match cmp(&$value.numerator, &$value.denominator) {
716 Ordering::Less => Some(0_u128),
717 Ordering::Equal => Some(1_u128),
718 Ordering::Greater => {
719 let result = unsafe {
720 div::<S>(&$value.numerator, &$value.denominator)
722 };
723
724 words_to_u128(&result)
725 }
726 }
727 } else {
728 words_to_u128(&$value.numerator)
729 }
730 }
731 }
732}
733
734macro_rules! signed_small {
735 ($value:expr, $target:ty, $unsigned:ty) => {
736 match $value.sign {
737 Sign::Zero => Some(0),
738 Sign::Positive => integer_magnitude!($value)
739 .and_then(|magnitude| <$target>::try_from(magnitude).ok()),
740 Sign::Negative => integer_magnitude!($value)
741 .and_then(|magnitude| {
742 if magnitude <= <$target>::MIN.unsigned_abs() as u128 {
745 Some((magnitude as $unsigned).wrapping_neg() as $target)
746 } else {
747 None
748 }
749 }),
750 }
751 }
752}
753
754macro_rules! unsigned_small {
755 ($value:expr, $target:ty) => {
756 match $value.sign {
757 Sign::Zero => Some(0),
758 Sign::Negative => None,
759 Sign::Positive => integer_magnitude!($value)
760 .and_then(|magnitude| <$target>::try_from(magnitude).ok()),
761 }
762 }
763}
764
765macro_rules! ratio_to_float {
769 ($value:expr, $target:ty, $to_float:ident) => {
770 {
771 let numerator = $value.numerator.$to_float().unwrap();
772 let denominator = $value.denominator.$to_float().unwrap();
773
774 if numerator.is_finite() && denominator.is_finite() {
775 numerator / denominator
776 } else {
777 let (numerator, numerator_shift) = highest_word(&$value.numerator);
784 let (denominator, denominator_shift) = highest_word(&$value.denominator);
785
786 let exponent = numerator_shift as i32 - denominator_shift as i32;
787 let half = exponent / 2;
790
791 (numerator as $target / denominator as $target)
792 * (2 as $target).powi(half)
793 * (2 as $target).powi(exponent - half)
794 }
795 }
796 }
797}
798
799impl<const S: usize> ToPrimitive for Big<S> {
800 fn to_isize(&self) -> Option<isize> {
801 signed_small!(self, isize, usize)
802 }
803
804 fn to_i8(&self) -> Option<i8> {
805 signed_small!(self, i8, u8)
806 }
807
808 fn to_i16(&self) -> Option<i16> {
809 signed_small!(self, i16, u16)
810 }
811
812 fn to_i32(&self) -> Option<i32> {
813 signed_small!(self, i32, u32)
814 }
815
816 fn to_i64(&self) -> Option<i64> {
817 signed_small!(self, i64, u64)
818 }
819
820 fn to_i128(&self) -> Option<i128> {
821 signed_small!(self, i128, u128)
822 }
823
824 fn to_usize(&self) -> Option<usize> {
825 unsigned_small!(self, usize)
826 }
827
828 fn to_u8(&self) -> Option<u8> {
829 unsigned_small!(self, u8)
830 }
831
832 fn to_u16(&self) -> Option<u16> {
833 unsigned_small!(self, u16)
834 }
835
836 fn to_u32(&self) -> Option<u32> {
837 unsigned_small!(self, u32)
838 }
839
840 fn to_u64(&self) -> Option<u64> {
841 unsigned_small!(self, u64)
842 }
843
844 fn to_u128(&self) -> Option<u128> {
845 unsigned_small!(self, u128)
846 }
847
848 fn to_f32(&self) -> Option<f32> {
849 Some(match self.sign {
850 Sign::Zero => 0_f32,
851 Sign::Positive => ratio_to_float!(self, f32, to_f32),
852 Sign::Negative => -ratio_to_float!(self, f32, to_f32),
853 })
854 }
855
856 fn to_f64(&self) -> Option<f64> {
857 Some(match self.sign {
858 Sign::Zero => 0_f64,
859 Sign::Positive => ratio_to_float!(self, f64, to_f64),
860 Sign::Negative => -ratio_to_float!(self, f64, to_f64),
861 })
862 }
863}
864
865#[cfg(test)]
866mod test {
867 use std::cmp::Ordering;
868 use std::str::FromStr;
869
870 use num_traits::{One, ToPrimitive, Zero};
871 use smallvec::{smallvec, SmallVec};
872
873 use crate::{Abs, NonZeroSign, Rational128, Rational64, RationalBig, RationalUsize, Sign, Ubig};
874 use crate::integer::big::{BITS_PER_WORD, NonZeroUbig};
875 use crate::integer::big::io::from_str_radix;
876 use crate::integer::big::ops::normalize::simplify_fraction_without_info;
877 use crate::rational::big::{Big, Big8, NonZeroBig8};
878 use crate::RB;
879
880 #[test]
881 fn from() {
882 let x = Rational64::new(4, 3).unwrap();
883 let y = Big8::from(x);
884 let z = RB!(4, 3);
885 assert_eq!(y, z);
886
887 let x = <Big8 as num_traits::FromPrimitive>::from_f32(0_f32).unwrap();
888 assert_eq!(x, RB!(0, 1));
889
890 let x = <Big8 as num_traits::FromPrimitive>::from_f32(1_f32).unwrap();
891 assert_eq!(x, RB!(1, 1));
892
893 let x = <Big8 as num_traits::FromPrimitive>::from_f32(0.5).unwrap();
894 assert_eq!(x, RB!(1, 2));
895
896 let x = <Big8 as num_traits::FromPrimitive>::from_f32(2_f32).unwrap();
897 assert_eq!(x, RB!(2, 1));
898
899 let x = <Big8 as num_traits::FromPrimitive>::from_f32(1.5_f32).unwrap();
900 assert_eq!(x, RB!(3, 2));
901 let x = <Big8 as num_traits::FromPrimitive>::from_f64(0_f64).unwrap();
902 assert_eq!(x, RB!(0, 1));
903
904 let x = <Big8 as num_traits::FromPrimitive>::from_f64(1_f64).unwrap();
905 assert_eq!(x, RB!(1, 1));
906
907 let x = <Big8 as num_traits::FromPrimitive>::from_f64(0.5).unwrap();
908 assert_eq!(x, RB!(1, 2));
909
910 let x = <Big8 as num_traits::FromPrimitive>::from_f64(2_f64).unwrap();
911 assert_eq!(x, RB!(2, 1));
912
913 let x = <Big8 as num_traits::FromPrimitive>::from_f64(1.5_f64).unwrap();
914 assert_eq!(x, RB!(3, 2));
915
916 let x = <Big8 as num_traits::FromPrimitive>::from_f64(f64::MIN_POSITIVE).unwrap();
917 let (words, bits) = (1022 / BITS_PER_WORD, 1022 % BITS_PER_WORD);
918 let mut denominator = smallvec![0; words as usize];
919 denominator.push(1 << bits);
920 let expected = Big8 {
921 sign: Sign::Positive,
922 numerator: Ubig::one(),
923 denominator: unsafe { NonZeroUbig::from_inner_unchecked(denominator) },
924 };
925 assert_eq!(x, expected);
926
927 let x = <Big8 as num_traits::FromPrimitive>::from_f64(f64::MAX).unwrap();
928 let total_shift = (1 << (11 - 1)) - 1 - 52;
929 let (words, bits) = (total_shift / BITS_PER_WORD, total_shift % BITS_PER_WORD);
930 let mut numerator = smallvec![0; words as usize];
931 numerator.push(((1 << (52 + 1)) - 1) << bits); let expected = Big8 {
933 sign: Sign::Positive,
934 numerator: unsafe { Ubig::from_inner_unchecked(numerator) },
935 denominator: NonZeroUbig::one(),
936 };
937 assert_eq!(x, expected);
938
939 let y = <Big8 as num_traits::FromPrimitive>::from_f64(4f64 / 3f64).unwrap();
940 let z = RB!(4, 3);
941 assert!((y - z).abs() < Big8::new(1, 2 << 10).unwrap());
942
943 assert_eq!(
945 RB!(28793048285076456849987446449190283896766061557132266451844835664715760516297522370041860391064901485759493828054533728788532902755163518009654497157537048672862208_f64),
946 RationalBig {
947 sign: Sign::Positive,
948 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![0, 0, 0, 0, 0, 0, 0, 0, 1 << 31]) },
949 denominator: NonZeroUbig::one(),
950 }
951 );
952
953 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_i64(0), Some(RB!(0)));
954 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_i64(1), Some(RB!(1)));
955 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_i64(-1), Some(-RB!(1)));
956 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_u64(0), Some(RB!(0)));
957 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_u64(1), Some(RB!(1)));
958 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f32(f32::NAN), None);
959 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f32(f32::INFINITY), None);
960 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f32(f32::NEG_INFINITY), None);
961 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f32(2_i64.pow(22) as f32), Some(RB!(2_i64.pow(22), 1)));
962 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f32(2_i64.pow(23) as f32), Some(RB!(2_i64.pow(23), 1)));
963 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f64(f64::NAN), None);
964 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f64(f64::INFINITY), None);
965 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f64(f64::NEG_INFINITY), None);
966 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f64(2_i64.pow(52) as f64), Some(RB!(2_i64.pow(52), 1)));
967 assert_eq!(<Big8 as num_traits::FromPrimitive>::from_f64(2_i64.pow(53) as f64), Some(RB!(2_i64.pow(53), 1)));
968 }
969
970 #[test]
971 fn test_one() {
972 let mut x = RB!(132);
973 x.set_one();
974 assert_eq!(x, RB!(1));
975 assert_eq!(RB!(1), Big::one());
976 }
977
978 #[test]
979 fn test_one_respects_sign() {
980 assert!(RB!(1).is_one());
981 assert!(!RB!(-1).is_one());
982 assert!(!RB!(0).is_one());
983 assert!(!RB!(2).is_one());
984 assert!(!RB!(1, 2).is_one());
985
986 let mut negative = RB!(-5, 6);
988 negative.set_one();
989 assert_eq!(negative.sign, Sign::Positive);
990 assert!(negative.is_one());
991 assert_eq!(negative, RB!(1));
992
993 let mut zero = RB!(0);
995 zero.set_one();
996 assert_eq!(zero.sign, Sign::Positive);
997 assert!(zero.is_one());
998 assert_eq!(zero, RB!(1));
999
1000 let mut non_zero = NonZeroBig8 {
1002 sign: NonZeroSign::Negative,
1003 numerator: NonZeroUbig::one(),
1004 denominator: NonZeroUbig::one(),
1005 };
1006 assert!(!non_zero.is_one());
1007 non_zero.set_one();
1008 assert_eq!(non_zero.sign, NonZeroSign::Positive);
1009 assert!(non_zero.is_one());
1010 assert!(non_zero == NonZeroBig8::one());
1012 }
1013
1014 #[test]
1015 fn test_signed() {
1016 assert_eq!(Big::new_signed(Sign::Positive, 1, 2).unwrap(), RB!(1, 2));
1017 assert_eq!(Big::new_signed(Sign::Zero, 0, 1).unwrap(), RB!(0));
1018 assert_eq!(Big::new_signed(Sign::Negative, 1, 3).unwrap(), RB!(-1, 3));
1019 }
1020
1021 #[test]
1022 fn test_new() {
1023 assert_eq!(RB!(3, 3), RB!(1));
1024 }
1025
1026 #[test]
1027 fn from_int() {
1028 assert_eq!(Big::from(0_i32), RB!(0));
1029 assert_eq!(Big::from(0_u32), RB!(0));
1030 assert_eq!(Big::from(1_i64), RB!(1));
1031 assert_eq!(Big::from(19_u8), RB!(19));
1032 assert_eq!(Big::from(-1_i16), RB!(-1));
1033 }
1034
1035 #[test]
1036 fn from_large_small_rational() {
1037 let zero = Big8::from(Rational128::zero());
1039 assert_eq!(zero.sign, Sign::Zero);
1040 assert!(zero.numerator.is_zero());
1041 assert!(zero.denominator.is_one());
1042 assert_eq!(zero, RB!(0));
1043 assert_eq!(Big8::from(RationalUsize::zero()), RB!(0));
1044
1045 assert_eq!(Big8::from(Rational128::one()), RB!(1));
1046 assert_eq!(Big8::from(RationalUsize::one()), RB!(1));
1047
1048 assert_eq!(Big8::from(Rational128::new(-1, 1).unwrap()), RB!(-1));
1049 assert_eq!(Big8::from(Rational128::new(-3, 2).unwrap()), RB!(-3, 2));
1050 assert_eq!(Big8::from(RationalUsize::new(-1, 1).unwrap()), RB!(-1));
1051 assert_eq!(Big8::from(RationalUsize::new(-3, 2).unwrap()), RB!(-3, 2));
1052
1053 assert_eq!(Big8::from(Rational128::new(4, 6).unwrap()), RB!(2, 3));
1055 assert_eq!(Big8::from(RationalUsize::new(-4, 6).unwrap()), RB!(-2, 3));
1056
1057 for value in [Rational128::zero(), Rational128::one(), Rational128::new(-3, 2).unwrap()] {
1059 assert_eq!(Big8::from(&value), Big8::from(value));
1060 }
1061 for value in [RationalUsize::zero(), RationalUsize::one(), RationalUsize::new(-3, 2).unwrap()] {
1062 assert_eq!(Big8::from(&value), Big8::from(value));
1063 }
1064
1065 assert_eq!(
1066 Big8::from(RationalUsize::new_signed(Sign::Negative, usize::MAX, 1).unwrap()),
1067 Big8::from_str(&format!("-{}", usize::MAX)).unwrap(),
1068 );
1069 }
1070
1071 #[test]
1072 fn from_rational_128_multiple_words() {
1073 let words_needed = 128 / BITS_PER_WORD as usize;
1075
1076 let large_numerator = Rational128::new_signed(Sign::Positive, u128::MAX, 1).unwrap();
1077 assert_eq!(
1078 Big8::from(large_numerator),
1079 Big8::from_str("340282366920938463463374607431768211455").unwrap(),
1080 );
1081 assert_eq!(Big8::from(large_numerator).to_string(), u128::MAX.to_string());
1082 assert_eq!(Big8::from(large_numerator).numerator.len(), words_needed);
1083
1084 let large_denominator = Rational128::new_signed(Sign::Negative, 1, u128::MAX).unwrap();
1085 assert_eq!(
1086 Big8::from(large_denominator),
1087 Big8::from_str("-1/340282366920938463463374607431768211455").unwrap(),
1088 );
1089 assert_eq!(Big8::from(large_denominator).denominator.len(), words_needed);
1090
1091 let both_large = Rational128::new_signed(Sign::Negative, u128::MAX - 2, u128::MAX).unwrap();
1092 assert_eq!(
1093 Big8::from(both_large),
1094 Big8::from_str(
1095 "-340282366920938463463374607431768211453/340282366920938463463374607431768211455",
1096 ).unwrap(),
1097 );
1098
1099 assert_eq!(Big8::from(Rational128::new_signed(Sign::Positive, u128::MAX, u128::MAX).unwrap()), RB!(1));
1101 assert_eq!(Big8::from(Rational128::new_signed(Sign::Negative, u128::MAX, u128::MAX).unwrap()), -RB!(1));
1102 }
1103
1104 #[test]
1105 fn from_tuple() {
1106 assert_eq!(Big::from((0_i32, 1_u32)), RB!(0));
1107 assert_eq!(Big::from((0_i32, 5_u32)), RB!(0));
1108 assert_eq!(Big::from((1_i64, 2_u64)), RB!(1, 2));
1109 assert_eq!(Big::from((22_i8, 2_u8)), RB!(11));
1110 assert_eq!(Big::from((-1_i16, 2_u16)), RB!(-1, 2));
1111 assert_eq!(Big::from((-1_i32, 1_i32)), RB!(-1));
1112 }
1113
1114 #[test]
1115 fn from_tuple_signed_is_normalized() {
1116 assert_eq!(Big8::from((2_i32, 4_i32)), RB!(1, 2));
1118 assert_eq!(Big8::from((-2_i32, 4_i32)), RB!(-1, 2));
1119 assert_eq!(Big8::from((2_i32, -4_i32)), RB!(-1, 2));
1120 assert_eq!(Big8::from((-2_i32, -4_i32)), RB!(1, 2));
1121 assert_eq!(Big8::from((6_i8, 4_i8)), RB!(3, 2));
1122 assert_eq!(Big8::from((100_i64, 10_i64)), RB!(10));
1123 assert_eq!(Big8::from((4_i128, 6_i128)), RB!(2, 3));
1124 assert_eq!(Big8::from((4_isize, 6_isize)), RB!(2, 3));
1125
1126 assert_eq!(Big8::from((2_i32, 4_i32)).cmp(&RB!(1, 2)), Ordering::Equal);
1128 assert_eq!(Big8::from((-2_i32, 4_i32)).cmp(&RB!(-1, 2)), Ordering::Equal);
1129
1130 for value in [(0_i32, 5_i32), (0_i32, -5_i32), (0_i32, 1_i32)] {
1132 let zero = Big8::from(value);
1133
1134 assert_eq!(zero.sign, Sign::Zero);
1135 assert!(zero.numerator.is_zero());
1136 assert!(zero.denominator.is_one());
1137 assert_eq!(zero, RB!(0));
1138 assert_eq!(zero.cmp(&RB!(0)), Ordering::Equal);
1139 }
1140 }
1141
1142 #[test]
1143 fn from_str() {
1144 assert_eq!(Big::from_str("0"), Ok(RB!(0)));
1145 assert_eq!(Big::from_str("0000000"), Ok(RB!(0)));
1146 assert_eq!(Big::from_str("0/2"), Ok(RB!(0)));
1147 assert_eq!(Big::from_str("-0/2"), Ok(RB!(0)));
1148 assert_eq!(Big::from_str("-2"), Ok(RB!(-2)));
1149 assert_eq!(Big8::from_str("-2a"), Err("Character is not a digit"));
1150 assert_eq!(Big8::from_str("-2.1"), Err("Decimal separators are not supported"));
1151 assert_eq!(Big8::from_str("-2.1/3"), Err("Decimal separators are not supported"));
1152 assert_eq!(Big::from_str("-0"), Ok(RB!(0)));
1153 assert_eq!(Big8::from_str("0/"), Err("Empty string"));
1154 assert_eq!(Big8::from_str("0/0"), Err("Zero division"));
1155 assert_eq!(Big8::from_str(""), Err("Empty string"));
1156 assert_eq!(Big::from_str("1/2"), Ok(RB!(1, 2)));
1157 assert_eq!(Big::from_str("-3/2"), Ok(RB!(-3, 2)));
1158 assert_eq!(
1159 Big8::from_str("27670116110564327425"),
1160 Ok(Big {
1161 sign: Sign::Positive,
1162 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![(1 << 63) + (1 << 0), 1]) },
1163 denominator: NonZeroUbig::one(),
1164 }),
1165 );
1166 assert_eq!(
1167 Big8::from_str("27670116110564327425/2"),
1168 Ok(Big {
1169 sign: Sign::Positive,
1170 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![(1 << 63) + (1 << 0), 1]) },
1171 denominator: NonZeroUbig::new(2).unwrap(),
1172 }),
1173 );
1174 assert_eq!(
1175 Big8::from_str("27670116110564327425/27670116110564327425"),
1176 Ok(Big {
1177 sign: Sign::Positive,
1178 numerator: Ubig::one(),
1179 denominator: NonZeroUbig::one(),
1180 }),
1181 );
1182 assert_eq!(
1183 Big8::from_str("18446744073709551616/2"),
1184 Ok(Big {
1185 sign: Sign::Positive,
1186 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![1 << 63]) },
1187 denominator: NonZeroUbig::one(),
1188 }),
1189 );
1190 assert_eq!(
1191 Big8::from_str("-36893488147419103232"),
1192 Ok(Big {
1193 sign: Sign::Negative,
1194 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![0, 2]) },
1195 denominator: NonZeroUbig::one(),
1196 }),
1197 );
1198
1199 assert_eq!(from_str_radix::<10, 8>("407030945657418069975"), Ok(smallvec![1202576035807934423, 22]));
1200 assert_eq!(from_str_radix::<10, 8>("36893488147419103232"), Ok(smallvec![0, 1 << 1]));
1201 assert_eq!(from_str_radix::<10, 8>("18889465931478580854784"), Ok(smallvec![0, 1 << 10]));
1202 assert_eq!(from_str_radix::<10, 8>("19342813113834066795298816"), Ok(smallvec![0, 1 << 20]));
1203 assert_eq!(from_str_radix::<10, 8>("1208925819614629174706176"), Ok(smallvec![0, 1 << (80 - 64)]));
1204
1205 assert_eq!(
1206 Big8::from_str("-1208925819614629174706176/10301051460877537453973547267843"),
1207 Ok(Big {
1208 sign: Sign::Negative,
1209 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![0, 1 << (80 - 64)]) },
1210 denominator: unsafe { NonZeroUbig::from_inner_unchecked(smallvec![0x6b9676a56c7c3703, 0x82047e0eae]) },
1211 }),
1212 );
1213
1214 type SV = SmallVec<[usize; 8]>;
1215
1216 let mut x = from_str_radix::<10, 8>("676230147000402641135208532975102322580080121519024130").unwrap();
1217 let expected: SV = smallvec![7877410236203542530, 0xe30d7c46c1f853f7, 1987261794136745];
1218 assert_eq!(x, expected);
1219 let mut y = from_str_radix::<10, 8>("68468465468464168545346854646").unwrap();
1220 let expected: SV = smallvec![7062882560094707446, 3711682950];
1221 assert_eq!(y, expected);
1222 unsafe { simplify_fraction_without_info(&mut x, &mut y) };
1223 let expected: SV = smallvec![13162077154956547073, 17403806869180131835, 993630897068372];
1224 assert_eq!(x, expected);
1225 let expected: SV = smallvec![3531441280047353723, 1855841475];
1226 assert_eq!(y, expected);
1227
1228 let z = Big8::from_str("676230147000402641135208532975102322580080121519024130/68468465468464168545346854646");
1229 assert_eq!(z, Ok(Big {
1230 sign: Sign::Positive,
1231 numerator: unsafe { Ubig::from_inner_unchecked(x) },
1232 denominator: unsafe { NonZeroUbig::from_inner_unchecked(y) },
1233 }));
1234
1235 assert_eq!(
1236 Big8::from_str("1190934288550035983230200000000/1219533185348999122218328290051").unwrap(),
1237 Big8::from_str("23800000000/24371529219").unwrap(),
1238 );
1239 }
1240
1241 #[test]
1242 fn test_to_str() {
1243 type SV = SmallVec<[usize; 8]>;
1244
1245 assert_eq!(Ubig::<1>::zero().to_string(), "0");
1246 assert_eq!(Ubig::<1>::one().to_string(), "1");
1247 assert_eq!(Ubig::<1>::new(2).to_string(), "2");
1248 assert_eq!(Ubig::<1>::new(3).to_string(), "3");
1249 assert_eq!(Ubig::<1>::new(10).to_string(), "10");
1250 assert_eq!(Ubig::<1>::new(11).to_string(), "11");
1251 assert_eq!(Ubig::<1>::new(101).to_string(), "101");
1252 assert_eq!(Ubig::<1>::new(123).to_string(), "123");
1253 assert_eq!(Ubig::<1>::new(usize::MAX).to_string(), "18446744073709551615");
1254 assert_eq!(unsafe { Ubig::<1>::from_inner_unchecked(smallvec![0, 1]) }.to_string(), "18446744073709551616");
1255 assert_eq!(unsafe { Ubig::<1>::from_inner_unchecked(smallvec![1, 1]) }.to_string(), "18446744073709551617");
1256
1257 for i in 1..100 {
1258 let expected = unsafe { Ubig::from_inner_unchecked(smallvec![i]) };
1259 assert_eq!(Ubig::<8>::from_str(&expected.to_string()), Ok(expected));
1260 }
1261
1262 let x: SV = smallvec![13284626917187606528, 14353657804625640860, 11366567065457835548, 501247837944];
1263 assert_eq!(
1264 unsafe { Ubig::from_inner_unchecked(x) }.to_string(),
1265 "3146383673420971972032023490593198871229613539715389096610302560000000",
1266 );
1267 let y: SV = smallvec![10945929334190035713, 13004504757950498814, 9];
1268 assert_eq!(unsafe { Ubig::from_inner_unchecked(y) }.to_string(), "3302432073363697202172148890923583722241");
1269 let y: SV = smallvec![602229295517812052, 3];
1270 assert_eq!(unsafe { Ubig::from_inner_unchecked(y) }.to_string(), "55942461516646466900");
1271 }
1272
1273 #[test]
1274 fn test_debug() {
1275 for text in [
1277 "0",
1278 "1",
1279 "-1",
1280 "2/3",
1281 "-2/3",
1282 "18446744073709551616",
1283 "-18446744073709551616",
1284 "676230147000402641135208532975102322580080121519024130",
1285 "676230147000402641135208532975102322580080121519024130/68468465468464168545346854646",
1286 ] {
1287 let value = RationalBig::from_str(text).unwrap();
1288
1289 assert_eq!(format!("{:?}", value), format!("{}", value));
1290 assert_eq!(RationalBig::from_str(&format!("{:?}", value)), Ok(value));
1291 }
1292
1293 assert_eq!(format!("{:?}", RB!(2, 3)), "2/3");
1294 assert_eq!(format!("{:?}", RB!(0)), "0");
1295 assert_eq!(format!("{:?}", RB!(-1)), "-1");
1296 }
1297
1298 #[test]
1300 fn test_to_float_large_ratio() {
1301 let (words, bits) = (1200 / BITS_PER_WORD, 1200 % BITS_PER_WORD);
1302 let mut numerator: SmallVec<[usize; 8]> = smallvec![0; words as usize];
1303 numerator.push(1 << bits);
1304 let mut denominator = numerator.clone();
1305 denominator[0] |= 1;
1306
1307 let value = Big8 {
1309 sign: Sign::Positive,
1310 numerator: unsafe { Ubig::from_inner_unchecked(numerator) },
1311 denominator: unsafe { NonZeroUbig::from_inner_unchecked(denominator) },
1312 };
1313
1314 assert_eq!(value.to_f64(), Some(1_f64));
1315 assert_eq!(value.to_f32(), Some(1_f32));
1316 assert_eq!((-value.clone()).to_f64(), Some(-1_f64));
1317 }
1318
1319 #[test]
1321 fn test_to_primitive_most_negative() {
1322 assert_eq!(Big8::from_str("-128").unwrap().to_i8(), Some(i8::MIN));
1323 assert_eq!(Big8::from_str("-32768").unwrap().to_i16(), Some(i16::MIN));
1324 assert_eq!(Big8::from_str("-2147483648").unwrap().to_i32(), Some(i32::MIN));
1325 assert_eq!(Big8::from_str("-9223372036854775808").unwrap().to_i64(), Some(i64::MIN));
1326 assert_eq!(
1327 Big8::from_str("-170141183460469231731687303715884105728").unwrap().to_i128(),
1328 Some(i128::MIN),
1329 );
1330 assert_eq!(
1331 Big8::from_str(&isize::MIN.to_string()).unwrap().to_isize(),
1332 Some(isize::MIN),
1333 );
1334
1335 assert_eq!(Big8::from_str("-129").unwrap().to_i8(), None);
1337 assert_eq!(Big8::from_str("-9223372036854775809").unwrap().to_i64(), None);
1338
1339 assert_eq!(Big8::from_str("128").unwrap().to_i8(), None);
1341 assert_eq!(Big8::from_str("9223372036854775808").unwrap().to_i64(), None);
1342 }
1343
1344 #[test]
1345 fn test_to_primitive_128() {
1346 assert_eq!(RB!(0).to_u128(), Some(0));
1347 assert_eq!(RB!(0).to_i128(), Some(0));
1348 assert_eq!(RB!(1).to_u128(), Some(1));
1349 assert_eq!(RB!(-1).to_i128(), Some(-1));
1350 assert_eq!(RB!(-1).to_u128(), None);
1351 assert_eq!(RB!(1, 2).to_u128(), Some(0));
1352 assert_eq!(RB!(-3, 2).to_i128(), Some(-1));
1353
1354 let large = Rational128::new_signed(Sign::Positive, u128::MAX, 1).unwrap();
1356 assert_eq!(Big8::from(large).to_u128(), Some(u128::MAX));
1357 assert_eq!(Big8::from(large).to_i128(), None);
1358
1359 let large = Rational128::new_signed(Sign::Positive, i128::MAX as u128, 1).unwrap();
1360 assert_eq!(Big8::from(large).to_i128(), Some(i128::MAX));
1361
1362 let too_large = Big8::from_str("340282366920938463463374607431768211456").unwrap();
1364 assert_eq!(too_large.to_u128(), None);
1365 assert_eq!(too_large.to_i128(), None);
1366 }
1367
1368 #[test]
1370 fn test_from_str_not_ascii() {
1371 assert_eq!(Big8::from_str("\u{e9}"), Err("Character is not a digit"));
1372 assert_eq!(Big8::from_str("-\u{e9}"), Err("Character is not a digit"));
1373 assert_eq!(Big8::from_str("\u{e9}/2"), Err("Character is not a digit"));
1374 assert_eq!(Big8::from_str("1/\u{e9}"), Err("Character is not a digit"));
1375 assert_eq!(Big8::from_str("\u{1f600}"), Err("Character is not a digit"));
1376 }
1377
1378 #[test]
1380 fn test_from_str_no_digits() {
1381 for text in ["", " ", "\t\n", "-", "+", "/", "-/", " 1", "1 ", "1 / 2", "- 1"] {
1382 assert!(Big8::from_str(text).is_err(), "parsed {:?}", text);
1383 }
1384
1385 assert_eq!(Big8::from_str("0"), Ok(RB!(0)));
1387 assert_eq!(Big8::from_str("0000"), Ok(RB!(0)));
1388 assert_eq!(Big8::from_str("-0000"), Ok(RB!(0)));
1389 }
1390
1391 #[test]
1392 fn test_to_primitive() {
1393 assert_eq!(RB!(1, 2).to_u64(), Some(0));
1394 assert_eq!(RB!(1, 1).to_u64(), Some(1));
1395 assert_eq!(RB!(2, 1).to_u64(), Some(2));
1396 assert_eq!(RB!(-1, 2).to_u64(), None);
1397 assert_eq!(RB!(1, 2).to_i8(), Some(0));
1398 assert_eq!(RB!(1, 1).to_i8(), Some(1));
1399 assert_eq!(RB!(2, 1).to_i8(), Some(2));
1400 assert_eq!(RB!(-1, 2).to_i8(), Some(0));
1401 assert_eq!(RB!(-1, 1).to_i8(), Some(-1));
1402
1403 assert_eq!(RB!(1, 2).to_f32(), Some(0.5_f32));
1404 assert_eq!(RB!(1, 2).to_f64(), Some(0.5_f64));
1405 assert_eq!(RB!(-1, 2).to_f64(), Some(-0.5_f64));
1406 assert_eq!(RB!(123456789, 1).to_f64(), Some(123456789_f64));
1407 assert_eq!(RB!(9_007_199_254_740_992, 1).to_f64(), Some(9_007_199_254_740_992_f64));
1408 assert_eq!(RB!(9_007_199_254_740_993, 1).to_f64(), Some(9_007_199_254_740_993_f64));
1409 assert_eq!(RB!(9_007_199_254_740_994, 1).to_f64(), Some(9_007_199_254_740_994_f64));
1410 }
1411}