1mod exponent;
2mod mantissa;
3
4use self::exponent::*;
5use self::mantissa::*;
6use crate::common;
7use crate::d2s::{self, *};
8use crate::f2s::*;
9use core::ptr;
10#[cfg(feature = "no-panic")]
11use 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)]
52pub 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)]
159pub 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