1#![allow(unused_unsafe)]
2
3use core::mem;
4use std::cmp::Ordering;
5use std::convert::TryFrom;
6use std::convert::TryInto;
7use std::fmt;
8use std::num::{NonZeroU128, NonZeroUsize};
9use std::str::FromStr;
10
11use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
12use smallvec::SmallVec;
13use smallvec::smallvec;
14
15use crate::integer::big::{BITS_PER_WORD, NonZeroUbig, Ubig};
16use crate::integer::big::ops::building_blocks::is_well_formed;
17use crate::integer::big::ops::non_zero::{add_assign_single_non_zero, mul_assign_single_non_zero, shl_mut, shr_mut};
18use crate::rational::{f32_kind, f64_kind};
19use crate::rational::big::io::FloatKind;
20
21impl<const S: usize> Ubig<S> {
22 #[must_use]
24 #[inline]
25 pub fn new(value: usize) -> Self {
26 Ubig(if value > 0 { smallvec![value] } else { smallvec![] })
27 }
28 #[must_use]
32 #[inline]
33 pub fn new_u128(value: u128) -> Self {
34 Ubig(u128_words(value))
35 }
36 #[must_use]
37 #[inline]
38 pub(crate) unsafe fn from_inner_unchecked(values: SmallVec<[usize; S]>) -> Self {
39 debug_assert!(is_well_formed(&values));
40
41 Self(values)
42 }
43}
44
45impl<const S: usize> NonZeroUbig<S> {
46 #[must_use]
50 pub fn new(n: usize) -> Option<Self> {
51 if n != 0 {
52 Some(unsafe { Self(smallvec![n]) })
53 } else {
54 None
55 }
56 }
57 #[must_use]
62 pub fn new_u128(n: u128) -> Option<Self> {
63 if n != 0 {
64 Some(Self(u128_words(n)))
65 } else {
66 None
67 }
68 }
69 #[must_use]
70 #[inline]
71 pub(crate) unsafe fn new_unchecked(value: usize) -> Self {
72 NonZeroUbig(smallvec![value])
73 }
74 #[must_use]
78 #[inline]
79 pub(crate) unsafe fn new_u128_unchecked(value: u128) -> Self {
80 debug_assert_ne!(value, 0);
81
82 NonZeroUbig(u128_words(value))
83 }
84 #[must_use]
85 #[inline]
86 pub(crate) unsafe fn from_inner_unchecked(values: SmallVec<[usize; S]>) -> Self {
87 debug_assert!(is_well_formed(&values));
88
89 Self(values)
90 }
91}
92
93impl<const S: usize> Default for Ubig<S> {
94 fn default() -> Self {
95 Self::zero()
96 }
97}
98
99impl<const S: usize> From<NonZeroUsize> for Ubig<S> {
100 fn from(value: NonZeroUsize) -> Self {
101 Self(smallvec![value.get()])
102 }
103}
104
105impl<const S: usize> From<NonZeroUsize> for NonZeroUbig<S> {
106 fn from(value: NonZeroUsize) -> Self {
107 Self(smallvec![value.get()])
108 }
109}
110
111impl<const S: usize> From<NonZeroU128> for Ubig<S> {
112 fn from(value: NonZeroU128) -> Self {
113 Self(u128_words(value.get()))
114 }
115}
116
117impl<const S: usize> From<NonZeroU128> for NonZeroUbig<S> {
118 fn from(value: NonZeroU128) -> Self {
119 Self(u128_words(value.get()))
120 }
121}
122
123impl<const S: usize, const I: usize> TryFrom<[usize; I]> for Ubig<S> {
124 type Error = ();
126
127 fn try_from(value: [usize; I]) -> Result<Self, Self::Error> {
128 if is_well_formed(&value) {
129 Ok(Self(SmallVec::from_slice(&value)))
130 } else {
131 Err(())
132 }
133 }
134}
135
136impl<const S: usize, const I: usize> TryFrom<[usize; I]> for NonZeroUbig<S> {
137 type Error = ();
139
140 fn try_from(value: [usize; I]) -> Result<Self, Self::Error> {
141 if is_well_formed(&value) && !value.is_empty() {
142 Ok(Self(SmallVec::from_slice(&value)))
143 } else {
144 Err(())
145 }
146 }
147}
148
149impl<const S: usize> Zero for Ubig<S> {
150 #[inline]
151 fn zero() -> Self {
152 Self(smallvec![])
153 }
154
155 #[inline]
156 fn set_zero(&mut self) {
157 self.0.clear();
158 }
159
160 #[inline]
161 fn is_zero(&self) -> bool {
162 self.0.is_empty()
163 }
164}
165
166impl<const S: usize> One for Ubig<S> {
167 #[inline]
168 fn one() -> Self {
169 Self(smallvec![1])
170 }
171
172 #[inline]
173 fn set_one(&mut self) {
174 self.0.clear();
175 self.0.push(1);
176 }
177
178 #[inline]
179 fn is_one(&self) -> bool {
180 self.0.len() == 1 && self.0[0] == 1
181 }
182}
183
184impl<const S: usize> One for NonZeroUbig<S> {
185 #[inline]
186 fn one() -> Self {
187 Self(smallvec![1])
188 }
189
190 #[inline]
191 fn set_one(&mut self) {
192 self.0.truncate(1);
193 *unsafe { self.0.get_unchecked_mut(0) } = 1;
194 }
195
196 #[inline]
197 fn is_one(&self) -> bool {
198 *unsafe { self.0.get_unchecked(0) } == 1 && self.0.len() == 1
199 }
200}
201
202
203impl<const S: usize> From<usize> for Ubig<S> {
204 fn from(value: usize) -> Self {
205 Self(if value > 0 { smallvec![value] } else { smallvec![] })
206 }
207}
208
209impl<const S: usize> From<u128> for Ubig<S> {
210 fn from(value: u128) -> Self {
211 Self::new_u128(value)
212 }
213}
214
215#[must_use]
225#[inline]
226fn u128_words<const S: usize>(value: u128) -> SmallVec<[usize; S]> {
227 let word_count = (mem::size_of::<u128>() / mem::size_of::<usize>()).max(1) as u32;
229
230 let mut words = (0..word_count)
231 .map(|index| (value >> (index * BITS_PER_WORD)) as usize)
232 .collect::<SmallVec<[usize; S]>>();
233
234 while let Some(&0) = words.last() {
235 words.pop();
236 }
237
238 debug_assert!(is_well_formed(&words));
239
240 words
241}
242
243impl<const S: usize> FromStr for Ubig<S> {
244 type Err = &'static str;
246
247 fn from_str(s: &str) -> Result<Self, Self::Err> {
248 from_str_radix::<10, S>(s).map(Self)
249 }
250}
251
252impl<const S: usize> FromStr for NonZeroUbig<S> {
253 type Err = &'static str;
255
256 fn from_str(s: &str) -> Result<Self, Self::Err> {
257 from_str_radix::<10, S>(s)
258 .and_then(|inner| {
259 if !inner.is_empty() {
260 Ok(unsafe { Self(inner) })
261 } else {
262 Err("Zero value")
263 }
264 })
265 }
266}
267
268impl<const S: usize> fmt::Display for Ubig<S> {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 f.write_str(&to_str_radix::<10>(self))
271 }
272}
273
274impl<const S: usize> fmt::Display for NonZeroUbig<S> {
275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
276 f.write_str(&to_str_radix::<10>(self))
278 }
279}
280
281#[inline]
282pub fn from_str_radix<const RADIX: u32, const S: usize>(s: &str) -> Result<SmallVec<[usize; S]>, &'static str> {
283 debug_assert!(RADIX <= 36);
284
285 match s.len() {
286 0 => Err("Empty string"),
287 _ => {
288 let mut char_iterator = s
291 .chars()
292 .skip_while(|&c| c == '0');
293 match char_iterator.next() {
294 None => Ok(smallvec![]),
295 Some(value) => {
296 match value.to_digit(RADIX) {
297 None => Err("Character is not a digit"),
298 Some(value) => {
299 let mut non_zero_total = unsafe { smallvec![value as usize] };
300
301 for character in char_iterator {
302 match character.to_digit(RADIX) {
303 None => return Err("Character is not a digit"),
304 Some(value) => {
305 mul_assign_single_non_zero(&mut non_zero_total, RADIX as usize);
306 add_assign_single_non_zero(&mut non_zero_total, value as usize);
307 }
308 }
309 }
310
311 Ok(non_zero_total)
312 }
313 }
314 }
315 }
316 }
317 }
318}
319
320fn to_str_radix<const RADIX: u32>(value: &[usize]) -> String {
321 assert!(RADIX > 1 && RADIX <= 36);
322
323 match value.len() {
324 0 => "0".to_string(),
325 _ => {
326 let mut digits = vec![0];
327
328 let mut leading_zero_words = 0;
330 while value[leading_zero_words] == 0 {
331 leading_zero_words += 1;
333 }
334 let leading_zero_bits = value.last().unwrap().leading_zeros();
335
336 let mut value = value.iter()
338 .skip(leading_zero_words)
339 .map(|word| word.reverse_bits())
340 .rev()
341 .collect::<SmallVec<[usize; 8]>>();
342 let len_before_shift = value.len() as u32;
343 shr_mut(&mut value, 0, leading_zero_bits);
344
345 let bit_count = len_before_shift * BITS_PER_WORD - leading_zero_bits;
346 debug_assert_eq!(value[0] % 2, 1);
347 for bit_index in 0..bit_count {
348 update_digits::<RADIX>(&mut digits, value[0] % 2 == 1);
349 shr_mut(&mut value, 0, 1);
350
351 if value.is_empty() {
352 for _ in (bit_index + 1)..(leading_zero_words as u32 * BITS_PER_WORD + bit_count) {
354 update_digits::<RADIX>(&mut digits, false);
355 }
356 break;
357 }
358 }
359
360 digits.into_iter()
361 .rev()
362 .map(|digit| {
363 if digit < 10 {
364 digit.to_string()
365 } else {
366 ASCII_LOWER[(digit - 10) as usize].to_string()
367 }
368 })
369 .collect()
370 }
371 }
372}
373
374static ASCII_LOWER: [char; 26] = [
375 'a', 'b', 'c', 'd', 'e',
376 'f', 'g', 'h', 'i', 'j',
377 'k', 'l', 'm', 'n', 'o',
378 'p', 'q', 'r', 's', 't',
379 'u', 'v', 'w', 'x', 'y',
380 'z',
381];
382
383fn update_digits<const RADIX: u32>(digits: &mut Vec<u32>, mut carry: bool) {
384 for digit in digits.iter_mut() {
385 *digit *= 2; if carry {
387 *digit += 1;
388 carry = false;
389 }
390 if *digit >= RADIX {
391 *digit %= RADIX;
392 carry = true;
393 }
394 }
395 if carry {
396 digits.push(1);
397 }
398}
399
400impl<const S: usize> FromPrimitive for Ubig<S> {
401 fn from_isize(n: isize) -> Option<Self> {
402 if n >= 0 {
403 Some(Self::new(n.unsigned_abs()))
404 } else {
405 None
406 }
407 }
408
409 fn from_i8(n: i8) -> Option<Self> {
410 if n >= 0 {
411 Some(Self::new(n.unsigned_abs() as usize))
412 } else {
413 None
414 }
415 }
416
417 fn from_i16(n: i16) -> Option<Self> {
418 if n >= 0 {
419 Some(Self::new(n.unsigned_abs() as usize))
420 } else {
421 None
422 }
423 }
424
425 fn from_i32(n: i32) -> Option<Self> {
426 if n >= 0 {
427 Some(Self::new(n.unsigned_abs() as usize))
428 } else {
429 None
430 }
431 }
432
433 fn from_i64(n: i64) -> Option<Self> {
434 if n >= 0 {
435 Some(Self::new(n.unsigned_abs() as usize))
436 } else {
437 None
438 }
439 }
440
441 fn from_i128(n: i128) -> Option<Self> {
442 if n >= 0 {
443 Self::from_u128(n.unsigned_abs())
444 } else {
445 None
446 }
447 }
448
449 fn from_usize(n: usize) -> Option<Self> {
450 Some(Self::new(n))
451 }
452
453 fn from_u8(n: u8) -> Option<Self> {
454 Some(Self::new(n as usize))
455 }
456
457 fn from_u16(n: u16) -> Option<Self> {
458 Some(Self::new(n as usize))
459 }
460
461 fn from_u32(n: u32) -> Option<Self> {
462 Some(Self::new(n as usize))
463 }
464
465 fn from_u64(n: u64) -> Option<Self> {
466 Some(Self::new(n as usize))
467 }
468
469 fn from_u128(n: u128) -> Option<Self> {
470 Some(Self::new_u128(n))
471 }
472
473 fn from_f32(n: f32) -> Option<Self> {
474 Self::from_float_kind(f32_kind(n))
475 }
476
477 fn from_f64(n: f64) -> Option<Self> {
478 Self::from_float_kind(f64_kind(n))
479 }
480}
481
482impl<const S: usize> Ubig<S> {
483 fn from_float_kind(kind: FloatKind) -> Option<Self> {
484 match kind {
485 FloatKind::Subnormal(as_ratio) | FloatKind::Normal(as_ratio) => {
486 if as_ratio.sign == 0 {
487 let result = match as_ratio.exponent.cmp(&0) {
488 Ordering::Less => {
489 let shift = as_ratio.exponent.unsigned_abs();
494 let result = as_ratio.fraction.get().unbounded_shr(shift);
495
496 Self::new_u128(result as u128)
497 }
498 Ordering::Equal => Self::new_u128(as_ratio.fraction.get() as u128),
499 Ordering::Greater => {
500 let shift = as_ratio.exponent.unsigned_abs();
502 let (words, bits) = (shift / BITS_PER_WORD, shift % BITS_PER_WORD);
503
504 let mut values = u128_words::<S>(as_ratio.fraction.get() as u128);
506 shl_mut(&mut values, words as usize, bits);
507
508 unsafe {
509 Self::from_inner_unchecked(values)
512 }
513 }
514 };
515
516 Some(result)
517 } else {
518 None
519 }
520 },
521 FloatKind::Zero => Some(Self::zero()),
522 _ => None,
523 }
524 }
525}
526
527
528macro_rules! small {
529 ($value:expr) => {
530 {
531 match $value.len() {
532 0 => Some(0),
533 1 => $value[0].try_into().ok(),
534 _ => None,
535 }
536 }
537 }
538}
539
540#[must_use]
542#[inline]
543pub(crate) fn bit_length(words: &[usize]) -> u32 {
544 debug_assert!(is_well_formed(words));
545
546 match words.last() {
547 None => 0,
548 Some(&last) => (words.len() as u32 - 1) * BITS_PER_WORD + last.bit_width(),
549 }
550}
551
552#[must_use]
559pub(crate) fn highest_word(words: &[usize]) -> (usize, u32) {
560 debug_assert!(!words.is_empty());
561
562 let shift = bit_length(words).saturating_sub(BITS_PER_WORD);
563 let (word_shift, bit_shift) = ((shift / BITS_PER_WORD) as usize, shift % BITS_PER_WORD);
564 debug_assert!(word_shift < words.len());
565
566 let low = words[word_shift] >> bit_shift;
567 let high = match words.get(word_shift + 1) {
570 Some(&word) => word.unbounded_shl(BITS_PER_WORD - bit_shift),
571 None => 0,
572 };
573
574 (low | high, shift)
575}
576
577#[must_use]
583#[inline]
584pub(crate) fn words_to_u128(words: &[usize]) -> Option<u128> {
585 let word_count = (mem::size_of::<u128>() / mem::size_of::<usize>()).max(1);
587
588 if words.len() > word_count {
589 return None;
590 }
591
592 let mut total = 0_u128;
593 for (index, &word) in words.iter().enumerate() {
594 total |= (word as u128) << (index as u32 * BITS_PER_WORD);
595 }
596
597 Some(total)
598}
599
600macro_rules! to_primitive_impl {
601 ($name:ty) => {
602 impl<const S: usize> ToPrimitive for $name {
603 fn to_isize(&self) -> Option<isize> {
604 small!(self)
605 }
606
607 fn to_i8(&self) -> Option<i8> {
608 small!(self)
609 }
610
611 fn to_i16(&self) -> Option<i16> {
612 small!(self)
613 }
614
615 fn to_i32(&self) -> Option<i32> {
616 small!(self)
617 }
618
619 fn to_i64(&self) -> Option<i64> {
620 small!(self)
621 }
622
623 fn to_i128(&self) -> Option<i128> {
624 words_to_u128(self).and_then(|value| i128::try_from(value).ok())
625 }
626
627 fn to_usize(&self) -> Option<usize> {
628 small!(self)
629 }
630
631 fn to_u8(&self) -> Option<u8> {
632 small!(self)
633 }
634
635 fn to_u16(&self) -> Option<u16> {
636 small!(self)
637 }
638
639 fn to_u32(&self) -> Option<u32> {
640 small!(self)
641 }
642
643 fn to_u64(&self) -> Option<u64> {
644 small!(self)
645 }
646
647 fn to_u128(&self) -> Option<u128> {
648 words_to_u128(self)
649 }
650
651 fn to_f32(&self) -> Option<f32> {
652 Some(make_float_32::<S>(self))
653 }
654
655 fn to_f64(&self) -> Option<f64> {
656 Some(make_float_64::<S>(self))
657 }
658 }
659 }
660}
661
662to_primitive_impl!(Ubig<S>);
663to_primitive_impl!(NonZeroUbig<S>);
664
665macro_rules! define_float_maker {
666 ($name:ident, $target:ty, $bit_array:ty, $bits_in_exponent:expr, $bits_in_fraction:expr) => {
667 fn $name<const S: usize>(values: &[usize]) -> $target {
668 let sign = 0;
669
670 match values.last() {
671 None => <$target>::zero(),
672 Some(last_value) => {
673 debug_assert_ne!(*last_value, 0);
674 let bits_in_highest = last_value.bit_width();
675 debug_assert!(bits_in_highest > 0);
676 let bits = (values.len() - 1) as u32 * BITS_PER_WORD + bits_in_highest;
677 debug_assert!(bits > 0);
678
679 let biased_exponent = bits as $bit_array + ((2 as $bit_array).pow($bits_in_exponent - 1) - 1 - 1);
680 if biased_exponent >= ((1 as $bit_array) << $bits_in_exponent) - 1 {
681 return <$target>::INFINITY;
684 }
685 let exponent = biased_exponent << $bits_in_fraction;
686
687 let mut copy = SmallVec::<[usize; S]>::from_slice(values);
688 *copy.last_mut().unwrap() -= last_value.isolate_highest_one();
691
692 let remaining_bits = bits - 1;
693 let fraction = match remaining_bits.cmp(&$bits_in_fraction) {
694 Ordering::Less => copy[0] << ($bits_in_fraction - remaining_bits),
695 Ordering::Equal => copy[0],
696 Ordering::Greater => {
697 let to_shift = remaining_bits - $bits_in_fraction;
698 let (highest_bit_lost_set, any_other_set) = {
699 let index = to_shift - 1;
700
701 let (words, bits) = ((index / BITS_PER_WORD) as usize, index % BITS_PER_WORD);
702 let highest_bit_lost = copy[words] & (1 << bits) > 0;
703
704 let mask = usize::MAX.unbounded_shr(BITS_PER_WORD - bits);
707 let any_other = copy[..words].iter().any(|&w| w != 0)
708 || mask & copy[words] > 0;
709
710 (highest_bit_lost, any_other)
711 };
712
713 let (words, bits) = (to_shift / BITS_PER_WORD, to_shift % BITS_PER_WORD);
714
715 let unrounded = 'scope: {
716 while let Some(&0) = copy.last() {
721 copy.pop();
722 }
723
724 if words as usize >= copy.len() {
725 break 'scope 0;
728 }
729
730 shr_mut(&mut copy, words as usize, bits);
731
732 match copy.last() {
733 Some(&value) => value,
734 None => 0,
735 }
736 };
737
738 if highest_bit_lost_set {
739 if any_other_set {
740 unrounded + 1
741 } else {
742 if unrounded % 2 == 1 {
744 unrounded + 1
745 } else {
746 unrounded
747 }
748 }
749 } else {
750 unrounded
751 }
752 },
753 };
754
755 <$target>::from_bits(sign | (exponent + fraction as $bit_array))
762 }
763 }
764 }
765 }
766}
767
768define_float_maker!(make_float_32, f32, u32, 8, 23);
769define_float_maker!(make_float_64, f64, u64, 11, 52);
770
771#[cfg(test)]
772mod test {
773 use std::num::NonZeroU128;
774 use std::str::FromStr;
775
776 use num_traits::FromPrimitive;
777 use num_traits::One;
778 use num_traits::ToPrimitive;
779 use num_traits::Zero;
780 use smallvec::{smallvec, SmallVec};
781
782 use crate::integer::big::{BITS_PER_WORD, NonZeroUbig};
783 use crate::Ubig;
784
785 fn power_of_two<const S: usize>(power: u32) -> Ubig<S> {
787 let (words, bits) = (power / BITS_PER_WORD, power % BITS_PER_WORD);
788
789 let mut values: SmallVec<[usize; S]> = smallvec![0; words as usize];
790 values.push(1 << bits);
791
792 unsafe {
793 Ubig::from_inner_unchecked(values)
795 }
796 }
797
798 fn power_of_two_plus_one<const S: usize>(power: u32) -> Ubig<S> {
800 debug_assert!(power >= BITS_PER_WORD);
801
802 let mut value = power_of_two::<S>(power);
803 unsafe {
804 value.inner_mut()[0] |= 1;
807 }
808
809 value
810 }
811
812 const U128_CASES: [u128; 8] = [
814 0,
815 1,
816 19,
817 usize::MAX as u128,
818 usize::MAX as u128 + 1,
819 (usize::MAX as u128 + 1) * 3,
820 i128::MAX as u128,
821 u128::MAX,
822 ];
823
824 #[test]
825 fn test_from_u128() {
826 assert_eq!(Ubig::<8>::new_u128(0), Ubig::zero());
827 assert_eq!(Ubig::<8>::new_u128(1), Ubig::one());
828 assert_eq!(Ubig::<8>::new_u128(19), Ubig::new(19));
829 assert_eq!(Ubig::<8>::new_u128(usize::MAX as u128), Ubig::new(usize::MAX));
830
831 for value in U128_CASES {
833 assert_eq!(Ubig::<8>::new_u128(value).to_string(), value.to_string());
834 assert_eq!(Ubig::<8>::from_str(&value.to_string()), Ok(Ubig::new_u128(value)));
835
836 assert_eq!(Ubig::<8>::from(value), Ubig::new_u128(value));
838 }
839 }
840
841 #[test]
842 fn test_from_u128_is_normalized() {
843 assert!(Ubig::<8>::new_u128(0).inner().is_empty());
845 for value in U128_CASES {
846 assert!(unsafe { Ubig::<8>::new_u128(value).is_well_formed() });
847 assert_eq!(Ubig::<8>::new_u128(value).is_zero(), value == 0);
848 }
849 }
850
851 #[test]
852 fn test_non_zero_from_u128() {
853 assert_eq!(NonZeroUbig::<8>::new_u128(0), None);
854 assert_eq!(NonZeroUbig::<8>::new_u128(1), Some(NonZeroUbig::one()));
855
856 for value in U128_CASES.into_iter().filter(|&value| value != 0) {
857 let expected = NonZeroUbig::<8>::from_str(&value.to_string()).unwrap();
858
859 assert_eq!(NonZeroUbig::<8>::new_u128(value), Some(expected.clone()));
860 assert_eq!(unsafe { NonZeroUbig::<8>::new_u128_unchecked(value) }, expected);
861 assert!(unsafe { expected.is_well_formed() });
862
863 let non_zero = NonZeroU128::new(value).unwrap();
864 assert_eq!(NonZeroUbig::<8>::from(non_zero), expected);
865 assert_eq!(Ubig::<8>::from(non_zero), Ubig::new_u128(value));
866 }
867 }
868
869 #[test]
870 fn test_from_primitive() {
871 assert_eq!(Ubig::<1>::from_i16(-4), None);
872 assert_eq!(Ubig::<1>::from_u16(4), Some(Ubig::from(4_usize)));
873 assert_eq!(Ubig::<1>::from_i128(0), Some(Ubig::from(0_usize)));
874 assert_eq!(Ubig::<1>::from_i128(1), Some(Ubig::from(1_usize)));
875 assert_eq!(Ubig::<1>::from_i128(-1), None);
876
877 assert_eq!(Ubig::<1>::from_f32(1.5_f32), Some(Ubig::from(1_usize)));
878 assert_eq!(Ubig::<1>::from_f32(1_f32), Some(Ubig::from(1_usize)));
879 assert_eq!(Ubig::<1>::from_f32(0.5_f32), Some(Ubig::from(0_usize)));
880 assert_eq!(Ubig::<1>::from_f32(0.75_f32), Some(Ubig::from(0_usize)));
881 assert_eq!(Ubig::<1>::from_f32(0_f32), Some(Ubig::from(0_usize)));
882
883 assert_eq!(Ubig::<1>::from_f32(-1.5_f32), None);
884 assert_eq!(Ubig::<1>::from_f32(-0_f32), Some(Ubig::from(0_usize)));
885 }
886
887 #[test]
888 fn test_from_primitive_large() {
889 for value in U128_CASES {
890 assert_eq!(Ubig::<8>::from_u128(value), Some(Ubig::new_u128(value)));
891 }
892
893 assert_eq!(Ubig::<8>::from_i128(i128::MAX), Some(Ubig::new_u128(i128::MAX as u128)));
894 assert_eq!(Ubig::<8>::from_i128(i128::MIN), None);
895 assert_eq!(Ubig::<8>::from_u128(u128::MAX).unwrap().to_string(), u128::MAX.to_string());
896 }
897
898 #[test]
900 fn test_from_float_with_positive_exponent() {
901 for value in [
903 1e16_f64,
904 9007199254740992_f64,
905 1.8446744073709552e19,
906 2_f64.powi(64),
907 2_f64.powi(100),
908 2_f64.powi(1000),
909 1e300,
910 ] {
911 let expected = Ubig::<8>::from_str(&format!("{:.0}", value)).unwrap();
912 assert_eq!(Ubig::<8>::from_f64(value), Some(expected), "value {}", value);
913 }
914
915 for value in [1e30_f32, 2_f32.powi(64), 2_f32.powi(100), f32::MAX] {
916 let expected = Ubig::<8>::from_str(&format!("{:.0}", value)).unwrap();
917 assert_eq!(Ubig::<8>::from_f32(value), Some(expected), "value {}", value);
918 }
919 }
920
921 #[test]
923 fn test_from_float_with_large_negative_exponent() {
924 assert_eq!(Ubig::<8>::from_f64(f64::MIN_POSITIVE), Some(Ubig::zero()));
926 assert_eq!(Ubig::<8>::from_f64(f64::from_bits(1)), Some(Ubig::zero()));
927 assert_eq!(Ubig::<8>::from_f64(1e-300), Some(Ubig::zero()));
928 assert_eq!(Ubig::<8>::from_f32(1e-30_f32), Some(Ubig::zero()));
929 assert_eq!(Ubig::<8>::from_f32(f32::MIN_POSITIVE), Some(Ubig::zero()));
930 assert_eq!(Ubig::<8>::from_f32(f32::from_bits(1)), Some(Ubig::zero()));
931 }
932
933 #[test]
936 fn test_to_float_powers_of_two() {
937 for power in [0_u32, 1, 52, 53, 62, 63, 64, 65, 66, 100, 127, 128, 200, 1000] {
938 let value = power_of_two::<8>(power);
939 assert_eq!(value.to_f64(), Some(2_f64.powi(power as i32)), "2 ** {}", power);
940 }
941
942 for power in [0_u32, 1, 22, 23, 30, 31, 32, 33, 63, 64, 65, 100, 127] {
943 let value = power_of_two::<8>(power);
944 assert_eq!(value.to_f32(), Some(2_f32.powi(power as i32)), "2 ** {}", power);
945 }
946 }
947
948 #[test]
949 fn test_to_float_one_above_power_of_two() {
950 for power in [64_u32, 65, 66, 100, 127, 128, 200] {
951 let value = power_of_two_plus_one::<8>(power);
952 assert_eq!(value.to_f64(), Some(2_f64.powi(power as i32)), "2 ** {} + 1", power);
953 }
954
955 for power in [64_u32, 65, 100, 127] {
956 let value = power_of_two_plus_one::<8>(power);
957 assert_eq!(value.to_f32(), Some(2_f32.powi(power as i32)), "2 ** {} + 1", power);
958 }
959 }
960
961 #[test]
963 fn test_to_float_overflow_is_infinite() {
964 for power in [128_u32, 129, 140, 300, 1000] {
966 for value in [power_of_two::<8>(power), power_of_two_plus_one::<8>(power)] {
967 let result = value.to_f32().unwrap();
968
969 assert_eq!(result, f32::INFINITY, "2 ** {}", power);
970 assert!(result.is_sign_positive(), "2 ** {}", power);
971 }
972 }
973
974 for power in [1024_u32, 1025, 2000] {
976 for value in [power_of_two::<8>(power), power_of_two_plus_one::<8>(power)] {
977 let result = value.to_f64().unwrap();
978
979 assert_eq!(result, f64::INFINITY, "2 ** {}", power);
980 assert!(result.is_sign_positive(), "2 ** {}", power);
981 }
982 }
983
984 assert_eq!(power_of_two::<8>(127).to_f32(), Some(2_f32.powi(127)));
986 assert_eq!(power_of_two::<8>(1023).to_f64(), Some(2_f64.powi(1023)));
987 }
988
989 #[test]
996 fn test_to_float_mantissa_carry() {
997 assert_eq!(Ubig::<8>::from((1_u128 << 55) - 1).to_f64(), Some(2_f64.powi(55)));
998 assert_eq!(Ubig::<8>::from((1_u128 << 25) - 1).to_f32(), Some(2_f32.powi(25)));
999
1000 for power in 2_u32..=127 {
1001 for difference in 1..=64_u128.min((1_u128 << power) - 1) {
1003 let value = (1_u128 << power) - difference;
1004 let big = Ubig::<8>::from(value);
1005
1006 assert_eq!(big.to_f64(), Some(value as f64), "2 ** {power} - {difference}");
1007 assert_eq!(big.to_f32(), Some(value as f32), "2 ** {power} - {difference}");
1008 }
1009 }
1010 }
1011
1012 #[test]
1013 fn test_to_primitive_128() {
1014 for value in U128_CASES {
1015 assert_eq!(Ubig::<8>::new_u128(value).to_u128(), Some(value));
1016 }
1017
1018 assert_eq!(Ubig::<8>::zero().to_i128(), Some(0));
1019 assert_eq!(Ubig::<8>::new_u128(i128::MAX as u128).to_i128(), Some(i128::MAX));
1020 assert_eq!(Ubig::<8>::new_u128(i128::MAX as u128 + 1).to_i128(), None);
1021 assert_eq!(Ubig::<8>::new_u128(u128::MAX).to_i128(), None);
1022
1023 assert_eq!(NonZeroUbig::<8>::new_u128(u128::MAX).unwrap().to_u128(), Some(u128::MAX));
1024 assert_eq!(NonZeroUbig::<8>::one().to_i128(), Some(1));
1025
1026 let too_large = Ubig::<8>::from_str("340282366920938463463374607431768211456").unwrap();
1028 assert_eq!(too_large.to_u128(), None);
1029 assert_eq!(too_large.to_i128(), None);
1030 }
1031
1032 #[test]
1033 fn test_to_primitive() {
1034 assert_eq!(Ubig::<1>::from(4_usize).to_i16(), Some(4));
1035
1036 assert_eq!(Ubig::<1>::from(0_usize).to_f32(), Some(0_f32));
1037 assert_eq!(Ubig::<1>::from(1_usize).to_f32(), Some(1_f32));
1038 assert_eq!(Ubig::<1>::from(2_usize).to_f32(), Some(2_f32));
1039 assert_eq!(Ubig::<1>::from(3_usize).to_f32(), Some(3_f32));
1040 assert_eq!(Ubig::<1>::from(4_usize).to_f32(), Some(4_f32));
1041 assert_eq!(Ubig::<1>::from(5_usize).to_f32(), Some(5_f32));
1042 assert_eq!(Ubig::<1>::from(6_usize).to_f32(), Some(6_f32));
1043 assert_eq!(Ubig::<1>::from(7_usize).to_f32(), Some(7_f32));
1044
1045 assert_eq!(Ubig::<1>::from(0_usize).to_f64(), Some(0_f64));
1046 assert_eq!(Ubig::<1>::from(1_usize).to_f64(), Some(1_f64));
1047 assert_eq!(Ubig::<1>::from(2_usize).to_f64(), Some(2_f64));
1048 assert_eq!(Ubig::<1>::from(3_usize).to_f64(), Some(3_f64));
1049 assert_eq!(Ubig::<1>::from(4_usize).to_f64(), Some(4_f64));
1050 assert_eq!(Ubig::<1>::from(5_usize).to_f64(), Some(5_f64));
1051 assert_eq!(Ubig::<1>::from(6_usize).to_f64(), Some(6_f64));
1052 assert_eq!(Ubig::<1>::from(7_usize).to_f64(), Some(7_f64));
1053 assert_eq!(Ubig::<1>::from(123456789_usize).to_f64(), Some(123456789_f64));
1054 }
1055
1056 #[test]
1057 fn test_to_primitive_rounding() {
1058 assert_eq!(Ubig::<1>::from(16777216_usize).to_f32(), Some(16777216_f32));
1059 assert_eq!(Ubig::<1>::from(16777217_usize).to_f32(), Some(16777217_f32));
1060 assert_eq!(Ubig::<1>::from(16777218_usize).to_f32(), Some(16777218_f32));
1061 assert_eq!(Ubig::<1>::from(16777219_usize).to_f32(), Some(16777219_f32));
1062
1063 assert_eq!(Ubig::<1>::from(123_456_789_usize).to_f32(), Some(123456790_f32));
1064
1065 for i in 0..100 {
1066 let x = 2_usize.pow(25) + i;
1067 assert_eq!(Ubig::<1>::from(x).to_f32(), Some(x as f32));
1068 }
1069
1070 assert_eq!(Ubig::<1>::from(9_007_199_254_740_992_usize).to_f32(), Some(9007199000000000_f32));
1071 assert_eq!(Ubig::<1>::from(9_007_199_254_740_993_usize).to_f32(), Some(9007199000000000_f32));
1072 assert_eq!(Ubig::<1>::from(9_007_199_254_740_994_usize).to_f32(), Some(9007199000000000_f32));
1073
1074 assert_eq!(Ubig::<1>::from(9_007_199_254_740_992_usize).to_f64(), Some(9_007_199_254_740_992_f64));
1075 assert_eq!(Ubig::<1>::from(9_007_199_254_740_993_usize).to_f64(), Some(9_007_199_254_740_992_f64));
1076 assert_eq!(Ubig::<1>::from(9_007_199_254_740_994_usize).to_f64(), Some(9_007_199_254_740_994_f64));
1077
1078 for i in 0..100 {
1079 let x = 2_usize.pow(54) + i;
1080 assert_eq!(Ubig::<1>::from(x).to_f64(), Some(x as f64));
1081 }
1082 }
1083}