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