use itoa;
use util::*;
#[inline]
pub(crate) fn naive_exponent(d: f64, radix: u32) -> i32
{
(d.ln() / (radix as f64).ln()).floor() as i32
}
fn ftoa_naive<'a>(value: f64, radix: u32, bytes: &'a mut [u8])
-> &'a mut [u8]
{
debug_assert_radix!(radix);
debug_assert!(!value.is_special());
debug_assert!(value != 0.0);
debug_assert!(value > 0.0);
const MAX_NONDIGIT_LENGTH: usize = 25;
const MAX_DIGIT_LENGTH: usize = BUFFER_SIZE - MAX_NONDIGIT_LENGTH;
const SIZE: usize = 2200;
let mut buffer: [u8; SIZE] = explicit_uninitialized();
let initial_position: usize = SIZE / 2;
let mut integer_cursor = initial_position;
let mut fraction_cursor = initial_position;
let base = radix as f64;
let mut integer = value.floor();
let mut fraction = value - integer;
let mut delta = 0.5 * (value.next_positive() - value);
delta = 0.0.next_positive().max_finite(delta);
debug_assert!(delta > 0.0);
if fraction > delta {
loop {
fraction *= base;
delta *= base;
let digit = fraction as i32;
buffer[fraction_cursor] = digit_to_char(digit);
fraction_cursor += 1;
fraction -= digit as f64;
if fraction > 0.5 || (fraction == 0.5 && (digit & 1) != 0) {
if fraction + delta > 1.0 {
loop {
fraction_cursor -= 1;
if fraction_cursor == initial_position-1 {
integer += 1.0;
break;
}
let c = buffer[fraction_cursor];
let digit = char_to_digit(c) as i32;
if digit <= radix as i32 {
let idx = (digit + 1) as usize;
buffer[fraction_cursor] = digit_to_char(idx);
fraction_cursor += 1;
break;
}
}
break;
}
}
if delta >= fraction {
break;
}
}
}
while (integer / base).exponent() > 0 {
integer /= base;
integer_cursor -= 1;
buffer[integer_cursor] = b'0';
}
loop {
let remainder = integer % base;
integer_cursor -= 1;
let idx = remainder as usize;
buffer[integer_cursor] = digit_to_char(idx);
integer = (integer - remainder) / base;
if integer <= 0.0 {
break;
}
};
if value <= 1e-5 || value >= 1e9 {
let exponent = naive_exponent(value, radix);
let start: usize;
let end: usize;
if value <= 1e-5 {
start = ((initial_position as i32) - exponent - 1) as usize;
end = fraction_cursor.min(start + MAX_DIGIT_LENGTH + 1);
} else {
start = integer_cursor;
end = fraction_cursor.min(start + MAX_DIGIT_LENGTH + 1);
}
let buffer = &buffer[start..end];
let buffer = rtrim_char_slice(buffer, b'0').0;
bytes[0] = buffer[0];
bytes[1] = b'.';
let bytes = copy_to_dst(&mut bytes[2..], &buffer[1..]);
bytes[0] = exponent_notation_char(radix);
let exp: u32;
if exponent < 0 {
bytes[1] = b'-';
exp = exponent.wrapping_neg() as u32;
itoa::forward(exp, radix, &mut bytes[2..])
} else {
exp = exponent as u32;
itoa::forward(exp, radix, &mut bytes[1..])
}
} else {
let integer_length = initial_position - integer_cursor;
let fraction_length = (fraction_cursor - initial_position).min(MAX_DIGIT_LENGTH - integer_length);
let bytes = copy_to_dst(bytes, &buffer[integer_cursor..integer_cursor+integer_length]);
if fraction_length > 0 {
bytes[0] = b'.';
let src = &buffer[initial_position..initial_position+fraction_length];
copy_to_dst(&mut bytes[1..], src)
} else {
copy_to_dst(bytes, ".0")
}
}
}
#[inline]
pub(crate) fn float_radix<'a>(f: f32, radix: u32, bytes: &'a mut [u8])
-> &'a mut [u8]
{
double_radix(f as f64, radix, bytes)
}
#[inline]
pub(crate) fn double_radix<'a>(value: f64, radix: u32, bytes: &'a mut [u8])
-> &'a mut [u8]
{
ftoa_naive(value, radix, bytes)
}