1use core::{mem, ptr};
22
23use common::*;
24#[cfg(not(feature = "small"))]
25use d2s_full_table::*;
26#[cfg(feature = "small")]
27use d2s_small_table::*;
28use digit_table::*;
29use d2s_intrinsics::*;
30
31#[cfg(feature = "no-panic")]
32use no_panic::no_panic;
33
34pub const DOUBLE_MANTISSA_BITS: u32 = 52;
35pub const DOUBLE_EXPONENT_BITS: u32 = 11;
36
37const DOUBLE_POW5_INV_BITCOUNT: i32 = 122;
38const DOUBLE_POW5_BITCOUNT: i32 = 121;
39
40#[cfg_attr(feature = "no-panic", inline)]
41fn pow5_factor(mut value: u64) -> u32 {
42 let mut count = 0u32;
43 loop {
44 debug_assert!(value != 0);
45 let q = div5(value);
46 let r = (value - 5 * q) as u32;
47 if r != 0 {
48 break;
49 }
50 value = q;
51 count += 1;
52 }
53 count
54}
55
56#[cfg_attr(feature = "no-panic", inline)]
58fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
59 pow5_factor(value) >= p
61}
62
63#[cfg_attr(feature = "no-panic", inline)]
65fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
66 (value & ((1u64 << p) - 1)) == 0
68}
69
70#[cfg(integer128)]
71#[cfg_attr(feature = "no-panic", inline)]
72fn mul_shift(m: u64, mul: &(u64, u64), j: u32) -> u64 {
73 let b0 = m as u128 * mul.0 as u128;
74 let b2 = m as u128 * mul.1 as u128;
75 (((b0 >> 64) + b2) >> (j - 64)) as u64
76}
77
78#[cfg(integer128)]
79#[cfg_attr(feature = "no-panic", inline)]
80fn mul_shift_all(
81 m: u64,
82 mul: &(u64, u64),
83 j: u32,
84 vp: &mut u64,
85 vm: &mut u64,
86 mm_shift: u32,
87) -> u64 {
88 *vp = mul_shift(4 * m + 2, mul, j);
89 *vm = mul_shift(4 * m - 1 - mm_shift as u64, mul, j);
90 mul_shift(4 * m, mul, j)
91}
92
93#[cfg(not(integer128))]
94#[cfg_attr(feature = "no-panic", inline)]
95fn mul_shift_all(
96 mut m: u64,
97 mul: &(u64, u64),
98 j: u32,
99 vp: &mut u64,
100 vm: &mut u64,
101 mm_shift: u32,
102) -> u64 {
103 m <<= 1;
104 let (lo, tmp) = umul128(m, mul.0);
106 let (mut mid, mut hi) = umul128(m, mul.1);
107 mid = mid.wrapping_add(tmp);
108 hi = hi.wrapping_add((mid < tmp) as u64); let lo2 = lo.wrapping_add(mul.0);
111 let mid2 = mid.wrapping_add(mul.1).wrapping_add((lo2 < lo) as u64);
112 let hi2 = hi.wrapping_add((mid2 < mid) as u64);
113 *vp = shiftright128(mid2, hi2, j - 64 - 1);
114
115 if mm_shift == 1 {
116 let lo3 = lo.wrapping_sub(mul.0);
117 let mid3 = mid.wrapping_sub(mul.1).wrapping_sub((lo3 > lo) as u64);
118 let hi3 = hi.wrapping_sub((mid3 > mid) as u64);
119 *vm = shiftright128(mid3, hi3, j - 64 - 1);
120 } else {
121 let lo3 = lo + lo;
122 let mid3 = mid.wrapping_add(mid).wrapping_add((lo3 < lo) as u64);
123 let hi3 = hi.wrapping_add(hi).wrapping_add((mid3 < mid) as u64);
124 let lo4 = lo3.wrapping_sub(mul.0);
125 let mid4 = mid3.wrapping_sub(mul.1).wrapping_sub((lo4 > lo3) as u64);
126 let hi4 = hi3.wrapping_sub((mid4 > mid3) as u64);
127 *vm = shiftright128(mid4, hi4, j - 64);
128 }
129
130 shiftright128(mid, hi, j - 64 - 1)
131}
132
133#[cfg_attr(feature = "no-panic", inline)]
134pub fn decimal_length(v: u64) -> u32 {
135 debug_assert!(v < 100000000000000000);
140
141 if v >= 10000000000000000 {
142 17
143 } else if v >= 1000000000000000 {
144 16
145 } else if v >= 100000000000000 {
146 15
147 } else if v >= 10000000000000 {
148 14
149 } else if v >= 1000000000000 {
150 13
151 } else if v >= 100000000000 {
152 12
153 } else if v >= 10000000000 {
154 11
155 } else if v >= 1000000000 {
156 10
157 } else if v >= 100000000 {
158 9
159 } else if v >= 10000000 {
160 8
161 } else if v >= 1000000 {
162 7
163 } else if v >= 100000 {
164 6
165 } else if v >= 10000 {
166 5
167 } else if v >= 1000 {
168 4
169 } else if v >= 100 {
170 3
171 } else if v >= 10 {
172 2
173 } else {
174 1
175 }
176}
177
178pub struct FloatingDecimal64 {
180 pub mantissa: u64,
181 pub exponent: i32,
182}
183
184#[cfg_attr(feature = "no-panic", inline)]
185pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
186 let bias = (1u32 << (DOUBLE_EXPONENT_BITS - 1)) - 1;
187
188 let (e2, m2) = if ieee_exponent == 0 {
189 (
190 1 - bias as i32 - DOUBLE_MANTISSA_BITS as i32 - 2,
192 ieee_mantissa,
193 )
194 } else {
195 (
196 ieee_exponent as i32 - bias as i32 - DOUBLE_MANTISSA_BITS as i32 - 2,
197 (1u64 << DOUBLE_MANTISSA_BITS) | ieee_mantissa,
198 )
199 };
200 let even = (m2 & 1) == 0;
201 let accept_bounds = even;
202
203 let mv = 4 * m2;
205 let mm_shift = (ieee_mantissa != 0 || ieee_exponent <= 1) as u32;
207 let mut vr: u64;
213 let mut vp: u64 = unsafe { mem::uninitialized() };
214 let mut vm: u64 = unsafe { mem::uninitialized() };
215 let e10: i32;
216 let mut vm_is_trailing_zeros = false;
217 let mut vr_is_trailing_zeros = false;
218 if e2 >= 0 {
219 let q = (log10_pow2(e2) - (e2 > 3) as i32) as u32;
222 e10 = q as i32;
223 let k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q as i32) as i32 - 1;
224 let i = -e2 + q as i32 + k;
225 vr = mul_shift_all(
226 m2,
227 #[cfg(feature = "small")]
228 unsafe {
229 &compute_inv_pow5(q)
230 },
231 #[cfg(not(feature = "small"))]
232 unsafe {
233 debug_assert!(q < DOUBLE_POW5_INV_SPLIT.len() as u32);
234 DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
235 },
236 i as u32,
237 &mut vp,
238 &mut vm,
239 mm_shift,
240 );
241 if q <= 21 {
242 let mv_mod5 = (mv - 5 * div5(mv)) as u32;
246 if mv_mod5 == 0 {
247 vr_is_trailing_zeros = multiple_of_power_of_5(mv, q);
248 } else if accept_bounds {
249 vm_is_trailing_zeros = multiple_of_power_of_5(mv - 1 - mm_shift as u64, q);
253 } else {
254 vp -= multiple_of_power_of_5(mv + 2, q) as u64;
256 }
257 }
258 } else {
259 let q = (log10_pow5(-e2) - (-e2 > 1) as i32) as u32;
261 e10 = q as i32 + e2;
262 let i = -e2 - q as i32;
263 let k = pow5bits(i) as i32 - DOUBLE_POW5_BITCOUNT;
264 let j = q as i32 - k;
265 vr = mul_shift_all(
266 m2,
267 #[cfg(feature = "small")]
268 unsafe {
269 &compute_pow5(i as u32)
270 },
271 #[cfg(not(feature = "small"))]
272 unsafe {
273 debug_assert!(i < DOUBLE_POW5_SPLIT.len() as i32);
274 DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
275 },
276 j as u32,
277 &mut vp,
278 &mut vm,
279 mm_shift,
280 );
281 if q <= 1 {
282 vr_is_trailing_zeros = true;
285 if accept_bounds {
286 vm_is_trailing_zeros = mm_shift == 1;
288 } else {
289 vp -= 1;
291 }
292 } else if q < 63 {
293 vr_is_trailing_zeros = multiple_of_power_of_2(mv, q - 1);
300 }
301 }
302
303 let mut removed = 0u32;
305 let mut last_removed_digit = 0u8;
306 let output = if vm_is_trailing_zeros || vr_is_trailing_zeros {
308 loop {
310 let vp_div10 = div10(vp);
311 let vm_div10 = div10(vm);
312 if vp_div10 <= vm_div10 {
313 break;
314 }
315 let vm_mod10 = (vm - 10 * vm_div10) as u32;
316 let vr_div10 = div10(vr);
317 let vr_mod10 = (vr - 10 * vr_div10) as u32;
318 vm_is_trailing_zeros &= vm_mod10 == 0;
319 vr_is_trailing_zeros &= last_removed_digit == 0;
320 last_removed_digit = vr_mod10 as u8;
321 vr = vr_div10;
322 vp = vp_div10;
323 vm = vm_div10;
324 removed += 1;
325 }
326 if vm_is_trailing_zeros {
327 loop {
328 let vm_div10 = div10(vm);
329 let vm_mod10 = (vm - 10 * vm_div10) as u32;
330 if vm_mod10 != 0 {
331 break;
332 }
333 let vp_div10 = div10(vp);
334 let vr_div10 = div10(vr);
335 let vr_mod10 = (vr - 10 * vr_div10) as u32;
336 vr_is_trailing_zeros &= last_removed_digit == 0;
337 last_removed_digit = vr_mod10 as u8;
338 vr = vr_div10;
339 vp = vp_div10;
340 vm = vm_div10;
341 removed += 1;
342 }
343 }
344 if vr_is_trailing_zeros && last_removed_digit == 5 && vr % 2 == 0 {
345 last_removed_digit = 4;
347 }
348 vr + ((vr == vm && (!accept_bounds || !vm_is_trailing_zeros)) || last_removed_digit >= 5)
350 as u64
351 } else {
352 let mut round_up = false;
354 let vp_div100 = div100(vp);
355 let vm_div100 = div100(vm);
356 if vp_div100 > vm_div100 {
358 let vr_div100 = div100(vr);
359 let vr_mod100 = (vr - 100 * vr_div100) as u32;
360 round_up = vr_mod100 >= 50;
361 vr = vr_div100;
362 vp = vp_div100;
363 vm = vm_div100;
364 removed += 2;
365 }
366 loop {
371 let vp_div10 = div10(vp);
372 let vm_div10 = div10(vm);
373 if vp_div10 <= vm_div10 {
374 break;
375 }
376 let vr_div10 = div10(vr);
377 let vr_mod10 = (vr - 10 * vr_div10) as u32;
378 round_up = vr_mod10 >= 5;
379 vr = vr_div10;
380 vp = vp_div10;
381 vm = vm_div10;
382 removed += 1;
383 }
384 vr + (vr == vm || round_up) as u64
386 };
387 let exp = e10 + removed as i32;
388
389 FloatingDecimal64 {
390 exponent: exp,
391 mantissa: output,
392 }
393}
394
395#[cfg_attr(feature = "no-panic", inline)]
396unsafe fn to_chars(v: FloatingDecimal64, sign: bool, result: *mut u8) -> usize {
397 let mut index = 0isize;
399 if sign {
400 *result.offset(index) = b'-';
401 index += 1;
402 }
403
404 let mut output = v.mantissa;
405 let olength = decimal_length(output);
406
407 let mut i = 0isize;
416 if (output >> 32) != 0 {
421 let q = div100_000_000(output);
423 let mut output2 = (output - 100_000_000 * q) as u32;
424 output = q;
425
426 let c = output2 % 10000;
427 output2 /= 10000;
428 let d = output2 % 10000;
429 let c0 = (c % 100) << 1;
430 let c1 = (c / 100) << 1;
431 let d0 = (d % 100) << 1;
432 let d1 = (d / 100) << 1;
433 ptr::copy_nonoverlapping(
434 DIGIT_TABLE.get_unchecked(c0 as usize),
435 result.offset(index + olength as isize - i - 1),
436 2,
437 );
438 ptr::copy_nonoverlapping(
439 DIGIT_TABLE.get_unchecked(c1 as usize),
440 result.offset(index + olength as isize - i - 3),
441 2,
442 );
443 ptr::copy_nonoverlapping(
444 DIGIT_TABLE.get_unchecked(d0 as usize),
445 result.offset(index + olength as isize - i - 5),
446 2,
447 );
448 ptr::copy_nonoverlapping(
449 DIGIT_TABLE.get_unchecked(d1 as usize),
450 result.offset(index + olength as isize - i - 7),
451 2,
452 );
453 i += 8;
454 }
455 let mut output2 = output as u32;
456 while output2 >= 10000 {
457 let c = (output2 - 10000 * (output2 / 10000)) as u32;
458 output2 /= 10000;
459 let c0 = (c % 100) << 1;
460 let c1 = (c / 100) << 1;
461 ptr::copy_nonoverlapping(
462 DIGIT_TABLE.get_unchecked(c0 as usize),
463 result.offset(index + olength as isize - i - 1),
464 2,
465 );
466 ptr::copy_nonoverlapping(
467 DIGIT_TABLE.get_unchecked(c1 as usize),
468 result.offset(index + olength as isize - i - 3),
469 2,
470 );
471 i += 4;
472 }
473 if output2 >= 100 {
474 let c = ((output2 % 100) << 1) as u32;
475 output2 /= 100;
476 ptr::copy_nonoverlapping(
477 DIGIT_TABLE.get_unchecked(c as usize),
478 result.offset(index + olength as isize - i - 1),
479 2,
480 );
481 i += 2;
482 }
483 if output2 >= 10 {
484 let c = (output2 << 1) as u32;
485 *result.offset(index + olength as isize - i) = *DIGIT_TABLE.get_unchecked(c as usize + 1);
487 *result.offset(index) = *DIGIT_TABLE.get_unchecked(c as usize);
488 } else {
489 *result.offset(index) = b'0' + output2 as u8;
490 }
491
492 if olength > 1 {
494 *result.offset(index + 1) = b'.';
495 index += olength as isize + 1;
496 } else {
497 index += 1;
498 }
499
500 *result.offset(index) = b'E';
502 index += 1;
503 let mut exp = v.exponent as i32 + olength as i32 - 1;
504 if exp < 0 {
505 *result.offset(index) = b'-';
506 index += 1;
507 exp = -exp;
508 }
509
510 if exp >= 100 {
511 let c = exp % 10;
512 ptr::copy_nonoverlapping(
513 DIGIT_TABLE.get_unchecked((2 * (exp / 10)) as usize),
514 result.offset(index),
515 2,
516 );
517 *result.offset(index + 2) = b'0' + c as u8;
518 index += 3;
519 } else if exp >= 10 {
520 ptr::copy_nonoverlapping(
521 DIGIT_TABLE.get_unchecked((2 * exp) as usize),
522 result.offset(index),
523 2,
524 );
525 index += 2;
526 } else {
527 *result.offset(index) = b'0' + exp as u8;
528 index += 1;
529 }
530
531 debug_assert!(index <= 24);
532 index as usize
533}
534
535#[cfg_attr(must_use_return, must_use)]
562#[cfg_attr(feature = "no-panic", no_panic)]
563pub unsafe fn d2s_buffered_n(f: f64, result: *mut u8) -> usize {
564 let bits = mem::transmute::<f64, u64>(f);
566
567 let ieee_sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
569 let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
570 let ieee_exponent =
571 (bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1);
572 if ieee_exponent == ((1u32 << DOUBLE_EXPONENT_BITS) - 1)
574 || (ieee_exponent == 0 && ieee_mantissa == 0)
575 {
576 return copy_special_str(result, ieee_sign, ieee_exponent != 0, ieee_mantissa != 0);
577 }
578
579 let v = d2d(ieee_mantissa, ieee_exponent);
580 to_chars(v, ieee_sign, result)
581}