1#![cfg(not(feature = "compact"))]
27#![doc(hidden)]
28
29use crate::float::{ExtendedFloat80, RawFloat};
30use crate::options::{Options, RoundMode};
31use crate::shared;
32use crate::table::*;
33#[cfg(feature = "f16")]
34use lexical_util::bf16::bf16;
35#[cfg(feature = "f16")]
36use lexical_util::f16::f16;
37use lexical_util::format::{NumberFormat, STANDARD};
38use lexical_util::num::{AsPrimitive, Float};
39use lexical_write_integer::decimal::DigitCount;
40use lexical_write_integer::write::WriteInteger;
41
42#[inline]
49pub unsafe fn write_float<F: RawFloat, const FORMAT: u128>(
50 float: F,
51 bytes: &mut [u8],
52 options: &Options,
53) -> usize {
54 debug_assert!(!float.is_special());
55 debug_assert!(float >= F::ZERO);
56
57 let fp = to_decimal(float);
58 let digit_count = F::digit_count(fp.mant);
59 let sci_exp = fp.exp + digit_count as i32 - 1;
60
61 write_float!(
67 FORMAT,
68 sci_exp,
69 options,
70 write_float_scientific,
71 write_float_positive_exponent,
72 write_float_negative_exponent,
73 generic => F,
74 args => bytes, fp, sci_exp, options,
75 )
76}
77
78pub unsafe fn write_float_scientific<F: DragonboxFloat, const FORMAT: u128>(
85 bytes: &mut [u8],
86 fp: ExtendedFloat80,
87 sci_exp: i32,
88 options: &Options,
89) -> usize {
90 debug_assert_eq!(count_factors(10, fp.mant), 0);
92 let format = NumberFormat::<{ FORMAT }> {};
93 assert!(format.is_valid());
94 let decimal_point = options.decimal_point();
95
96 let digits = unsafe { &mut index_unchecked_mut!(bytes[1..]) };
100 let digit_count = unsafe { F::write_digits(digits, fp.mant) };
101
102 let (digit_count, carried) =
105 unsafe { shared::truncate_and_round_decimal(digits, digit_count, options) };
106 let sci_exp = sci_exp + carried as i32;
107
108 let exact_count = shared::min_exact_digits(digit_count, options);
110
111 let mut cursor: usize;
114 unsafe {
115 index_unchecked_mut!(bytes[0] = bytes[1]);
116 index_unchecked_mut!(bytes[1]) = decimal_point;
117
118 if !format.no_exponent_without_fraction() && digit_count == 1 && options.trim_floats() {
119 cursor = 1;
120 } else if digit_count < exact_count {
121 cursor = digit_count + 1;
123 let zeros = exact_count - digit_count;
124 unsafe {
125 slice_fill_unchecked!(index_unchecked_mut!(bytes[cursor..cursor + zeros]), b'0');
126 }
127 cursor += zeros;
128 } else if digit_count == 1 {
129 index_unchecked_mut!(bytes[2]) = b'0';
130 cursor = 3;
131 } else {
132 cursor = digit_count + 1;
133 }
134 }
135
136 unsafe { shared::write_exponent::<FORMAT>(bytes, &mut cursor, sci_exp, options.exponent()) };
139
140 cursor
141}
142
143pub unsafe fn write_float_negative_exponent<F: DragonboxFloat, const FORMAT: u128>(
151 bytes: &mut [u8],
152 fp: ExtendedFloat80,
153 sci_exp: i32,
154 options: &Options,
155) -> usize {
156 debug_assert!(sci_exp < 0);
157 debug_assert_eq!(count_factors(10, fp.mant), 0);
158
159 let decimal_point = options.decimal_point();
161 let sci_exp = sci_exp.wrapping_neg() as usize;
162
163 let mut cursor = sci_exp + 1;
165 debug_assert!(cursor >= 2);
166 unsafe {
168 let digits = &mut index_unchecked_mut!(bytes[..cursor]);
173 slice_fill_unchecked!(digits, b'0');
174 }
175
176 let digits = unsafe { &mut index_unchecked_mut!(bytes[cursor..]) };
179 let digit_count = unsafe { F::write_digits(digits, fp.mant) };
180
181 debug_assert!(cursor > 0);
184 let (digit_count, carried) =
185 unsafe { shared::truncate_and_round_decimal(digits, digit_count, options) };
186
187 let mut trimmed = false;
189 if carried && cursor == 2 {
190 unsafe {
194 index_unchecked_mut!(bytes[0]) = b'1';
195 if options.trim_floats() {
196 cursor = 1;
197 trimmed = true;
198 } else {
199 index_unchecked_mut!(bytes[1]) = decimal_point;
200 index_unchecked_mut!(bytes[2]) = b'0';
201 cursor = 3;
202 }
203 }
204 } else if carried {
205 unsafe {
208 index_unchecked_mut!(bytes[1]) = decimal_point;
209 index_unchecked_mut!(bytes[cursor - 1] = bytes[cursor]);
210 }
211 } else {
212 unsafe { index_unchecked_mut!(bytes[1]) = decimal_point };
214 cursor += digit_count;
215 }
216
217 let exact_count = shared::min_exact_digits(digit_count, options);
219
220 if !trimmed && digit_count < exact_count {
223 let zeros = exact_count - digit_count;
224 unsafe {
226 slice_fill_unchecked!(index_unchecked_mut!(bytes[cursor..cursor + zeros]), b'0');
227 }
228 cursor += zeros;
229 }
230
231 cursor
232}
233
234pub unsafe fn write_float_positive_exponent<F: DragonboxFloat, const FORMAT: u128>(
242 bytes: &mut [u8],
243 fp: ExtendedFloat80,
244 sci_exp: i32,
245 options: &Options,
246) -> usize {
247 debug_assert!(sci_exp >= 0);
249 debug_assert_eq!(count_factors(10, fp.mant), 0);
250 let decimal_point = options.decimal_point();
251
252 let digit_count = unsafe { F::write_digits(bytes, fp.mant) };
260 let (mut digit_count, carried) =
261 unsafe { shared::truncate_and_round_decimal(bytes, digit_count, options) };
262
263 let leading_digits = sci_exp as usize + 1 + carried as usize;
265 let mut cursor: usize;
266 let mut trimmed = false;
267 if leading_digits >= digit_count {
268 unsafe {
272 let digits = &mut index_unchecked_mut!(bytes[digit_count..leading_digits]);
273 slice_fill_unchecked!(digits, b'0');
274 }
275 cursor = leading_digits;
276 digit_count = leading_digits;
277 if !options.trim_floats() {
279 unsafe { index_unchecked_mut!(bytes[cursor]) = decimal_point };
281 cursor += 1;
282 unsafe { index_unchecked_mut!(bytes[cursor]) = b'0' };
283 cursor += 1;
284 digit_count += 1;
285 } else {
286 trimmed = true;
287 }
288 } else {
289 let count = digit_count - leading_digits;
293 unsafe {
294 let buf = &mut index_unchecked_mut!(bytes[leading_digits..digit_count + 1]);
295 safe_assert!(buf.len() > count);
296 for i in (0..count).rev() {
297 index_unchecked_mut!(buf[i + 1] = buf[i]);
298 }
299 }
300
301 unsafe { index_unchecked_mut!(bytes[leading_digits]) = decimal_point };
304 cursor = digit_count + 1;
305 }
306
307 let exact_count = shared::min_exact_digits(digit_count, options);
311
312 if !trimmed && exact_count > digit_count {
314 let zeros = exact_count - digit_count;
316 unsafe {
318 let digits = &mut index_unchecked_mut!(bytes[cursor..cursor + zeros]);
319 slice_fill_unchecked!(digits, b'0');
320 }
321 cursor += zeros;
322 }
323
324 cursor
325}
326
327#[inline]
340pub fn to_decimal<F: RawFloat>(float: F) -> ExtendedFloat80 {
341 let bits = float.to_bits();
342 let mantissa_bits = bits & F::MANTISSA_MASK;
343
344 if (bits & !F::SIGN_MASK).as_u64() == 0 {
345 return extended_float(0, 0);
346 }
347
348 if mantissa_bits.as_u64() == 0 {
405 compute_round_short(float)
406 } else {
407 compute_round(float)
408 }
409}
410
411#[inline(always)]
413pub fn compute_round_short<F: RawFloat>(float: F) -> ExtendedFloat80 {
414 compute_nearest_shorter(float)
415}
416
417#[inline(always)]
419pub fn compute_round<F: RawFloat>(float: F) -> ExtendedFloat80 {
420 compute_nearest_normal(float)
421}
422
423pub fn compute_nearest_shorter<F: RawFloat>(float: F) -> ExtendedFloat80 {
426 let exponent = float.exponent();
428 let minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
429 let beta = exponent + floor_log2_pow10(-minus_k);
430
431 let pow5 = unsafe { F::dragonbox_power(-minus_k) };
434 let mut xi = F::compute_left_endpoint(&pow5, beta);
435 let mut zi = F::compute_right_endpoint(&pow5, beta);
436
437 let interval_type = IntervalType::Closed;
440
441 if !interval_type.include_right_endpoint() && is_right_endpoint::<F>(exponent) {
444 zi -= 1;
445 }
446
447 if !(interval_type.include_left_endpoint() && is_left_endpoint::<F>(exponent)) {
449 xi += 1;
450 }
451
452 let significand = zi / 10;
454
455 if significand * 10 >= xi {
457 let (mant, exp) = F::process_trailing_zeros(significand, minus_k + 1);
458 return extended_float(mant, exp);
459 }
460
461 let mut significand = F::compute_round_up(&pow5, beta);
463
464 let bits: i32 = F::MANTISSA_SIZE;
466 let lower_threshold: i32 = -floor_log5_pow2_minus_log5_3(bits + 4) - 2 - bits;
467 let upper_threshold: i32 = -floor_log5_pow2(bits + 2) - 2 - bits;
468
469 let round_down = RoundMode::Round.prefer_round_down(significand);
470 if round_down && exponent >= lower_threshold && exponent <= upper_threshold {
471 significand -= 1;
472 } else if significand < xi {
473 significand += 1;
474 }
475
476 debug_assert!(float.exponent() == exponent);
479 debug_assert!(minus_k == floor_log10_pow2_minus_log10_4_over_3(exponent));
480
481 extended_float(significand, minus_k)
482}
483
484#[allow(clippy::comparison_chain)]
487pub fn compute_nearest_normal<F: RawFloat>(float: F) -> ExtendedFloat80 {
488 let mantissa = float.mantissa().as_u64();
489 let exponent = float.exponent();
490 let is_even = mantissa % 2 == 0;
491
492 let minus_k = floor_log10_pow2(exponent) - F::KAPPA as i32;
495 let pow5 = unsafe { F::dragonbox_power(-minus_k) };
497 let beta = exponent + floor_log2_pow10(-minus_k);
498
499 let two_fc = mantissa << 1;
502 let deltai = F::compute_delta(&pow5, beta);
503 let (zi, is_z_integer) = F::compute_mul((two_fc | 1) << beta, &pow5);
513
514 let big_divisor = pow32(10, F::KAPPA + 1);
516 let small_divisor = pow32(10, F::KAPPA);
517
518 let exp = F::KAPPA + 1;
521 let n_max = (1 << (F::MANTISSA_SIZE + 1)) * big_divisor as u64 - 1;
522 let mut significand = F::divide_by_pow10(zi, exp, n_max);
523 let mut r = (zi - (big_divisor as u64).wrapping_mul(significand)) as u32;
524
525 let interval_type = IntervalType::Symmetric(is_even);
528
529 let mut should_short_circuit = true;
535 if r < deltai {
536 let include_right = interval_type.include_right_endpoint();
538 if r == 0 && !include_right && is_z_integer {
539 significand -= 1;
540 r = big_divisor;
541 should_short_circuit = false;
542 }
543 } else if r > deltai {
544 should_short_circuit = false;
545 } else {
546 let two_fl = two_fc - 1;
551 let include_left = interval_type.include_left_endpoint();
552
553 if !include_left || exponent < F::FC_PM_HALF_LOWER || exponent > F::DIV_BY_5_THRESHOLD {
554 let parity = F::compute_mul_parity(two_fl, &pow5, beta).0;
560 if !parity {
561 should_short_circuit = false;
562 }
563 } else {
564 let (xi_parity, x_is_integer) = F::compute_mul_parity(two_fl, &pow5, beta);
565 if !xi_parity && !x_is_integer {
566 should_short_circuit = false
567 }
568 }
569 }
570
571 if should_short_circuit {
572 let (mant, exp) = F::process_trailing_zeros(significand, minus_k + F::KAPPA as i32 + 1);
574 extended_float(mant, exp)
575 } else {
576 significand *= 10;
578
579 let dist = r - (deltai / 2) + (small_divisor / 2);
580 let approx_y_parity = ((dist ^ (small_divisor / 2)) & 1) != 0;
581
582 let (dist, is_dist_div_by_kappa) = F::check_div_pow10(dist);
584
585 significand += dist as u64;
587
588 if is_dist_div_by_kappa {
589 let (yi_parity, is_y_integer) = F::compute_mul_parity(two_fc, &pow5, beta);
596 let round_down = RoundMode::Round.prefer_round_down(significand);
597
598 if yi_parity != approx_y_parity || (is_y_integer && round_down) {
599 significand -= 1;
604 }
605 }
606
607 debug_assert!(float.exponent() == exponent);
610 debug_assert!(minus_k == floor_log10_pow2(exponent) - F::KAPPA as i32);
611
612 extended_float(significand, minus_k + F::KAPPA as i32)
613 }
614}
615
616#[allow(clippy::comparison_chain)]
618pub fn compute_left_closed_directed<F: RawFloat>(float: F) -> ExtendedFloat80 {
619 let mantissa = float.mantissa().as_u64();
620 let exponent = float.exponent();
621
622 let minus_k = floor_log10_pow2(exponent) - F::KAPPA as i32;
625 let pow5 = unsafe { F::dragonbox_power(-minus_k) };
627 let beta = exponent + floor_log2_pow10(-minus_k);
628
629 let two_fc = mantissa << 1;
632 let deltai = F::compute_delta(&pow5, beta);
633 let (mut xi, mut is_x_integer) = F::compute_mul(two_fc << beta, &pow5);
634
635 if F::BITS == 32 && exponent <= -80 {
642 is_x_integer = false;
643 }
644
645 if !is_x_integer {
646 xi += 1;
647 }
648
649 let big_divisor = pow32(10, F::KAPPA + 1);
651
652 let exp = F::KAPPA + 1;
655 let n_max = (1 << (F::MANTISSA_SIZE + 1)) * big_divisor as u64 - 1;
656 let mut significand = F::divide_by_pow10(xi, exp, n_max);
657 let mut r = (xi - (big_divisor as u64).wrapping_mul(significand)) as u32;
658
659 if r != 0 {
660 significand += 1;
661 r = big_divisor - r;
662 }
663
664 let mut should_short_circuit = true;
670 if r > deltai {
671 should_short_circuit = false;
672 } else if r == deltai {
673 let (zi_parity, is_z_integer) = F::compute_mul_parity(two_fc + 2, &pow5, beta);
680 if zi_parity || is_z_integer {
681 should_short_circuit = false;
682 }
683 }
684
685 if should_short_circuit {
686 let (mant, exp) = F::process_trailing_zeros(significand, minus_k + F::KAPPA as i32 + 1);
687 extended_float(mant, exp)
688 } else {
689 significand *= 10;
691 significand -= F::div_pow10(r) as u64;
692
693 debug_assert!(float.exponent() == exponent);
696 debug_assert!(minus_k == floor_log10_pow2(exponent) - F::KAPPA as i32);
697
698 extended_float(significand, minus_k + F::KAPPA as i32)
699 }
700}
701
702#[allow(clippy::comparison_chain, clippy::if_same_then_else)]
704pub fn compute_right_closed_directed<F: RawFloat>(float: F, shorter: bool) -> ExtendedFloat80 {
705 let mantissa = float.mantissa().as_u64();
706 let exponent = float.exponent();
707
708 let minus_k = floor_log10_pow2(exponent - shorter as i32) - F::KAPPA as i32;
711 let pow5 = unsafe { F::dragonbox_power(-minus_k) };
713 let beta = exponent + floor_log2_pow10(-minus_k);
714
715 let two_fc = mantissa << 1;
718 let deltai = F::compute_delta(&pow5, beta - shorter as i32);
719 let zi = F::compute_mul(two_fc << beta, &pow5).0;
720
721 let big_divisor = pow32(10, F::KAPPA + 1);
723
724 let exp = F::KAPPA + 1;
727 let n_max = (1 << (F::MANTISSA_SIZE + 1)) * big_divisor as u64 - 1;
728 let mut significand = F::divide_by_pow10(zi, exp, n_max);
729 let r = (zi - (big_divisor as u64).wrapping_mul(significand)) as u32;
730
731 let mut should_short_circuit = true;
737 if r > deltai {
738 should_short_circuit = false;
739 } else if r == deltai {
740 let two_f = two_fc
742 - if shorter {
743 1
744 } else {
745 2
746 };
747 if !F::compute_mul_parity(two_f, &pow5, beta).0 {
748 should_short_circuit = false;
749 }
750 }
751
752 if should_short_circuit {
753 let (mant, exp) = F::process_trailing_zeros(significand, minus_k + F::KAPPA as i32 + 1);
754 extended_float(mant, exp)
755 } else {
756 significand *= 10;
758 significand -= F::div_pow10(r) as u64;
759
760 debug_assert!(float.exponent() == exponent);
763 debug_assert!(minus_k == floor_log10_pow2(exponent - shorter as i32) - F::KAPPA as i32);
764
765 extended_float(significand, minus_k + F::KAPPA as i32)
766 }
767}
768
769#[inline]
791pub unsafe fn write_digits_u32(bytes: &mut [u8], mantissa: u32) -> usize {
792 debug_assert!(bytes.len() >= 10);
793 unsafe { mantissa.write_mantissa::<u32, { STANDARD }>(bytes) }
794}
795
796#[inline]
805#[allow(clippy::branches_sharing_code)]
806pub unsafe fn write_digits_u64(bytes: &mut [u8], mantissa: u64) -> usize {
807 debug_assert!(bytes.len() >= 20);
808 unsafe { mantissa.write_mantissa::<u64, { STANDARD }>(bytes) }
809}
810
811#[inline(always)]
816pub const fn extended_float(mant: u64, exp: i32) -> ExtendedFloat80 {
817 ExtendedFloat80 {
818 mant,
819 exp,
820 }
821}
822
823#[inline(always)]
827pub const fn floor_log2(mut n: u64) -> i32 {
828 let mut count = -1;
829 while n != 0 {
830 count += 1;
831 n >>= 1;
832 }
833 count
834}
835
836#[inline(always)]
837pub const fn is_endpoint(exponent: i32, lower: i32, upper: i32) -> bool {
838 exponent >= lower && exponent <= upper
839}
840
841#[inline(always)]
842pub fn is_right_endpoint<F: Float>(exponent: i32) -> bool {
843 let lower_threshold = 0;
844 let factors = count_factors(5, (1u64 << (F::MANTISSA_SIZE + 1)) + 1) + 1;
845 let upper_threshold = 2 + floor_log2(pow64(10, factors) / 3);
846 is_endpoint(exponent, lower_threshold, upper_threshold)
847}
848
849#[inline(always)]
850pub fn is_left_endpoint<F: Float>(exponent: i32) -> bool {
851 let lower_threshold = 2;
852 let factors = count_factors(5, (1u64 << (F::MANTISSA_SIZE + 2)) - 1) + 1;
853 let upper_threshold = 2 + floor_log2(pow64(10, factors) / 3);
854 is_endpoint(exponent, lower_threshold, upper_threshold)
855}
856
857#[inline(always)]
861pub const fn umul128_upper64(x: u64, y: u64) -> u64 {
862 let p = x as u128 * y as u128;
863 (p >> 64) as u64
864}
865
866#[inline(always)]
867pub const fn umul192_upper128(x: u64, hi: u64, lo: u64) -> (u64, u64) {
868 let mut r = x as u128 * hi as u128;
869 r += umul128_upper64(x, lo) as u128;
870 ((r >> 64) as u64, r as u64)
871}
872
873#[inline(always)]
874pub const fn umul192_lower128(x: u64, yhi: u64, ylo: u64) -> (u64, u64) {
875 let hi = x.wrapping_mul(yhi);
876 let hi_lo = x as u128 * ylo as u128;
877 (hi.wrapping_add((hi_lo >> 64) as u64), hi_lo as u64)
879}
880
881#[inline(always)]
882pub const fn umul96_upper64(x: u64, y: u64) -> u64 {
883 umul128_upper64(x << 32, y)
884}
885
886#[inline(always)]
887pub const fn umul96_lower64(x: u64, y: u64) -> u64 {
888 x.wrapping_mul(y)
889}
890
891#[inline(always)]
898pub const fn floor_log5_pow2(q: i32) -> i32 {
899 q.wrapping_mul(225799) >> 19
900}
901
902#[inline(always)]
906pub const fn floor_log10_pow2(q: i32) -> i32 {
907 q.wrapping_mul(315653) >> 20
908}
909
910#[inline(always)]
914pub const fn floor_log2_pow10(q: i32) -> i32 {
915 q.wrapping_mul(1741647) >> 19
916}
917
918#[inline(always)]
922pub const fn floor_log5_pow2_minus_log5_3(q: i32) -> i32 {
923 q.wrapping_mul(451597).wrapping_sub(715764) >> 20
924}
925
926#[inline(always)]
930pub const fn floor_log10_pow2_minus_log10_4_over_3(q: i32) -> i32 {
931 q.wrapping_mul(1262611).wrapping_sub(524031) >> 22
935}
936
937#[inline(always)]
942pub const fn pow32(radix: u32, mut exp: u32) -> u32 {
943 let mut p = 1;
944 while exp > 0 {
945 p *= radix;
946 exp -= 1;
947 }
948 p
949}
950
951#[inline(always)]
953pub const fn pow64(radix: u32, mut exp: u32) -> u64 {
954 let mut p = 1;
955 while exp > 0 {
956 p *= radix as u64;
957 exp -= 1;
958 }
959 p
960}
961
962#[inline(always)]
964pub const fn count_factors(radix: u32, mut n: u64) -> u32 {
965 let mut c = 0;
966 while n != 0 && n % radix as u64 == 0 {
967 n /= radix as u64;
968 c += 1;
969 }
970 c
971}
972
973#[inline(always)]
979pub const fn divide_by_pow10_32(n: u32, exp: u32) -> u32 {
980 if exp == 2 {
986 ((n as u64 * 1374389535) >> 37) as u32
987 } else {
988 let divisor = pow32(exp as u32, 10);
989 n / divisor
990 }
991}
992
993#[inline(always)]
996pub const fn divide_by_pow10_64(n: u64, exp: u32, n_max: u64) -> u64 {
997 if exp == 3 && n_max <= 15534100272597517998 {
1000 umul128_upper64(n, 2361183241434822607) >> 7
1001 } else {
1002 let divisor = pow64(exp as u32, 10);
1003 n / divisor
1004 }
1005}
1006
1007impl RoundMode {
1011 #[inline(always)]
1013 pub const fn prefer_round_down(&self, significand: u64) -> bool {
1014 match self {
1015 RoundMode::Round => significand % 2 != 0,
1016 RoundMode::Truncate => true,
1017 }
1018 }
1019}
1020
1021#[non_exhaustive]
1026pub enum IntervalType {
1027 Symmetric(bool),
1028 Asymmetric(bool),
1029 Closed,
1030 Open,
1031 LeftClosedRightOpen,
1032 RightClosedLeftOpen,
1033}
1034
1035impl IntervalType {
1036 #[inline(always)]
1038 pub fn is_symmetric(&self) -> bool {
1039 match self {
1040 Self::Symmetric(_) => true,
1041 Self::Asymmetric(_) => false,
1042 Self::Closed => true,
1043 Self::Open => true,
1044 Self::LeftClosedRightOpen => false,
1045 Self::RightClosedLeftOpen => false,
1046 }
1047 }
1048
1049 #[inline(always)]
1051 pub fn include_left_endpoint(&self) -> bool {
1052 match self {
1053 Self::Symmetric(closed) => *closed,
1054 Self::Asymmetric(left_closed) => *left_closed,
1055 Self::Closed => true,
1056 Self::Open => false,
1057 Self::LeftClosedRightOpen => true,
1058 Self::RightClosedLeftOpen => false,
1059 }
1060 }
1061
1062 #[inline(always)]
1064 pub fn include_right_endpoint(&self) -> bool {
1065 match self {
1066 Self::Symmetric(closed) => *closed,
1067 Self::Asymmetric(left_closed) => !*left_closed,
1068 Self::Closed => true,
1069 Self::Open => false,
1070 Self::LeftClosedRightOpen => false,
1071 Self::RightClosedLeftOpen => true,
1072 }
1073 }
1074}
1075
1076#[inline(always)]
1081pub fn compute_left_endpoint_u64<F: DragonboxFloat>(pow5: u64, beta: i32) -> u64 {
1082 let zero_carry = pow5 >> (F::MANTISSA_SIZE as usize + 2);
1083 let mantissa_shift = 64 - F::MANTISSA_SIZE as usize - 1;
1084 (pow5 - zero_carry) >> (mantissa_shift as i32 - beta)
1085}
1086
1087#[inline(always)]
1088pub fn compute_right_endpoint_u64<F: DragonboxFloat>(pow5: u64, beta: i32) -> u64 {
1089 let zero_carry = pow5 >> (F::MANTISSA_SIZE as usize + 1);
1090 let mantissa_shift = 64 - F::MANTISSA_SIZE as usize - 1;
1091 (pow5 + zero_carry) >> (mantissa_shift as i32 - beta)
1092}
1093
1094#[inline(always)]
1096pub fn compute_round_up_u64<F: DragonboxFloat>(pow5: u64, beta: i32) -> u64 {
1097 let shift = 64 - F::MANTISSA_SIZE - 2;
1098 ((pow5 >> (shift - beta)) + 1) / 2
1099}
1100
1101#[inline(always)]
1106pub const fn high(pow5: &(u64, u64)) -> u64 {
1107 pow5.0
1108}
1109
1110#[inline(always)]
1112pub const fn low(pow5: &(u64, u64)) -> u64 {
1113 pow5.1
1114}
1115
1116#[inline(always)]
1118pub const fn rotr32(n: u32, r: u32) -> u32 {
1119 let r = r & 31;
1120 (n >> r) | (n << (32 - r))
1121}
1122
1123#[inline(always)]
1125pub const fn rotr64(n: u64, r: u64) -> u64 {
1126 let r = r & 63;
1127 (n >> r) | (n << (64 - r))
1128}
1129
1130struct Div10Info {
1136 magic_number: u32,
1137 shift_amount: i32,
1138}
1139
1140const F32_DIV10_INFO: Div10Info = Div10Info {
1141 magic_number: 6554,
1142 shift_amount: 16,
1143};
1144
1145const F64_DIV10_INFO: Div10Info = Div10Info {
1146 magic_number: 656,
1147 shift_amount: 16,
1148};
1149
1150macro_rules! check_div_pow10 {
1151 ($n:ident, $exp:literal, $float:ident, $info:ident) => {{
1152 debug_assert!($exp + 2 < floor_log10_pow2(31));
1154 debug_assert!($n as u64 <= pow64(10, $exp + 1));
1155
1156 let n = $n.wrapping_mul($info.magic_number);
1157 let mask = (1u32 << $info.shift_amount) - 1;
1158 let r = (n & mask) < $info.magic_number;
1159
1160 (n >> $info.shift_amount, r)
1161 }};
1162}
1163
1164const MOD_INV_5_U32: u32 = 0xCCCC_CCCD;
1166const MOD_INV_25_U32: u32 = MOD_INV_5_U32.wrapping_mul(MOD_INV_5_U32);
1167const MOD_INV_5_U64: u64 = 0xCCCC_CCCC_CCCC_CCCD;
1168const MOD_INV_25_U64: u64 = MOD_INV_5_U64.wrapping_mul(MOD_INV_5_U64);
1169
1170macro_rules! div_pow10 {
1171 ($n:ident, $info:ident) => {{
1172 $n.wrapping_mul($info.magic_number) >> $info.shift_amount
1173 }};
1174}
1175
1176pub trait DragonboxFloat: Float {
1178 const KAPPA: u32;
1180 const DECIMAL_DIGITS: usize;
1183 const FC_PM_HALF_LOWER: i32 = -(Self::KAPPA as i32) - floor_log5_pow2(Self::KAPPA as i32);
1184 const DIV_BY_5_THRESHOLD: i32 = floor_log2_pow10(Self::KAPPA as i32 + 1);
1185
1186 type Power;
1187
1188 fn digit_count(mantissa: u64) -> usize;
1190
1191 unsafe fn write_digits(bytes: &mut [u8], mantissa: u64) -> usize;
1198
1199 unsafe fn dragonbox_power(exponent: i32) -> Self::Power;
1205
1206 fn compute_left_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64;
1208
1209 fn compute_right_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64;
1211
1212 fn compute_round_up(pow5: &Self::Power, beta_minus_1: i32) -> u64;
1214
1215 fn compute_mul(u: u64, pow5: &Self::Power) -> (u64, bool);
1216 fn compute_mul_parity(two_f: u64, pow5: &Self::Power, beta_minus_1: i32) -> (bool, bool);
1217 fn compute_delta(pow5: &Self::Power, beta_minus_1: i32) -> u32;
1218
1219 fn process_trailing_zeros(mantissa: u64, exponent: i32) -> (u64, i32);
1221
1222 fn remove_trailing_zeros(mantissa: u64) -> (u64, i32);
1224
1225 #[inline(always)]
1227 fn divisible_by_pow2(x: u64, exp: u32) -> bool {
1228 x.trailing_zeros() >= exp
1230 }
1231
1232 fn check_div_pow10(n: u32) -> (u32, bool);
1236
1237 fn div_pow10(n: u32) -> u32;
1240
1241 fn divide_by_pow10(n: u64, exp: u32, n_max: u64) -> u64;
1244}
1245
1246impl DragonboxFloat for f32 {
1247 const KAPPA: u32 = 1;
1248 const DECIMAL_DIGITS: usize = 9;
1249
1250 type Power = u64;
1251
1252 #[inline(always)]
1253 fn digit_count(mantissa: u64) -> usize {
1254 debug_assert!(mantissa <= u32::MAX as u64);
1255 (mantissa as u32).digit_count()
1256 }
1257
1258 #[inline(always)]
1259 unsafe fn write_digits(bytes: &mut [u8], mantissa: u64) -> usize {
1260 debug_assert!(mantissa <= u32::MAX as u64);
1261 unsafe { write_digits_u32(bytes, mantissa as u32) }
1263 }
1264
1265 #[inline(always)]
1266 unsafe fn dragonbox_power(exponent: i32) -> Self::Power {
1267 debug_assert!((SMALLEST_F32_POW5..=LARGEST_F32_POW5).contains(&exponent));
1268 let index = (exponent - SMALLEST_F32_POW5) as usize;
1269 unsafe { index_unchecked!(DRAGONBOX32_POWERS_OF_FIVE[index]) }
1271 }
1272
1273 #[inline(always)]
1274 fn compute_left_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1275 compute_left_endpoint_u64::<Self>(*pow5, beta_minus_1)
1276 }
1277
1278 #[inline(always)]
1279 fn compute_right_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1280 compute_right_endpoint_u64::<Self>(*pow5, beta_minus_1)
1281 }
1282
1283 #[inline(always)]
1284 fn compute_round_up(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1285 compute_round_up_u64::<Self>(*pow5, beta_minus_1)
1286 }
1287
1288 #[inline(always)]
1289 fn compute_mul(u: u64, pow5: &Self::Power) -> (u64, bool) {
1290 let r = umul96_upper64(u, *pow5);
1291 (r >> 32, (r as u32) == 0)
1292 }
1293
1294 #[inline(always)]
1295 fn compute_mul_parity(two_f: u64, pow5: &Self::Power, beta: i32) -> (bool, bool) {
1296 debug_assert!((1..64).contains(&beta));
1297
1298 let r = umul96_lower64(two_f, *pow5);
1299 let parity = (r >> (64 - beta)) & 1;
1300 let is_integer = r >> (32 - beta);
1301 (parity != 0, is_integer == 0)
1302 }
1303
1304 #[inline(always)]
1305 fn compute_delta(pow5: &Self::Power, beta: i32) -> u32 {
1306 (*pow5 >> (64 - 1 - beta)) as u32
1307 }
1308
1309 #[inline(always)]
1310 fn process_trailing_zeros(mantissa: u64, exponent: i32) -> (u64, i32) {
1311 let (mantissa, trailing) = Self::remove_trailing_zeros(mantissa);
1313 (mantissa, exponent + trailing)
1314 }
1315
1316 #[inline(always)]
1317 fn remove_trailing_zeros(mantissa: u64) -> (u64, i32) {
1318 debug_assert!(mantissa <= u32::MAX as u64);
1319 debug_assert!(mantissa != 0);
1320
1321 let mut n = mantissa as u32;
1322 let mut quo: u32;
1323 let mut s: i32 = 0;
1324 loop {
1325 quo = rotr32(n.wrapping_mul(MOD_INV_25_U32), 2);
1326 if quo <= u32::MAX / 100 {
1327 n = quo;
1328 s += 2;
1329 } else {
1330 break;
1331 }
1332 }
1333
1334 quo = rotr32(n.wrapping_mul(MOD_INV_5_U32), 1);
1335 if quo <= u32::MAX / 10 {
1336 n = quo;
1337 s |= 1;
1338 }
1339 (n as u64, s)
1340 }
1341
1342 #[inline(always)]
1343 fn check_div_pow10(n: u32) -> (u32, bool) {
1344 check_div_pow10!(n, 1, f32, F32_DIV10_INFO)
1345 }
1346
1347 #[inline(always)]
1348 fn div_pow10(n: u32) -> u32 {
1349 div_pow10!(n, F32_DIV10_INFO)
1350 }
1351
1352 #[inline(always)]
1353 fn divide_by_pow10(n: u64, exp: u32, _: u64) -> u64 {
1354 divide_by_pow10_32(n as u32, exp) as u64
1355 }
1356}
1357
1358impl DragonboxFloat for f64 {
1359 const KAPPA: u32 = 2;
1360 const DECIMAL_DIGITS: usize = 17;
1361
1362 type Power = (u64, u64);
1363
1364 #[inline(always)]
1365 fn digit_count(mantissa: u64) -> usize {
1366 mantissa.digit_count()
1367 }
1368
1369 #[inline(always)]
1370 unsafe fn write_digits(bytes: &mut [u8], mantissa: u64) -> usize {
1371 unsafe { write_digits_u64(bytes, mantissa) }
1373 }
1374
1375 #[inline(always)]
1376 unsafe fn dragonbox_power(exponent: i32) -> Self::Power {
1377 debug_assert!((SMALLEST_F64_POW5..=LARGEST_F64_POW5).contains(&exponent));
1378 let index = (exponent - SMALLEST_F64_POW5) as usize;
1379 unsafe { index_unchecked!(DRAGONBOX64_POWERS_OF_FIVE[index]) }
1381 }
1382
1383 #[inline(always)]
1384 fn compute_left_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1385 compute_left_endpoint_u64::<Self>(high(pow5), beta_minus_1)
1386 }
1387
1388 #[inline(always)]
1389 fn compute_right_endpoint(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1390 compute_right_endpoint_u64::<Self>(high(pow5), beta_minus_1)
1391 }
1392
1393 #[inline(always)]
1394 fn compute_round_up(pow5: &Self::Power, beta_minus_1: i32) -> u64 {
1395 compute_round_up_u64::<Self>(high(pow5), beta_minus_1)
1396 }
1397
1398 #[inline(always)]
1399 fn compute_mul(u: u64, pow5: &Self::Power) -> (u64, bool) {
1400 let (hi, lo) = umul192_upper128(u, high(pow5), low(pow5));
1401 (hi, lo == 0)
1402 }
1403
1404 #[inline(always)]
1405 fn compute_mul_parity(two_f: u64, pow5: &Self::Power, beta: i32) -> (bool, bool) {
1406 debug_assert!((1..64).contains(&beta));
1407
1408 let (rhi, rlo) = umul192_lower128(two_f, high(pow5), low(pow5));
1409 let parity = (rhi >> (64 - beta)) & 1;
1410 let is_integer = (rhi << beta) | (rlo >> (64 - beta));
1411 (parity != 0, is_integer == 0)
1412 }
1413
1414 #[inline(always)]
1415 fn compute_delta(pow5: &Self::Power, beta: i32) -> u32 {
1416 (high(pow5) >> (64 - 1 - beta)) as u32
1417 }
1418
1419 #[inline(always)]
1420 fn process_trailing_zeros(mantissa: u64, exponent: i32) -> (u64, i32) {
1421 let (mantissa, trailing) = Self::remove_trailing_zeros(mantissa);
1424 (mantissa, exponent + trailing)
1425 }
1426
1427 #[inline(always)]
1428 fn remove_trailing_zeros(mantissa: u64) -> (u64, i32) {
1429 debug_assert!(mantissa != 0);
1430
1431 let magic_number = 12379400392853802749u64;
1433 let nm = mantissa as u128 * magic_number as u128;
1434
1435 let high = (nm >> 64) as u64;
1437 let mask = (1 << (90 - 64)) - 1;
1438 let low = nm as u64;
1439 if high & mask == 0 && low < magic_number {
1440 let mut n = (high >> (90 - 64)) as u32;
1442 let mut s: i32 = 8;
1443 let mut quo: u32;
1444
1445 loop {
1446 quo = rotr32(n.wrapping_mul(MOD_INV_25_U32), 2);
1447 if quo <= u32::MAX / 100 {
1448 n = quo;
1449 s += 2;
1450 } else {
1451 break;
1452 }
1453 }
1454
1455 quo = rotr32(n.wrapping_mul(MOD_INV_5_U32), 1);
1456 if quo <= u32::MAX / 10 {
1457 n = quo;
1458 s |= 1;
1459 }
1460
1461 (n as u64, s)
1462 } else {
1463 let mut n = mantissa;
1465 let mut s: i32 = 0;
1466 let mut quo: u64;
1467
1468 loop {
1469 quo = rotr64(n.wrapping_mul(MOD_INV_25_U64), 2);
1470 if quo <= u64::MAX / 100 {
1471 n = quo;
1472 s += 2;
1473 } else {
1474 break;
1475 }
1476 }
1477
1478 quo = rotr64(n.wrapping_mul(MOD_INV_5_U64), 1);
1479 if quo <= u64::MAX / 10 {
1480 n = quo;
1481 s |= 1;
1482 }
1483
1484 (n, s)
1485 }
1486 }
1487
1488 #[inline(always)]
1489 fn check_div_pow10(n: u32) -> (u32, bool) {
1490 check_div_pow10!(n, 2, f64, F64_DIV10_INFO)
1491 }
1492
1493 #[inline(always)]
1494 fn div_pow10(n: u32) -> u32 {
1495 div_pow10!(n, F64_DIV10_INFO)
1496 }
1497
1498 #[inline(always)]
1499 fn divide_by_pow10(n: u64, exp: u32, n_max: u64) -> u64 {
1500 divide_by_pow10_64(n, exp, n_max)
1501 }
1502}
1503
1504#[cfg(feature = "f16")]
1505macro_rules! dragonbox_unimpl {
1506 ($($t:ident)*) => ($(
1507 impl DragonboxFloat for $t {
1508 const KAPPA: u32 = 0;
1509 const DECIMAL_DIGITS: usize = 0;
1510
1511 type Power = u64;
1512
1513 #[inline(always)]
1514 fn digit_count(_: u64) -> usize {
1515 unimplemented!()
1516 }
1517
1518 #[inline(always)]
1519 unsafe fn write_digits(_: &mut [u8], _: u64) -> usize {
1520 unimplemented!()
1521 }
1522
1523 #[inline(always)]
1524 unsafe fn dragonbox_power(_: i32) -> Self::Power {
1525 unimplemented!()
1526 }
1527
1528 #[inline(always)]
1529 fn compute_left_endpoint(_: &Self::Power, _: i32) -> u64 {
1530 unimplemented!()
1531 }
1532
1533 #[inline(always)]
1534 fn compute_right_endpoint(_: &Self::Power, _: i32) -> u64 {
1535 unimplemented!()
1536 }
1537
1538 #[inline(always)]
1539 fn compute_round_up(_: &Self::Power, _: i32) -> (u64, bool) {
1540 unimplemented!()
1541 }
1542
1543 #[inline(always)]
1544 fn compute_mul(_: u64, _: &Self::Power) -> (u64, bool) {
1545 unimplemented!()
1546 }
1547
1548 #[inline(always)]
1549 fn compute_mul_parity(_: u64, _: &Self::Power, _: i32) -> (bool, bool) {
1550 unimplemented!()
1551 }
1552
1553 #[inline(always)]
1554 fn compute_delta(_: &Self::Power, _: i32) -> u32 {
1555 unimplemented!()
1556 }
1557
1558 #[inline(always)]
1559 fn process_trailing_zeros(_: u64, _: i32) -> (u64, i32) {
1560 unimplemented!()
1561 }
1562
1563 #[inline(always)]
1564 fn remove_trailing_zeros(_: u64) -> (u64, i32) {
1565 unimplemented!()
1566 }
1567
1568 #[inline(always)]
1569 fn check_div_pow10(_: u32) -> (u32, bool) {
1570 unimplemented!()
1571 }
1572
1573 #[inline(always)]
1574 fn div_pow10(_: u32) -> u32 {
1575 unimplemented!()
1576 }
1577 }
1578 )*);
1579}
1580
1581#[cfg(feature = "f16")]
1582dragonbox_unimpl! { bf16 f16 }