use alloc::{
format,
string::{String, ToString},
};
use core::{
cmp::{max, min},
fmt,
mem::MaybeUninit,
ops::{AddAssign, Rem},
};
use f256_pow10_div_pow2_lut::{
get_pow10_div_pow2_params, lookup_pow10_div_pow2, CHUNK_BASE,
CHUNK_CUTOFF, CHUNK_SIZE, COMPRESSION_RATE, SHIFT,
};
use f256_pow2_div_pow10_lut::{
get_pow2_div_pow10_params, lookup_pow2_div_pow10,
};
use super::{
common::{floor_log10_pow2, floor_log10f},
dec_repr::DecNumRepr,
formatted::{Formatted, Part},
powers_of_five::{get_power_of_five, is_multiple_of_pow5},
};
use crate::{
big_uint::rounding_div_pow10, f256, BigUInt, DivRem, HiLo, EMAX, EMIN,
FRACTION_BITS, SIGNIFICAND_BITS, U256, U512,
};
#[derive(PartialEq)]
enum Round {
Up,
ToEven,
Down,
}
#[inline(always)]
#[allow(clippy::cast_possible_truncation)]
fn mul_shift_mod(x: &U256, y: &U512, k: u32) -> u64 {
debug_assert!(k > 256);
let mut t = x.widening_mul(&y.hi);
let mut res = U512::from_hi_lo(t.1, t.0);
t = x.widening_mul(&y.lo);
let mut carry = false;
(res.lo, carry) = res.lo.overflowing_add(&t.1);
if carry {
res.hi.incr();
}
res >>= (k - 256);
(res % CHUNK_BASE as u128) as u64
}
#[inline(always)]
fn pow2_div_pow10(segment_idx: usize, chunk_idx: usize) -> U512 {
let t = lookup_pow2_div_pow10(segment_idx, chunk_idx);
U512::from_hi_lo(U256::new(0, t.0), U256::new(t.1, t.2))
}
#[inline(always)]
fn pow10_div_pow2(segment_idx: usize, chunk_idx: usize) -> U512 {
let t = lookup_pow10_div_pow2(segment_idx, chunk_idx);
U512::from_hi_lo(U256::new(0, t.0), U256::new(t.1, t.2))
}
#[allow(clippy::integer_division)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
fn bin_fract_2_dec_str(
signif2: U256,
exp2: i32,
prec: usize,
buf: &mut String,
) -> Round {
let mut round = Round::Down;
let n_chunks = prec as u32 / CHUNK_SIZE + 1;
let (segment_idx, (n_zero_chunks, segment_shift)) =
get_pow10_div_pow2_params(exp2);
debug_assert!(segment_shift > exp2);
let shift = (segment_shift - exp2) as u32;
if n_chunks <= n_zero_chunks {
buf.push_str("0".repeat(prec).as_str());
return round;
}
if n_zero_chunks > 0 {
buf.push_str(
"0".repeat((n_zero_chunks * CHUNK_SIZE) as usize).as_str(),
);
}
let n_signif_chunks = n_chunks - n_zero_chunks;
debug_assert!(
n_signif_chunks <= CHUNK_CUTOFF,
"Internal limit for significant fractional digits exceeded."
);
for chunk_idx in 0..n_signif_chunks {
let t = pow10_div_pow2(segment_idx, chunk_idx as usize);
let mut chunk = mul_shift_mod(&signif2, &t, shift);
if chunk_idx < n_signif_chunks - 1 {
buf.push_str(
format!("{:01$}", chunk, CHUNK_SIZE as usize).as_str(),
);
} else {
let n_digits = prec as u32 - (n_chunks - 1) * CHUNK_SIZE;
debug_assert!(n_digits <= CHUNK_SIZE);
let d = 10_u64.pow(CHUNK_SIZE - n_digits);
let rem = chunk % d;
chunk /= d;
let tie = d >> 1;
#[allow(clippy::comparison_chain)]
if rem > tie {
round = Round::Up;
} else if rem == tie {
round = if (signif2.trailing_zeros() as i32)
>= (-exp2 - prec as i32 - 1)
{
Round::ToEven
} else {
Round::Up
};
}
if n_digits > 0 {
buf.push_str(
format!("{:01$}", chunk, n_digits as usize).as_str(),
);
}
}
}
round
}
#[allow(unsafe_code)]
#[inline]
fn round_up_fixed_point_inplace(num: &mut str) {
let mut idx = num.len() - 1;
unsafe {
let bytes = num.as_bytes_mut();
loop {
if bytes[idx] == b'9' {
bytes[idx] = b'0';
idx -= 1;
} else if bytes[idx] == b'.' {
idx -= 1;
} else {
bytes[idx] += 1;
break;
}
}
}
}
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
pub(crate) fn bin_2_dec_fixed_point(f: f256, prec: usize) -> String {
debug_assert!(f.is_finite());
debug_assert!(f.is_sign_positive());
let mut exp2 = f.quantum_exponent();
let mut signif2 = f.integral_significand();
let ntz = signif2.trailing_zeros() as i32;
let (is_less_than_one, is_int, (ip, fp)) = if exp2 >= -ntz {
(false, true, (f, f256::ZERO))
} else if exp2 < -(FRACTION_BITS as i32) {
(true, false, (f256::ZERO, f))
} else {
(false, false, f.split())
};
let buf_len = if is_less_than_one {
3 + prec
} else {
floor_log10_pow2(exp2 + SIGNIFICAND_BITS as i32) as usize + 3 + prec
};
let mut res = String::with_capacity(buf_len);
res.push('0');
if is_less_than_one {
res.push('0');
} else {
res.push_str(ip.to_string().as_str());
}
if prec > 0 {
res.push('.');
}
let mut round = Round::Down;
if is_int {
res.push_str("0".repeat(prec).as_str());
} else {
exp2 = fp.quantum_exponent();
signif2 = fp.integral_significand();
if exp2 < EMIN {
let adj = SIGNIFICAND_BITS - signif2.msb();
signif2 <<= adj;
exp2 -= adj as i32;
}
round = bin_fract_2_dec_str(signif2, exp2, prec, &mut res);
}
if round == Round::Up
|| (round == Round::ToEven
&& res.ends_with(['1', '3', '5', '7', '9']))
{
round_up_fixed_point_inplace(&mut res);
}
res
}
#[inline]
fn split_into_buf(buf: &mut String, s: &str) {
buf.push_str(&s[..1]);
buf.push('.');
buf.push_str(&s[1..]);
}
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
fn bin_small_float_2_scientific(
signif2: U256,
exp2: i32,
prec: usize,
buf: &mut String,
) -> (Round, i32) {
debug_assert!(exp2 > -(SIGNIFICAND_BITS as i32) && exp2 < 0);
let mut exp10 = floor_log10f(signif2, exp2);
let k = prec as i32 - exp10;
let n = -exp2;
let signif10 = if k >= 0 {
let (lo, hi) = signif2.widening_mul(&get_power_of_five(k as u32));
let mut t = U512::from_hi_lo(hi, lo);
if k < n {
t = t.rounding_div_pow2((n - k) as u32);
} else {
t <<= (k - n) as u32;
}
t
} else {
let d = get_power_of_five(-k as u32) << (n - k) as u32;
let mut t = signif2.rounding_div(&d);
U512::from_hi_lo(U256::ZERO, t)
};
let mut s = signif10.to_string();
if s.len() > prec + 1 {
s = s[..s.len() - 1].to_string();
exp10 += 1;
}
if prec == 0 {
buf.push_str(&s);
} else {
split_into_buf(buf, &s);
}
(Round::Down, exp10)
}
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
fn bin_small_int_2_scientific(
signif2: U256,
exp2: i32,
prec: usize,
buf: &mut String,
) -> (Round, i32) {
debug_assert!(
exp2 >= 0 && exp2 <= (U512::BITS - SIGNIFICAND_BITS) as i32
);
let mut exp10 = floor_log10f(signif2, exp2);
let k = exp10 - prec as i32;
let signif10 = if k > 0 {
let mut t = U512::from_hi_lo(U256::ZERO, signif2);
t <<= exp2 as u32;
rounding_div_pow10(&t, k as u32)
} else {
let t = get_power_of_five(-k as u32) << (exp2 - k) as u32;
let (lo, hi) = signif2.widening_mul(&t);
U512::from_hi_lo(hi, lo)
};
let mut s = signif10.to_string();
if s.len() > prec + 1 {
s = s[..s.len() - 1].to_string();
exp10 += 1;
}
if prec == 0 {
buf.push_str(&s);
} else {
split_into_buf(buf, &s);
}
(Round::Down, exp10)
}
#[allow(clippy::integer_division)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
fn bin_large_int_2_scientific(
signif2: U256,
exp2: i32,
prec: usize,
buf: &mut String,
) -> (Round, i32) {
debug_assert!(exp2 > (U512::BITS - SIGNIFICAND_BITS) as i32);
let mut round = Round::Down;
let (segment_idx, (mut n_chunks, segment_shift)) =
get_pow2_div_pow10_params(exp2);
let shift = segment_shift - exp2 as u32;
let mut n_rem_digits = prec as u32;
let mut chunk_idx = 0_u32;
let mut t = pow2_div_pow10(segment_idx, chunk_idx as usize);
let mut chunk = mul_shift_mod(&signif2, &t, shift);
if chunk == 0 {
n_chunks -= 1;
chunk_idx += 1;
t = pow2_div_pow10(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
}
let mut chunk_size = CHUNK_SIZE;
let mut n_digits = chunk.ilog10();
let exp10 = n_digits + (n_chunks - 1) * CHUNK_SIZE;
if n_digits > n_rem_digits {
let d = 10_u64.pow(n_digits);
let i = chunk / d;
buf.push_str(i.to_string().as_str());
if n_rem_digits > 0 {
buf.push('.');
}
chunk %= d;
chunk_size = n_digits;
n_digits = min(chunk_size, n_rem_digits);
} else {
let s = chunk.to_string();
if prec > 0 {
split_into_buf(buf, s.as_str());
} else {
buf.push_str(s.as_str());
}
n_rem_digits -= n_digits;
chunk_idx += 1;
debug_assert!(
chunk_idx < CHUNK_CUTOFF,
"Internal limit for significant fractional digits exceeded."
);
t = pow2_div_pow10(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
chunk_size = CHUNK_SIZE;
n_digits = min(chunk_size, n_rem_digits);
}
while n_digits == chunk_size {
buf.push_str(format!("{:01$}", chunk, n_digits as usize).as_str());
n_rem_digits -= n_digits;
chunk_idx += 1;
assert!(
chunk_idx < CHUNK_CUTOFF,
"Internal limit for significant fractional digits exceeded."
);
t = pow2_div_pow10(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
chunk_size = CHUNK_SIZE;
n_digits = min(chunk_size, n_rem_digits);
}
let d = 10_u64.pow(chunk_size - n_digits);
let rem = chunk % d;
chunk /= d;
let tie = d >> 1;
#[allow(clippy::comparison_chain)]
if rem > tie {
round = Round::Up;
} else if rem == tie {
let k = exp10 - prec as u32 - 1;
round = if k < 103 && is_multiple_of_pow5(&signif2, k) {
Round::ToEven
} else {
Round::Up
};
}
if n_digits > 0 {
buf.push_str(
format!("{:01$}", chunk, n_rem_digits as usize).as_str(),
);
}
(round, exp10 as i32)
}
#[allow(clippy::cognitive_complexity)]
#[allow(clippy::integer_division)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
fn bin_fract_2_scientific(
signif2: U256,
exp2: i32,
prec: usize,
buf: &mut String,
) -> (Round, i32) {
debug_assert!(exp2 <= -(SIGNIFICAND_BITS as i32));
let mut round = Round::Down;
let (segment_idx, (n_zero_chunks, segment_shift)) =
get_pow10_div_pow2_params(exp2);
debug_assert!(segment_shift > exp2);
let mut exp10 = -((n_zero_chunks * CHUNK_SIZE) as i32);
let shift = (segment_shift - exp2) as u32;
let mut n_rem_digits = prec as u32;
let mut chunk_idx = 0_u32;
let mut t = pow10_div_pow2(segment_idx, chunk_idx as usize);
let mut chunk = mul_shift_mod(&signif2, &t, shift);
if chunk == 0 {
exp10 -= CHUNK_SIZE as i32;
chunk_idx += 1;
t = pow10_div_pow2(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
debug_assert_ne!(chunk, 0);
}
let mut chunk_size = CHUNK_SIZE;
let mut n_digits = chunk.ilog10();
exp10 -= (chunk_size - n_digits) as i32;
if n_digits > n_rem_digits {
let d = 10_u64.pow(n_digits);
let i = chunk / d;
buf.push_str(i.to_string().as_str());
if n_rem_digits > 0 {
buf.push('.');
}
chunk %= d;
chunk_size = n_digits;
n_digits = min(chunk_size, n_rem_digits);
} else {
let s = chunk.to_string();
if prec > 0 {
split_into_buf(buf, s.as_str());
} else {
buf.push_str(s.as_str());
}
n_rem_digits -= n_digits;
chunk_idx += 1;
debug_assert!(
chunk_idx < CHUNK_CUTOFF,
"Internal limit for significant fractional digits exceeded."
);
t = pow10_div_pow2(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
chunk_size = CHUNK_SIZE;
n_digits = min(chunk_size, n_rem_digits);
}
while n_digits == chunk_size {
buf.push_str(format!("{:01$}", chunk, n_digits as usize).as_str());
n_rem_digits -= n_digits;
chunk_idx += 1;
debug_assert!(
chunk_idx < CHUNK_CUTOFF,
"Internal limit for significant fractional digits exceeded."
);
t = pow10_div_pow2(segment_idx, chunk_idx as usize);
chunk = mul_shift_mod(&signif2, &t, shift);
chunk_size = CHUNK_SIZE;
n_digits = min(chunk_size, n_rem_digits);
}
let d = 10_u64.pow(chunk_size - n_digits);
let rem = chunk % d;
chunk /= d;
let tie = d >> 1;
#[allow(clippy::comparison_chain)]
if rem > tie {
round = Round::Up;
} else if rem == tie {
round =
if (signif2.trailing_zeros() + prec as u32 + 1) as i32 >= -exp2 {
Round::ToEven
} else {
Round::Up
};
}
if n_digits > 0 {
buf.push_str(
format!("{:01$}", chunk, n_rem_digits as usize).as_str(),
);
}
(round, exp10)
}
#[allow(unsafe_code)]
#[inline]
fn round_up_scientific_inplace(num: &mut str) -> i32 {
let mut carry = 0_i32;
let mut idx = num.len() - 1;
unsafe {
let bytes = num.as_bytes_mut();
loop {
if idx == 0 && bytes[idx] == b'9' {
bytes[idx] = b'1';
carry = 1;
break;
} else if bytes[idx] == b'9' {
bytes[idx] = b'0';
idx -= 1;
} else if bytes[idx] == b'.' {
idx -= 1;
} else {
bytes[idx] += 1;
break;
}
}
}
carry
}
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
pub(crate) fn bin_2_dec_scientific(
f: f256,
exp_mark: char,
prec: usize,
) -> String {
debug_assert!(f.is_finite());
debug_assert!(f.is_sign_positive());
const SUBNORMAL_EXP_LOWER_BOUND: i32 = EMIN - FRACTION_BITS as i32;
const NORMAL_EXP_LOWER_BOUND: i32 = EMIN;
const FAST_LOWER_BOUND: i32 = -(FRACTION_BITS as i32);
const SLOW_LOWER_BOUND: i32 = (U512::BITS - SIGNIFICAND_BITS + 1) as i32;
const EXP_UPPER_BOUND: i32 = EMAX - FRACTION_BITS as i32;
let mut exp2 = f.quantum_exponent();
let mut signif2 = f.integral_significand();
let mut res = String::with_capacity(prec + 9);
let mut round = Round::Down;
let mut exp10 = 0_i32;
match exp2 {
FAST_LOWER_BOUND..=-1 => {
(round, exp10) =
bin_small_float_2_scientific(signif2, exp2, prec, &mut res);
}
0..SLOW_LOWER_BOUND => {
(round, exp10) =
bin_small_int_2_scientific(signif2, exp2, prec, &mut res);
}
NORMAL_EXP_LOWER_BOUND..FAST_LOWER_BOUND => {
(round, exp10) =
bin_fract_2_scientific(signif2, exp2, prec, &mut res);
}
SLOW_LOWER_BOUND..=EXP_UPPER_BOUND => {
(round, exp10) =
bin_large_int_2_scientific(signif2, exp2, prec, &mut res);
res.push_str(
"0".repeat(prec - min(prec, exp10 as usize)).as_str(),
);
}
SUBNORMAL_EXP_LOWER_BOUND..NORMAL_EXP_LOWER_BOUND => {
let adj = SIGNIFICAND_BITS - signif2.msb();
signif2 <<= adj;
exp2 -= adj as i32;
(round, exp10) =
bin_fract_2_scientific(signif2, exp2, prec, &mut res);
}
_ => {
unreachable!()
}
}
if round == Round::Up
|| (round == Round::ToEven
&& res.ends_with(['1', '3', '5', '7', '9']))
{
exp10 += round_up_scientific_inplace(&mut res);
}
res.push(exp_mark);
res.push_str(exp10.to_string().as_str());
res
}
#[cfg(test)]
mod to_fixed_point_tests {
use alloc::borrow::ToOwned;
use core::{ops::Index, str::FromStr};
use super::*;
#[test]
fn test_one() {
let f = f256::ONE;
let s = bin_2_dec_fixed_point(f, 2);
assert_eq!(s, "01.00");
}
#[test]
fn test_one_half() {
let f = f256::from_str("0.5").unwrap();
let s = bin_2_dec_fixed_point(f, 0);
assert_eq!(s, "00");
}
#[test]
fn test_five_times_ten_pow_minus_twenty() {
let f = f256::from_str("0.00000000000000000005").unwrap();
let s = bin_2_dec_fixed_point(f, 19);
assert_eq!(s, "00.0000000000000000001");
}
#[test]
fn test_a_bit_less_ten() {
let f = f256::from_str("9.9995").unwrap();
let s = bin_2_dec_fixed_point(f, 3);
assert_eq!(s, "10.000");
}
#[test]
fn test_epsilon() {
let f = f256::EPSILON;
let s = bin_2_dec_fixed_point(f, 75);
assert_eq!(
s,
"00.000000000000000000000000000000000000000000000000000000000\
000000000000009056"
);
}
#[test]
fn test_min_gt_zero() {
let f = f256::MIN_GT_ZERO;
let s = bin_2_dec_fixed_point(f, 79004);
assert!(s.starts_with("00.0"));
assert_eq!(s[s.len() - 23..], "00224800708647703657297".to_owned());
}
#[test]
fn test_7e28() {
let f = f256::from_str("7e28").unwrap();
let s = bin_2_dec_fixed_point(f, 3);
assert_eq!(s, "070000000000000000000000000000.000");
}
#[test]
fn test_one_sixteenth() {
let f = f256::from_str("0.0625").unwrap();
let s = bin_2_dec_fixed_point(f, 23);
assert_eq!(s, "00.06250000000000000000000");
}
}
#[cfg(test)]
#[allow(clippy::decimal_literal_representation)]
mod to_scientific_tests {
use alloc::borrow::ToOwned;
use core::{ops::Index, str::FromStr};
use super::*;
#[test]
fn test_one() {
let f = f256::ONE;
let s = bin_2_dec_scientific(f, 'e', 2);
assert_eq!(s, "1.00e0");
}
#[test]
fn test_one_half() {
let f = f256::from_str("0.5").unwrap();
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "5e-1");
}
#[test]
fn test_two_and_a_half() {
let f = f256::from_str("2.5").unwrap();
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "2e0");
let s = bin_2_dec_scientific(f, 'E', 3);
assert_eq!(s, "2.500E0");
}
#[test]
fn test_three_and_a_half() {
let f = f256::from_str("3.5").unwrap();
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "4e0");
let s = bin_2_dec_scientific(f, 'E', 3);
assert_eq!(s, "3.500E0");
}
#[test]
fn test_one_sixteenth() {
let f = f256::from_str("0.0625").unwrap();
let s = bin_2_dec_scientific(f, 'e', 20);
assert_eq!(s, "6.25000000000000000000e-2");
}
#[test]
fn test_5_pow_4() {
let f = f256::from_str("625").unwrap();
let s = bin_2_dec_scientific(f, 'e', 3);
assert_eq!(s, "6.250e2");
}
#[test]
fn test_epsilon() {
let f = f256::EPSILON;
let s = bin_2_dec_scientific(f, 'E', 2);
assert_eq!(s, "9.06E-72");
let s = bin_2_dec_scientific(f, 'e', 4);
assert_eq!(s, "9.0557e-72");
let s = bin_2_dec_scientific(f, 'e', 6);
assert_eq!(s, "9.055679e-72");
}
#[test]
fn test_min_gt_zero() {
let f = f256::MIN_GT_ZERO;
let s = bin_2_dec_scientific(f, 'e', 20);
assert_eq!(s, "2.24800708647703657297e-78984".to_owned());
}
#[test]
fn test_rounding_overflow() {
let f = f256::from_str("97").unwrap();
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "1e2");
let f = f256::from_str("9999999999999999999997").unwrap();
let s = bin_2_dec_scientific(f, 'e', 20);
assert_eq!(s, "1.00000000000000000000e22");
}
#[test]
fn test_near_6e51() {
let f = f256::from_sign_exp_signif(
0,
-63,
(
162259276829213363391578010288171,
6509687757833892565831669291823167287,
),
);
let s = bin_2_dec_scientific(f, 'e', 16);
assert_eq!(s, "5.9863107065073784e51".to_owned());
}
#[test]
fn test_near_9e46() {
let f = f256::from_sign_exp_signif(
0,
-80,
(
324518553658426726783156020576260,
131182013909294755642979131487572278739,
),
);
let s = bin_2_dec_scientific(f, 'e', 27);
assert_eq!(s, "9.134385233318143238773030204e46".to_owned());
}
#[test]
fn test_near_5e49() {
let f = f256::from_sign_exp_signif(
0,
-70,
(
162259276829213363391578010288165,
333798641618909605187797312347902131237,
),
);
let s = bin_2_dec_scientific(f, 'e', 9);
assert_eq!(s, "4.676805239e49".to_owned());
}
#[test]
fn test_near_1e53_p30() {
let f = f256::from_sign_exp_signif(
0,
-58,
(
111204638850565804364613732798775,
53992318206422839663747108816097201329,
),
);
let s = bin_2_dec_scientific(f, 'e', 30);
assert_eq!(s, "1.312872648118838857960020003483e53".to_owned());
}
#[test]
fn test_near_1e71_p73() {
let f = f256::from_sign_exp_signif(
0,
0,
(
324518553658426726783156020576293,
211723174022145587833097996892173825913,
),
);
let s = bin_2_dec_scientific(f, 'e', 73);
assert_eq!(
s,
"1.104279415486490205989560937964452094099678404234621628410\
7225517843852100e71"
.to_owned()
);
}
#[test]
fn test_near_1e71_p32() {
let f = f256::from_sign_exp_signif(
0,
3,
(
40564819207303340847894502572036,
30633738155744440067036836117427062411,
),
);
let s = bin_2_dec_scientific(f, 'e', 32);
assert_eq!(s, "1.10427941548649020598956093796444e71".to_owned());
}
#[test]
fn test_near_1e71_p71() {
let f = f256::from_sign_exp_signif(
0,
0,
(
324518553658426726783156020576302,
114739602320310674262284750468945069455,
),
);
let s = bin_2_dec_scientific(f, 'e', 71);
assert_eq!(
s,
"1.104279415486490205989560937964481749676984270347197623992\
92717863585167e71"
.to_owned()
);
}
#[test]
fn test_near_1e153_1() {
let f = f256::from_sign_exp_signif(
0,
273,
(
190239164977113327839599021215685,
51755389174173320950400950367778013131,
),
);
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "1e153".to_owned());
}
#[test]
fn test_near_1e153_2() {
let f = f256::from_sign_exp_signif(
0,
272,
(
413471794362977846403210123211276,
124164318988604946586367062043758872275,
),
);
let s = bin_2_dec_scientific(f, 'e', 0);
assert_eq!(s, "1e153".to_owned());
}
#[test]
fn test_near_2e154_p61() {
let f = f256::from_sign_exp_signif(
0,
276,
(
476572172941463809973332496053458,
68728353086631173142785452318047905517,
),
);
let s = bin_2_dec_scientific(f, 'e', 61);
assert_eq!(
s,
"1.969005496764332863783443912931624800937847641827908017905\
9660e154"
.to_owned()
);
}
#[test]
fn test_near_1e154_p59() {
let f = f256::from_sign_exp_signif(
0,
280,
(
21818185152426254566033124806402,
292040079606001995347138042200221474811,
),
);
let s = bin_2_dec_scientific(f, 'e', 59);
assert_eq!(
s,
"1.44230415231821555091417756482480990212576324553723504560651e154"
.to_owned()
);
}
#[test]
fn test_near_1e154_p20() {
let f = f256::from_sign_exp_signif(
0,
276,
(
361137145230230407900995305707557,
110598383419209761764611943431534229547,
),
);
let s = bin_2_dec_scientific(f, 'e', 20);
assert_eq!(s, "1.49207415878946667629e154".to_owned());
}
#[test]
fn test_near_10e_minus_10918_p64() {
let f = f256::from_sign_exp_signif(
0,
-36502,
(
447555113562244345125307681812305,
111083065766899325684028850678679662440,
),
);
let s = bin_2_dec_scientific(f, 'e', 64);
assert_eq!(
s,
"9.677969339371647374674789631478211843426763786935989435\
5285173687e-10918"
.to_owned()
);
}
#[test]
fn test_greatest_less_1_p54() {
let f = f256::ONE - f256::EPSILON;
let s = bin_2_dec_scientific(f, 'e', 54);
assert_eq!(
s,
"1.000000000000000000000000000000000000000000000000000000e0"
.to_owned()
);
}
#[test]
fn test_near_2e_minus_35402_p71() {
let f = f256::from_sign_exp_signif(
0,
-117838,
(
430291270053216327019827899538921,
38660543114844194825861158788102622161,
),
);
let s = bin_2_dec_scientific(f, 'e', 71);
assert_eq!(
s,
"2.471570072197153940829180483920657748943792994870723271\
92157954211602055e-35402"
.to_owned()
);
}
#[test]
fn test_near_2e_minus_35402_p70() {
let f = f256::from_sign_exp_signif(
0,
-117838,
(
430291270053216327019827899538921,
38660543114844194825861158788102622161,
),
);
let s = bin_2_dec_scientific(f, 'e', 70);
assert_eq!(
s,
"2.471570072197153940829180483920657748943792994870723271\
9215795421160206e-35402"
.to_owned()
);
}
#[test]
fn test_near_8e16807_p73() {
let f = f256::from_sign_exp_signif(
0,
55598,
(
536040174375893933201096973487091,
307984350317190873395708741682215551557,
),
);
let s = bin_2_dec_scientific(f, 'e', 73);
assert_eq!(
s,
"8.447646086055224609046497651648431840143361281963366366\
6796603174614594313e16807"
.to_owned()
);
}
#[test]
fn test_near_8e16807_p67() {
let f = f256::from_sign_exp_signif(
0,
55598,
(
536040174375893933201096973487091,
307984350317190873395708741682215551557,
),
);
let s = bin_2_dec_scientific(f, 'e', 67);
assert_eq!(
s,
"8.447646086055224609046497651648431840143361281963366366\
6796603174615e16807"
.to_owned()
);
}
#[test]
fn test_near_2e_minus_47352_p72() {
let f = f256::from_sign_exp_signif(
0,
-157535,
(
401609310945955079118279405485910,
168709353958551391248113314710179390005,
),
);
let s = bin_2_dec_scientific(f, 'e', 72);
assert_eq!(
s,
"2.372882823780069989738354638128785919529692752357933380\
060881450776866269e-47352"
.to_owned()
);
}
#[test]
fn test_near_2e_minus_55309_p61() {
let f = f256::from_sign_exp_signif(
0,
-183968,
(
622361313473788073495577958636900,
21807422016073324498045687998560255045,
),
);
let s = bin_2_dec_scientific(f, 'e', 61);
assert_eq!(
s,
"2.751944825690125768618234983557273839998107604792147797\
6588487e-55309"
.to_owned()
);
}
#[test]
fn test_near_1e_minus_28481_p67() {
let f = f256::from_sign_exp_signif(
0,
-94848,
(
480556181134176289164812750762510,
154360262685660584150336803990464604332,
),
);
let s = bin_2_dec_scientific(f, 'e', 67);
assert_eq!(
s,
"1.319942082877611614846938029746780763801526923656755728\
9282641062734e-28481"
.to_owned()
);
}
}