/rust/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.19/src/pretty/mod.rs
Line | Count | Source (jump to first uncovered line) |
1 | | mod exponent; |
2 | | mod mantissa; |
3 | | |
4 | | use self::exponent::{write_exponent2, write_exponent3}; |
5 | | use self::mantissa::{write_mantissa, write_mantissa_long}; |
6 | | use crate::common; |
7 | | use crate::d2s::{self, d2d, DOUBLE_EXPONENT_BITS, DOUBLE_MANTISSA_BITS}; |
8 | | use crate::f2s::{f2d, FLOAT_EXPONENT_BITS, FLOAT_MANTISSA_BITS}; |
9 | | use core::ptr; |
10 | | #[cfg(feature = "no-panic")] |
11 | | use no_panic::no_panic; |
12 | | |
13 | | /// Print f64 to the given buffer and return number of bytes written. |
14 | | /// |
15 | | /// At most 24 bytes will be written. |
16 | | /// |
17 | | /// ## Special cases |
18 | | /// |
19 | | /// This function **does not** check for NaN or infinity. If the input |
20 | | /// number is not a finite float, the printed representation will be some |
21 | | /// correctly formatted but unspecified numerical value. |
22 | | /// |
23 | | /// Please check [`is_finite`] yourself before calling this function, or |
24 | | /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself. |
25 | | /// |
26 | | /// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite |
27 | | /// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan |
28 | | /// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite |
29 | | /// |
30 | | /// ## Safety |
31 | | /// |
32 | | /// The `result` pointer argument must point to sufficiently many writable bytes |
33 | | /// to hold Ryū's representation of `f`. |
34 | | /// |
35 | | /// ## Example |
36 | | /// |
37 | | /// ``` |
38 | | /// use std::{mem::MaybeUninit, slice, str}; |
39 | | /// |
40 | | /// let f = 1.234f64; |
41 | | /// |
42 | | /// unsafe { |
43 | | /// let mut buffer = [MaybeUninit::<u8>::uninit(); 24]; |
44 | | /// let len = ryu::raw::format64(f, buffer.as_mut_ptr() as *mut u8); |
45 | | /// let slice = slice::from_raw_parts(buffer.as_ptr() as *const u8, len); |
46 | | /// let print = str::from_utf8_unchecked(slice); |
47 | | /// assert_eq!(print, "1.234"); |
48 | | /// } |
49 | | /// ``` |
50 | | #[must_use] |
51 | | #[cfg_attr(feature = "no-panic", no_panic)] |
52 | 0 | pub unsafe fn format64(f: f64, result: *mut u8) -> usize { |
53 | 0 | let bits = f.to_bits(); |
54 | 0 | let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0; |
55 | 0 | let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1); |
56 | 0 | let ieee_exponent = |
57 | 0 | (bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1); |
58 | 0 |
|
59 | 0 | let mut index = 0isize; |
60 | 0 | if sign { |
61 | 0 | *result = b'-'; |
62 | 0 | index += 1; |
63 | 0 | } |
64 | | |
65 | 0 | if ieee_exponent == 0 && ieee_mantissa == 0 { |
66 | 0 | ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3); |
67 | 0 | return sign as usize + 3; |
68 | 0 | } |
69 | 0 |
|
70 | 0 | let v = d2d(ieee_mantissa, ieee_exponent); |
71 | 0 |
|
72 | 0 | let length = d2s::decimal_length17(v.mantissa) as isize; |
73 | 0 | let k = v.exponent as isize; |
74 | 0 | let kk = length + k; // 10^(kk-1) <= v < 10^kk |
75 | 0 | debug_assert!(k >= -324); |
76 | | |
77 | 0 | if 0 <= k && kk <= 16 { |
78 | | // 1234e7 -> 12340000000.0 |
79 | 0 | write_mantissa_long(v.mantissa, result.offset(index + length)); |
80 | 0 | for i in length..kk { |
81 | 0 | *result.offset(index + i) = b'0'; |
82 | 0 | } |
83 | 0 | *result.offset(index + kk) = b'.'; |
84 | 0 | *result.offset(index + kk + 1) = b'0'; |
85 | 0 | index as usize + kk as usize + 2 |
86 | 0 | } else if 0 < kk && kk <= 16 { |
87 | | // 1234e-2 -> 12.34 |
88 | 0 | write_mantissa_long(v.mantissa, result.offset(index + length + 1)); |
89 | 0 | ptr::copy(result.offset(index + 1), result.offset(index), kk as usize); |
90 | 0 | *result.offset(index + kk) = b'.'; |
91 | 0 | index as usize + length as usize + 1 |
92 | 0 | } else if -5 < kk && kk <= 0 { |
93 | | // 1234e-6 -> 0.001234 |
94 | 0 | *result.offset(index) = b'0'; |
95 | 0 | *result.offset(index + 1) = b'.'; |
96 | 0 | let offset = 2 - kk; |
97 | 0 | for i in 2..offset { |
98 | 0 | *result.offset(index + i) = b'0'; |
99 | 0 | } |
100 | 0 | write_mantissa_long(v.mantissa, result.offset(index + length + offset)); |
101 | 0 | index as usize + length as usize + offset as usize |
102 | 0 | } else if length == 1 { |
103 | | // 1e30 |
104 | 0 | *result.offset(index) = b'0' + v.mantissa as u8; |
105 | 0 | *result.offset(index + 1) = b'e'; |
106 | 0 | index as usize + 2 + write_exponent3(kk - 1, result.offset(index + 2)) |
107 | | } else { |
108 | | // 1234e30 -> 1.234e33 |
109 | 0 | write_mantissa_long(v.mantissa, result.offset(index + length + 1)); |
110 | 0 | *result.offset(index) = *result.offset(index + 1); |
111 | 0 | *result.offset(index + 1) = b'.'; |
112 | 0 | *result.offset(index + length + 1) = b'e'; |
113 | 0 | index as usize |
114 | 0 | + length as usize |
115 | 0 | + 2 |
116 | 0 | + write_exponent3(kk - 1, result.offset(index + length + 2)) |
117 | | } |
118 | 0 | } |
119 | | |
120 | | /// Print f32 to the given buffer and return number of bytes written. |
121 | | /// |
122 | | /// At most 16 bytes will be written. |
123 | | /// |
124 | | /// ## Special cases |
125 | | /// |
126 | | /// This function **does not** check for NaN or infinity. If the input |
127 | | /// number is not a finite float, the printed representation will be some |
128 | | /// correctly formatted but unspecified numerical value. |
129 | | /// |
130 | | /// Please check [`is_finite`] yourself before calling this function, or |
131 | | /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself. |
132 | | /// |
133 | | /// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_finite |
134 | | /// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_nan |
135 | | /// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_infinite |
136 | | /// |
137 | | /// ## Safety |
138 | | /// |
139 | | /// The `result` pointer argument must point to sufficiently many writable bytes |
140 | | /// to hold Ryū's representation of `f`. |
141 | | /// |
142 | | /// ## Example |
143 | | /// |
144 | | /// ``` |
145 | | /// use std::{mem::MaybeUninit, slice, str}; |
146 | | /// |
147 | | /// let f = 1.234f32; |
148 | | /// |
149 | | /// unsafe { |
150 | | /// let mut buffer = [MaybeUninit::<u8>::uninit(); 16]; |
151 | | /// let len = ryu::raw::format32(f, buffer.as_mut_ptr() as *mut u8); |
152 | | /// let slice = slice::from_raw_parts(buffer.as_ptr() as *const u8, len); |
153 | | /// let print = str::from_utf8_unchecked(slice); |
154 | | /// assert_eq!(print, "1.234"); |
155 | | /// } |
156 | | /// ``` |
157 | | #[must_use] |
158 | | #[cfg_attr(feature = "no-panic", no_panic)] |
159 | 0 | pub unsafe fn format32(f: f32, result: *mut u8) -> usize { |
160 | 0 | let bits = f.to_bits(); |
161 | 0 | let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0; |
162 | 0 | let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1); |
163 | 0 | let ieee_exponent = (bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1); |
164 | 0 |
|
165 | 0 | let mut index = 0isize; |
166 | 0 | if sign { |
167 | 0 | *result = b'-'; |
168 | 0 | index += 1; |
169 | 0 | } |
170 | | |
171 | 0 | if ieee_exponent == 0 && ieee_mantissa == 0 { |
172 | 0 | ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3); |
173 | 0 | return sign as usize + 3; |
174 | 0 | } |
175 | 0 |
|
176 | 0 | let v = f2d(ieee_mantissa, ieee_exponent); |
177 | 0 |
|
178 | 0 | let length = common::decimal_length9(v.mantissa) as isize; |
179 | 0 | let k = v.exponent as isize; |
180 | 0 | let kk = length + k; // 10^(kk-1) <= v < 10^kk |
181 | 0 | debug_assert!(k >= -45); |
182 | | |
183 | 0 | if 0 <= k && kk <= 13 { |
184 | | // 1234e7 -> 12340000000.0 |
185 | 0 | write_mantissa(v.mantissa, result.offset(index + length)); |
186 | 0 | for i in length..kk { |
187 | 0 | *result.offset(index + i) = b'0'; |
188 | 0 | } |
189 | 0 | *result.offset(index + kk) = b'.'; |
190 | 0 | *result.offset(index + kk + 1) = b'0'; |
191 | 0 | index as usize + kk as usize + 2 |
192 | 0 | } else if 0 < kk && kk <= 13 { |
193 | | // 1234e-2 -> 12.34 |
194 | 0 | write_mantissa(v.mantissa, result.offset(index + length + 1)); |
195 | 0 | ptr::copy(result.offset(index + 1), result.offset(index), kk as usize); |
196 | 0 | *result.offset(index + kk) = b'.'; |
197 | 0 | index as usize + length as usize + 1 |
198 | 0 | } else if -6 < kk && kk <= 0 { |
199 | | // 1234e-6 -> 0.001234 |
200 | 0 | *result.offset(index) = b'0'; |
201 | 0 | *result.offset(index + 1) = b'.'; |
202 | 0 | let offset = 2 - kk; |
203 | 0 | for i in 2..offset { |
204 | 0 | *result.offset(index + i) = b'0'; |
205 | 0 | } |
206 | 0 | write_mantissa(v.mantissa, result.offset(index + length + offset)); |
207 | 0 | index as usize + length as usize + offset as usize |
208 | 0 | } else if length == 1 { |
209 | | // 1e30 |
210 | 0 | *result.offset(index) = b'0' + v.mantissa as u8; |
211 | 0 | *result.offset(index + 1) = b'e'; |
212 | 0 | index as usize + 2 + write_exponent2(kk - 1, result.offset(index + 2)) |
213 | | } else { |
214 | | // 1234e30 -> 1.234e33 |
215 | 0 | write_mantissa(v.mantissa, result.offset(index + length + 1)); |
216 | 0 | *result.offset(index) = *result.offset(index + 1); |
217 | 0 | *result.offset(index + 1) = b'.'; |
218 | 0 | *result.offset(index + length + 1) = b'e'; |
219 | 0 | index as usize |
220 | 0 | + length as usize |
221 | 0 | + 2 |
222 | 0 | + write_exponent2(kk - 1, result.offset(index + length + 2)) |
223 | | } |
224 | 0 | } |