xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/ryu-1.0.17/src/pretty/mod.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)]
format64(f: f64, result: *mut u8) -> usize52 pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
53     let bits = f.to_bits();
54     let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
55     let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
56     let ieee_exponent =
57         (bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1);
58 
59     let mut index = 0isize;
60     if sign {
61         *result = b'-';
62         index += 1;
63     }
64 
65     if ieee_exponent == 0 && ieee_mantissa == 0 {
66         ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
67         return sign as usize + 3;
68     }
69 
70     let v = d2d(ieee_mantissa, ieee_exponent);
71 
72     let length = d2s::decimal_length17(v.mantissa) as isize;
73     let k = v.exponent as isize;
74     let kk = length + k; // 10^(kk-1) <= v < 10^kk
75     debug_assert!(k >= -324);
76 
77     if 0 <= k && kk <= 16 {
78         // 1234e7 -> 12340000000.0
79         write_mantissa_long(v.mantissa, result.offset(index + length));
80         for i in length..kk {
81             *result.offset(index + i) = b'0';
82         }
83         *result.offset(index + kk) = b'.';
84         *result.offset(index + kk + 1) = b'0';
85         index as usize + kk as usize + 2
86     } else if 0 < kk && kk <= 16 {
87         // 1234e-2 -> 12.34
88         write_mantissa_long(v.mantissa, result.offset(index + length + 1));
89         ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
90         *result.offset(index + kk) = b'.';
91         index as usize + length as usize + 1
92     } else if -5 < kk && kk <= 0 {
93         // 1234e-6 -> 0.001234
94         *result.offset(index) = b'0';
95         *result.offset(index + 1) = b'.';
96         let offset = 2 - kk;
97         for i in 2..offset {
98             *result.offset(index + i) = b'0';
99         }
100         write_mantissa_long(v.mantissa, result.offset(index + length + offset));
101         index as usize + length as usize + offset as usize
102     } else if length == 1 {
103         // 1e30
104         *result.offset(index) = b'0' + v.mantissa as u8;
105         *result.offset(index + 1) = b'e';
106         index as usize + 2 + write_exponent3(kk - 1, result.offset(index + 2))
107     } else {
108         // 1234e30 -> 1.234e33
109         write_mantissa_long(v.mantissa, result.offset(index + length + 1));
110         *result.offset(index) = *result.offset(index + 1);
111         *result.offset(index + 1) = b'.';
112         *result.offset(index + length + 1) = b'e';
113         index as usize
114             + length as usize
115             + 2
116             + write_exponent3(kk - 1, result.offset(index + length + 2))
117     }
118 }
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)]
format32(f: f32, result: *mut u8) -> usize159 pub unsafe fn format32(f: f32, result: *mut u8) -> usize {
160     let bits = f.to_bits();
161     let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
162     let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
163     let ieee_exponent = (bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1);
164 
165     let mut index = 0isize;
166     if sign {
167         *result = b'-';
168         index += 1;
169     }
170 
171     if ieee_exponent == 0 && ieee_mantissa == 0 {
172         ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
173         return sign as usize + 3;
174     }
175 
176     let v = f2d(ieee_mantissa, ieee_exponent);
177 
178     let length = common::decimal_length9(v.mantissa) as isize;
179     let k = v.exponent as isize;
180     let kk = length + k; // 10^(kk-1) <= v < 10^kk
181     debug_assert!(k >= -45);
182 
183     if 0 <= k && kk <= 13 {
184         // 1234e7 -> 12340000000.0
185         write_mantissa(v.mantissa, result.offset(index + length));
186         for i in length..kk {
187             *result.offset(index + i) = b'0';
188         }
189         *result.offset(index + kk) = b'.';
190         *result.offset(index + kk + 1) = b'0';
191         index as usize + kk as usize + 2
192     } else if 0 < kk && kk <= 13 {
193         // 1234e-2 -> 12.34
194         write_mantissa(v.mantissa, result.offset(index + length + 1));
195         ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
196         *result.offset(index + kk) = b'.';
197         index as usize + length as usize + 1
198     } else if -6 < kk && kk <= 0 {
199         // 1234e-6 -> 0.001234
200         *result.offset(index) = b'0';
201         *result.offset(index + 1) = b'.';
202         let offset = 2 - kk;
203         for i in 2..offset {
204             *result.offset(index + i) = b'0';
205         }
206         write_mantissa(v.mantissa, result.offset(index + length + offset));
207         index as usize + length as usize + offset as usize
208     } else if length == 1 {
209         // 1e30
210         *result.offset(index) = b'0' + v.mantissa as u8;
211         *result.offset(index + 1) = b'e';
212         index as usize + 2 + write_exponent2(kk - 1, result.offset(index + 2))
213     } else {
214         // 1234e30 -> 1.234e33
215         write_mantissa(v.mantissa, result.offset(index + length + 1));
216         *result.offset(index) = *result.offset(index + 1);
217         *result.offset(index + 1) = b'.';
218         *result.offset(index + length + 1) = b'e';
219         index as usize
220             + length as usize
221             + 2
222             + write_exponent2(kk - 1, result.offset(index + length + 2))
223     }
224 }
225