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::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, shr, 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]
29 #[inline]
30 pub(crate) unsafe fn from_inner_unchecked(values: SmallVec<[usize; S]>) -> Self {
31 debug_assert!(is_well_formed(&values));
32
33 Self(values)
34 }
35}
36
37impl<const S: usize> NonZeroUbig<S> {
38 #[must_use]
42 pub fn new(n: usize) -> Option<Self> {
43 if n != 0 {
44 Some(unsafe { Self(smallvec![n]) })
45 } else {
46 None
47 }
48 }
49 #[must_use]
50 #[inline]
51 pub(crate) unsafe fn new_unchecked(value: usize) -> Self {
52 NonZeroUbig(smallvec![value])
53 }
54 #[must_use]
55 #[inline]
56 pub(crate) unsafe fn from_inner_unchecked(values: SmallVec<[usize; S]>) -> Self {
57 debug_assert!(is_well_formed(&values));
58
59 Self(values)
60 }
61}
62
63impl<const S: usize> Default for Ubig<S> {
64 fn default() -> Self {
65 Self::zero()
66 }
67}
68
69impl<const S: usize> From<NonZeroUsize> for Ubig<S> {
70 fn from(value: NonZeroUsize) -> Self {
71 Self(smallvec![value.get()])
72 }
73}
74
75impl<const S: usize> From<NonZeroUsize> for NonZeroUbig<S> {
76 fn from(value: NonZeroUsize) -> Self {
77 Self(smallvec![value.get()])
78 }
79}
80
81impl<const S: usize, const I: usize> TryFrom<[usize; I]> for Ubig<S> {
82 type Error = ();
84
85 fn try_from(value: [usize; I]) -> Result<Self, Self::Error> {
86 if is_well_formed(&value) {
87 Ok(Self(SmallVec::from_slice(&value)))
88 } else {
89 Err(())
90 }
91 }
92}
93
94impl<const S: usize, const I: usize> TryFrom<[usize; I]> for NonZeroUbig<S> {
95 type Error = ();
97
98 fn try_from(value: [usize; I]) -> Result<Self, Self::Error> {
99 if is_well_formed(&value) && !value.is_empty() {
100 Ok(Self(SmallVec::from_slice(&value)))
101 } else {
102 Err(())
103 }
104 }
105}
106
107impl<const S: usize> Zero for Ubig<S> {
108 #[must_use]
109 #[inline]
110 fn zero() -> Self {
111 Self(smallvec![])
112 }
113
114 #[inline]
115 fn set_zero(&mut self) {
116 self.0.clear();
117 }
118
119 #[must_use]
120 #[inline]
121 fn is_zero(&self) -> bool {
122 self.0.is_empty()
123 }
124}
125
126impl<const S: usize> One for Ubig<S> {
127 #[must_use]
128 #[inline]
129 fn one() -> Self {
130 Self(smallvec![1])
131 }
132
133 #[inline]
134 fn set_one(&mut self) {
135 self.0.clear();
136 self.0.push(1);
137 }
138
139 #[must_use]
140 #[inline]
141 fn is_one(&self) -> bool {
142 self.0.len() == 1 && self.0[0] == 1
143 }
144}
145
146impl<const S: usize> One for NonZeroUbig<S> {
147 #[must_use]
148 #[inline]
149 fn one() -> Self {
150 Self(smallvec![1])
151 }
152
153 #[inline]
154 fn set_one(&mut self) {
155 self.0.truncate(1);
156 *unsafe { self.0.get_unchecked_mut(0) } = 1;
157 }
158
159 #[must_use]
160 #[inline]
161 fn is_one(&self) -> bool {
162 *unsafe { self.0.get_unchecked(0) } == 1 && self.0.len() == 1
163 }
164}
165
166
167impl<const S: usize> From<usize> for Ubig<S> {
168 fn from(value: usize) -> Self {
169 Self(if value > 0 { smallvec![value] } else { smallvec![] })
170 }
171}
172
173impl<const S: usize> FromStr for Ubig<S> {
174 type Err = &'static str;
176
177 fn from_str(s: &str) -> Result<Self, Self::Err> {
178 from_str_radix::<10, S>(s).map(Self)
179 }
180}
181
182impl<const S: usize> FromStr for NonZeroUbig<S> {
183 type Err = &'static str;
185
186 fn from_str(s: &str) -> Result<Self, Self::Err> {
187 from_str_radix::<10, S>(s)
188 .map(|inner| {
189 if !inner.is_empty() {
190 Ok(unsafe { Self(inner) })
191 } else {
192 Err("Zero value")
193 }
194 })
195 .flatten()
196 }
197}
198
199impl<const S: usize> fmt::Display for Ubig<S> {
200 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
201 f.write_str(&to_str_radix::<10>(self))
202 }
203}
204
205impl<const S: usize> fmt::Display for NonZeroUbig<S> {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 f.write_str(&to_str_radix::<10>(self))
209 }
210}
211
212#[inline]
213pub fn from_str_radix<const RADIX: u32, const S: usize>(s: &str) -> Result<SmallVec<[usize; S]>, &'static str> {
214 debug_assert!(RADIX <= 36);
215
216 match s.len() {
217 0 => Err("Empty string"),
218 _ => {
219 let mut char_iterator = s
220 .trim()
221 .chars()
222 .skip_while(|&c| c == '0');
223 match char_iterator.next() {
224 None => Ok(smallvec![]),
225 Some(value) => {
226 match value.to_digit(RADIX) {
227 None => Err("Character is not a digit"),
228 Some(value) => {
229 let mut non_zero_total = unsafe { smallvec![value as usize] };
230
231 for character in char_iterator {
232 match character.to_digit(RADIX) {
233 None => return Err("Character is not a digit"),
234 Some(value) => {
235 mul_assign_single_non_zero(&mut non_zero_total, RADIX as usize);
236 add_assign_single_non_zero(&mut non_zero_total, value as usize);
237 }
238 }
239 }
240
241 Ok(non_zero_total)
242 }
243 }
244 }
245 }
246 }
247 }
248}
249
250fn to_str_radix<const RADIX: u32>(value: &[usize]) -> String {
251 assert!(RADIX > 1 && RADIX <= 36);
252
253 match value.len() {
254 0 => "0".to_string(),
255 _ => {
256 let mut digits = vec![0];
257
258 let mut leading_zero_words = 0;
260 while value[leading_zero_words] == 0 {
261 leading_zero_words += 1;
263 }
264 let leading_zero_bits = value.last().unwrap().leading_zeros();
265
266 let mut value = value.iter()
268 .skip(leading_zero_words)
269 .map(|word| word.reverse_bits())
270 .rev()
271 .collect::<SmallVec<[usize; 8]>>();
272 let len_before_shift = value.len() as u32;
273 shr_mut(&mut value, 0, leading_zero_bits);
274
275 let bit_count = len_before_shift * BITS_PER_WORD - leading_zero_bits;
276 debug_assert_eq!(value[0] % 2, 1);
277 for bit_index in 0..bit_count {
278 update_digits::<RADIX>(&mut digits, value[0] % 2 == 1);
279 shr_mut(&mut value, 0, 1);
280
281 if value.is_empty() {
282 for _ in (bit_index + 1)..(leading_zero_words as u32 * BITS_PER_WORD + bit_count) {
284 update_digits::<RADIX>(&mut digits, false);
285 }
286 break;
287 }
288 }
289
290 digits.into_iter()
291 .rev()
292 .map(|digit| {
293 if digit < 10 {
294 digit.to_string()
295 } else {
296 ASCII_LOWER[(digit - 10) as usize].to_string()
297 }
298 })
299 .collect()
300 }
301 }
302}
303
304static ASCII_LOWER: [char; 26] = [
305 'a', 'b', 'c', 'd', 'e',
306 'f', 'g', 'h', 'i', 'j',
307 'k', 'l', 'm', 'n', 'o',
308 'p', 'q', 'r', 's', 't',
309 'u', 'v', 'w', 'x', 'y',
310 'z',
311];
312
313fn update_digits<const RADIX: u32>(digits: &mut Vec<u32>, mut carry: bool) {
314 for digit in digits.iter_mut() {
315 *digit *= 2; if carry {
317 *digit += 1;
318 carry = false;
319 }
320 if *digit >= RADIX {
321 *digit %= RADIX;
322 carry = true;
323 }
324 }
325 if carry {
326 digits.push(1);
327 }
328}
329
330impl<const S: usize> FromPrimitive for Ubig<S> {
331 fn from_isize(n: isize) -> Option<Self> {
332 if n >= 0 {
333 Some(Self::new(n.unsigned_abs()))
334 } else {
335 None
336 }
337 }
338
339 fn from_i8(n: i8) -> Option<Self> {
340 if n >= 0 {
341 Some(Self::new(n.unsigned_abs() as usize))
342 } else {
343 None
344 }
345 }
346
347 fn from_i16(n: i16) -> Option<Self> {
348 if n >= 0 {
349 Some(Self::new(n.unsigned_abs() as usize))
350 } else {
351 None
352 }
353 }
354
355 fn from_i32(n: i32) -> Option<Self> {
356 if n >= 0 {
357 Some(Self::new(n.unsigned_abs() as usize))
358 } else {
359 None
360 }
361 }
362
363 fn from_i64(n: i64) -> Option<Self> {
364 if n >= 0 {
365 Some(Self::new(n.unsigned_abs() as usize))
366 } else {
367 None
368 }
369 }
370
371 fn from_i128(n: i128) -> Option<Self> {
372 if n >= 0 {
373 Self::from_u128(n.unsigned_abs())
374 } else {
375 None
376 }
377 }
378
379 fn from_usize(n: usize) -> Option<Self> {
380 Some(Self::new(n))
381 }
382
383 fn from_u8(n: u8) -> Option<Self> {
384 Some(Self::new(n as usize))
385 }
386
387 fn from_u16(n: u16) -> Option<Self> {
388 Some(Self::new(n as usize))
389 }
390
391 fn from_u32(n: u32) -> Option<Self> {
392 Some(Self::new(n as usize))
393 }
394
395 fn from_u64(n: u64) -> Option<Self> {
396 Some(Self::new(n as usize))
397 }
398
399 fn from_u128(n: u128) -> Option<Self> {
400 let bits = mem::size_of::<u32>() * 8;
401 let groups = 128 / bits;
402
403 let mut data = (0..groups)
404 .map(|i| (n >> (i * bits)) as usize)
405 .collect::<SmallVec<_>>();
406 while let Some(0) = data.last() {
407 data.pop();
408 }
409
410 debug_assert!(is_well_formed(&data));
411
412 Some(unsafe {
413 Self::from_inner_unchecked(data)
415 })
416 }
417
418 fn from_f32(n: f32) -> Option<Self> {
419 Self::from_float_kind(f32_kind(n))
420 }
421
422 fn from_f64(n: f64) -> Option<Self> {
423 Self::from_float_kind(f64_kind(n))
424 }
425}
426
427impl<const S: usize> Ubig<S> {
428 fn from_float_kind(kind: FloatKind) -> Option<Self> {
429 match kind {
430 FloatKind::Subnormal(as_ratio) | FloatKind::Normal(as_ratio) => {
431 if as_ratio.sign == 0 {
432 let result = match as_ratio.exponent.cmp(&0) {
433 Ordering::Less => {
434 let result = as_ratio.fraction.get() >> as_ratio.exponent.unsigned_abs();
435 Self::from(result as usize)
436 }
437 Ordering::Equal => Self::from(as_ratio.fraction.get() as usize),
438 Ordering::Greater => {
439 let exponent = as_ratio.exponent.unsigned_abs();
440 let (words, bits) = (exponent / BITS_PER_WORD, exponent % BITS_PER_WORD);
441 let values = [as_ratio.fraction.get() as usize];
442 let result = shr(&values, words as usize, bits);
443
444 unsafe {
445 Self::from_inner_unchecked(result)
446 }
447 }
448 };
449
450 Some(result)
451 } else {
452 None
453 }
454 },
455 FloatKind::Zero => Some(Self::zero()),
456 _ => None,
457 }
458 }
459}
460
461
462macro_rules! small {
463 ($value:expr) => {
464 {
465 match $value.len() {
466 0 => Some(0),
467 1 => $value[0].try_into().ok(),
468 _ => None,
469 }
470 }
471 }
472}
473
474macro_rules! to_primitive_impl {
475 ($name:ty) => {
476 impl<const S: usize> ToPrimitive for $name {
477 fn to_isize(&self) -> Option<isize> {
478 small!(self)
479 }
480
481 fn to_i8(&self) -> Option<i8> {
482 small!(self)
483 }
484
485 fn to_i16(&self) -> Option<i16> {
486 small!(self)
487 }
488
489 fn to_i32(&self) -> Option<i32> {
490 small!(self)
491 }
492
493 fn to_i64(&self) -> Option<i64> {
494 small!(self)
495 }
496
497 fn to_i128(&self) -> Option<i128> {
498 todo!()
499 }
500
501 fn to_usize(&self) -> Option<usize> {
502 small!(self)
503 }
504
505 fn to_u8(&self) -> Option<u8> {
506 small!(self)
507 }
508
509 fn to_u16(&self) -> Option<u16> {
510 small!(self)
511 }
512
513 fn to_u32(&self) -> Option<u32> {
514 small!(self)
515 }
516
517 fn to_u64(&self) -> Option<u64> {
518 small!(self)
519 }
520
521 fn to_u128(&self) -> Option<u128> {
522 todo!()
523 }
524
525 fn to_f32(&self) -> Option<f32> {
526 Some(make_float_32::<S>(self))
527 }
528
529 fn to_f64(&self) -> Option<f64> {
530 Some(make_float_64::<S>(self))
531 }
532 }
533 }
534}
535
536to_primitive_impl!(Ubig<S>);
537to_primitive_impl!(NonZeroUbig<S>);
538
539macro_rules! define_float_maker {
540 ($name:ident, $target:ty, $bit_array:ty, $bits_in_exponent:expr, $bits_in_fraction:expr) => {
541 fn $name<const S: usize>(values: &[usize]) -> $target {
542 let sign = 0;
543
544 match values.last() {
545 None => <$target>::zero(),
546 Some(last_value) => {
547 debug_assert_ne!(*last_value, 0);
548 let bits_in_highest = BITS_PER_WORD - last_value.leading_zeros();
549 debug_assert!(bits_in_highest > 0);
550 let bits = (values.len() - 1) as u32 * BITS_PER_WORD + bits_in_highest;
551 debug_assert!(bits > 0);
552
553 let exponent = (bits as $bit_array + ((2 as $bit_array).pow($bits_in_exponent - 1) - 1 - 1)) << $bits_in_fraction;
554
555 let mut copy = SmallVec::<[usize; S]>::from_slice(values);
556 *copy.last_mut().unwrap() -= 1 << (bits_in_highest - 1);
557
558 let remaining_bits = bits - 1;
559 let fraction = match remaining_bits.cmp(&$bits_in_fraction) {
560 Ordering::Less => copy[0] << ($bits_in_fraction - remaining_bits),
561 Ordering::Equal => copy[0],
562 Ordering::Greater => {
563 let to_shift = remaining_bits - $bits_in_fraction;
564 let (highest_bit_lost_set, any_other_set) = {
565 let index = to_shift - 1;
566
567 let (words, bits) = ((index / BITS_PER_WORD) as usize, index % BITS_PER_WORD);
568 let highest_bit_lost = copy[words] & (1 << bits) > 0;
569
570 let any_other = copy[..words].iter().any(|&w| w != 0)
571 || {
572 if bits == 0 {
573 false
574 } else {
575 let mask = !0 >> (BITS_PER_WORD - bits);
576 mask & copy[words] > 0
577 }
578 };
579
580 (highest_bit_lost, any_other)
581 };
582
583 let (mut words, bits) = (to_shift / BITS_PER_WORD, to_shift % BITS_PER_WORD);
584
585 let unrounded = 'scope: {
586 while let Some(0) = copy.last() {
588 if copy.len() == 1 {
589 break 'scope 0;
591 }
592 copy.pop();
593 words -= 1;
594 }
595 shr_mut(&mut copy, words as usize, bits);
596
597 match copy.last() {
598 Some(&value) => value,
599 None => 0,
600 }
601 };
602
603 if highest_bit_lost_set {
604 if any_other_set {
605 unrounded + 1
606 } else {
607 if unrounded % 2 == 1 {
609 unrounded + 1
610 } else {
611 unrounded
612 }
613 }
614 } else {
615 unrounded
616 }
617 },
618 };
619
620 <$target>::from_bits(sign | exponent | fraction as $bit_array)
621 }
622 }
623 }
624 }
625}
626
627define_float_maker!(make_float_32, f32, u32, 8, 23);
628define_float_maker!(make_float_64, f64, u64, 11, 52);
629
630#[cfg(test)]
631mod test {
632 use num_traits::FromPrimitive;
633 use num_traits::ToPrimitive;
634
635 use crate::Ubig;
636
637 #[test]
638 fn test_from_primitive() {
639 assert_eq!(Ubig::<1>::from_i16(-4), None);
640 assert_eq!(Ubig::<1>::from_u16(4), Some(Ubig::from(4)));
641 assert_eq!(Ubig::<1>::from_i128(0), Some(Ubig::from(0)));
642 assert_eq!(Ubig::<1>::from_i128(1), Some(Ubig::from(1)));
643 assert_eq!(Ubig::<1>::from_i128(-1), None);
644
645 assert_eq!(Ubig::<1>::from_f32(1.5_f32), Some(Ubig::from(1)));
646 assert_eq!(Ubig::<1>::from_f32(1_f32), Some(Ubig::from(1)));
647 assert_eq!(Ubig::<1>::from_f32(0.5_f32), Some(Ubig::from(0)));
648 assert_eq!(Ubig::<1>::from_f32(0.75_f32), Some(Ubig::from(0)));
649 assert_eq!(Ubig::<1>::from_f32(0_f32), Some(Ubig::from(0)));
650
651 assert_eq!(Ubig::<1>::from_f32(-1.5_f32), None);
652 assert_eq!(Ubig::<1>::from_f32(-0_f32), Some(Ubig::from(0)));
653 }
654
655 #[test]
656 fn test_to_primitive() {
657 assert_eq!(Ubig::<1>::from(4).to_i16(), Some(4));
658
659 assert_eq!(Ubig::<1>::from(0).to_f32(), Some(0_f32));
660 assert_eq!(Ubig::<1>::from(1).to_f32(), Some(1_f32));
661 assert_eq!(Ubig::<1>::from(2).to_f32(), Some(2_f32));
662 assert_eq!(Ubig::<1>::from(3).to_f32(), Some(3_f32));
663 assert_eq!(Ubig::<1>::from(4).to_f32(), Some(4_f32));
664 assert_eq!(Ubig::<1>::from(5).to_f32(), Some(5_f32));
665 assert_eq!(Ubig::<1>::from(6).to_f32(), Some(6_f32));
666 assert_eq!(Ubig::<1>::from(7).to_f32(), Some(7_f32));
667
668 assert_eq!(Ubig::<1>::from(0).to_f64(), Some(0_f64));
669 assert_eq!(Ubig::<1>::from(1).to_f64(), Some(1_f64));
670 assert_eq!(Ubig::<1>::from(2).to_f64(), Some(2_f64));
671 assert_eq!(Ubig::<1>::from(3).to_f64(), Some(3_f64));
672 assert_eq!(Ubig::<1>::from(4).to_f64(), Some(4_f64));
673 assert_eq!(Ubig::<1>::from(5).to_f64(), Some(5_f64));
674 assert_eq!(Ubig::<1>::from(6).to_f64(), Some(6_f64));
675 assert_eq!(Ubig::<1>::from(7).to_f64(), Some(7_f64));
676 assert_eq!(Ubig::<1>::from(123456789).to_f64(), Some(123456789_f64));
677 }
678
679 #[test]
680 fn test_to_primitive_rounding() {
681 assert_eq!(Ubig::<1>::from(16777216).to_f32(), Some(16777216_f32));
682 assert_eq!(Ubig::<1>::from(16777217).to_f32(), Some(16777217_f32));
683 assert_eq!(Ubig::<1>::from(16777218).to_f32(), Some(16777218_f32));
684 assert_eq!(Ubig::<1>::from(16777219).to_f32(), Some(16777219_f32));
685
686 assert_eq!(Ubig::<1>::from(123_456_789).to_f32(), Some(123456790_f32));
687
688 for i in 0..100 {
689 let x = 2_usize.pow(25) + i;
690 assert_eq!(Ubig::<1>::from(x).to_f32(), Some(x as f32));
691 }
692
693 assert_eq!(Ubig::<1>::from(9_007_199_254_740_992).to_f32(), Some(9007199000000000_f32));
694 assert_eq!(Ubig::<1>::from(9_007_199_254_740_993).to_f32(), Some(9007199000000000_f32));
695 assert_eq!(Ubig::<1>::from(9_007_199_254_740_994).to_f32(), Some(9007199000000000_f32));
696
697 assert_eq!(Ubig::<1>::from(9_007_199_254_740_992).to_f64(), Some(9_007_199_254_740_992_f64));
698 assert_eq!(Ubig::<1>::from(9_007_199_254_740_993).to_f64(), Some(9_007_199_254_740_992_f64));
699 assert_eq!(Ubig::<1>::from(9_007_199_254_740_994).to_f64(), Some(9_007_199_254_740_994_f64));
700
701 for i in 0..100 {
702 let x = 2_usize.pow(54) + i;
703 assert_eq!(Ubig::<1>::from(x).to_f64(), Some(x as f64));
704 }
705 }
706}