1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use util::diyfp::{ self, DiyFp };
#[inline]
unsafe fn grisu_round(buffer: &mut u64, delta: u64, mut rest: u64, ten_kappa: u64, wp_w: u64) {
while rest < wp_w && delta - rest >= ten_kappa &&
(rest + ten_kappa < wp_w ||
wp_w - rest > rest + ten_kappa - wp_w) {
*buffer -= 1;
rest += ten_kappa;
}
}
#[inline]
fn count_decimal_digit32(n: u32) -> i16 {
if n < 10 { 1 }
else if n < 100 { 2 }
else if n < 1000 { 3 }
else if n < 10000 { 4 }
else if n < 100000 { 5 }
else if n < 1000000 { 6 }
else if n < 10000000 { 7 }
else if n < 100000000 { 8 }
else { 9 }
}
#[inline]
unsafe fn digit_gen(w: DiyFp, mp: DiyFp, mut delta: u64, mut k: i16) -> (u64, i16) {
static POW10: [u32; 10] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ];
let one = DiyFp::new(1u64 << -mp.e, mp.e);
let wp_w = mp - w;
let mut p1 = (mp.f >> -one.e) as u32;
let mut p2 = mp.f & (one.f - 1);
let mut kappa = count_decimal_digit32(p1);
let mut buffer = p1 as u64;
while kappa > 0 {
match kappa {
9 => { p1 %= 100000000; }
8 => { p1 %= 10000000; }
7 => { p1 %= 1000000; }
6 => { p1 %= 100000; }
5 => { p1 %= 10000; }
4 => { p1 %= 1000; }
3 => { p1 %= 100; }
2 => { p1 %= 10; }
1 => { p1 = 0; }
_ => {}
}
kappa = kappa.wrapping_sub(1);
let tmp = ((p1 as u64) << -one.e) + p2;
if tmp <= delta {
k += kappa;
let pow10 = POW10[kappa as usize] as u64;
buffer /= pow10;
grisu_round(&mut buffer, delta, tmp, pow10 << -one.e, wp_w.f);
return (buffer, k);
}
}
loop {
p2 *= 10;
delta *= 10;
let d = (p2 >> -one.e) as u8;
if d != 0 || buffer != 0 {
buffer = buffer * 10 + d as u64;
}
p2 &= one.f - 1;
kappa = kappa.wrapping_sub(1);
if p2 < delta {
k += kappa;
let index = -(kappa as isize);
grisu_round(&mut buffer, delta, p2, one.f, wp_w.f * if index < 9 { POW10[-(kappa as isize) as usize] as u64 } else { 0 });
return (buffer, k);
}
}
}
#[inline]
pub fn convert(float: f64) -> (u64, i16) {
if float == 0.0 {
return (0, 0);
}
unsafe {
let v = DiyFp::from_f64(float);
let (w_m, w_p) = v.normalized_boundaries();
let (c_mk, k) = diyfp::get_cached_power(w_p.e);
let w = v.normalize() * c_mk;
let mut wp = w_p * c_mk;
let mut wm = w_m * c_mk;
wm.f += 1;
wp.f -= 1;
digit_gen(w, wp, wp.f - wm.f, k as i16)
}
}