use crate::soft_f32::F32;
use crate::soft_f64::F64;
pub const fn extend(a: F32) -> F64 {
let src_zero = 0;
let src_one = 1;
let src_bits = F32::BITS;
let src_sign_bits = F32::SIGNIFICAND_BITS;
let src_exp_bias = F32::EXPONENT_BIAS;
let src_min_normal = F32::IMPLICIT_BIT;
let src_infinity = F32::EXPONENT_MASK;
let src_sign_mask = F32::SIGN_MASK;
let src_abs_mask = src_sign_mask - src_one;
let src_qnan = F32::SIGNIFICAND_MASK;
let src_nan_code = src_qnan - src_one;
let dst_bits = F64::BITS;
let dst_sign_bits = F64::SIGNIFICAND_BITS;
let dst_inf_exp = F64::EXPONENT_MAX;
let dst_exp_bias = F64::EXPONENT_BIAS;
let dst_min_normal = F64::IMPLICIT_BIT;
let sign_bits_delta = dst_sign_bits - src_sign_bits;
let exp_bias_delta = dst_exp_bias - src_exp_bias;
let a_abs = a.repr() & src_abs_mask;
let mut abs_result: u64 = 0;
if a_abs.wrapping_sub(src_min_normal) < src_infinity.wrapping_sub(src_min_normal) {
let abs_dst = a_abs as u64;
let bias_dst = exp_bias_delta as u64;
abs_result = abs_dst.wrapping_shl(sign_bits_delta);
abs_result += bias_dst.wrapping_shl(dst_sign_bits);
} else if a_abs >= src_infinity {
let qnan_dst = (a_abs & src_qnan) as u64;
let nan_code_dst = (a_abs & src_nan_code) as u64;
let inf_exp_dst = dst_inf_exp as u64;
abs_result = inf_exp_dst.wrapping_shl(dst_sign_bits);
abs_result |= qnan_dst.wrapping_shl(sign_bits_delta);
abs_result |= nan_code_dst.wrapping_shl(sign_bits_delta);
} else if a_abs != src_zero {
let scale = a_abs.leading_zeros() - src_min_normal.leading_zeros();
let abs_dst = a_abs as u64;
let bias_dst = (exp_bias_delta - scale + 1) as u64;
abs_result = abs_dst.wrapping_shl(sign_bits_delta + scale);
abs_result = (abs_result ^ dst_min_normal) | (bias_dst.wrapping_shl(dst_sign_bits));
}
let sign_result = (a.repr() & src_sign_mask) as u64;
F64::from_repr(abs_result | (sign_result.wrapping_shl(dst_bits - src_bits)))
}
pub const fn trunc(a: F64) -> F32 {
let src_zero = 0_u64;
let src_one = 1_u64;
let src_bits = F64::BITS;
let src_exp_bias = F64::EXPONENT_BIAS;
let src_min_normal = F64::IMPLICIT_BIT;
let src_significand_mask = F64::SIGNIFICAND_MASK;
let src_infinity = F64::EXPONENT_MASK;
let src_sign_mask = F64::SIGN_MASK;
let src_abs_mask = src_sign_mask - src_one;
let round_mask = (src_one << (F64::SIGNIFICAND_BITS - F32::SIGNIFICAND_BITS)) - src_one;
let halfway = src_one << (F64::SIGNIFICAND_BITS - F32::SIGNIFICAND_BITS - 1);
let src_qnan = src_one << (F64::SIGNIFICAND_BITS - 1);
let src_nan_code = src_qnan - src_one;
let dst_zero = 0_u32;
let dst_one = 1_u32;
let dst_bits = F32::BITS;
let dst_inf_exp = F32::EXPONENT_MAX;
let dst_exp_bias = F32::EXPONENT_BIAS;
let underflow_exponent: u64 = (src_exp_bias + 1 - dst_exp_bias) as u64;
let overflow_exponent: u64 = (src_exp_bias + dst_inf_exp - dst_exp_bias) as u64;
let underflow: u64 = underflow_exponent << F64::SIGNIFICAND_BITS;
let overflow: u64 = overflow_exponent << F64::SIGNIFICAND_BITS;
let dst_qnan = 1_u32 << (F32::SIGNIFICAND_BITS - 1);
let dst_nan_code = dst_qnan - dst_one;
let sign_bits_delta = F64::SIGNIFICAND_BITS - F32::SIGNIFICAND_BITS;
let a_abs = a.repr() & src_abs_mask;
let sign = a.repr() & src_sign_mask;
let mut abs_result: u32;
if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) {
abs_result = (a_abs >> sign_bits_delta) as u32;
let tmp = src_exp_bias.wrapping_sub(dst_exp_bias) << F32::SIGNIFICAND_BITS;
abs_result = abs_result.wrapping_sub(tmp as u32);
let round_bits = a_abs & round_mask;
if round_bits > halfway {
abs_result += dst_one;
} else if round_bits == halfway {
abs_result += abs_result & dst_one;
};
} else if a_abs > src_infinity {
abs_result = (dst_inf_exp << F32::SIGNIFICAND_BITS) as u32;
abs_result |= dst_qnan;
abs_result |= dst_nan_code
& ((a_abs & src_nan_code) >> (F64::SIGNIFICAND_BITS - F32::SIGNIFICAND_BITS)) as u32;
} else if a_abs >= overflow {
abs_result = (dst_inf_exp << F32::SIGNIFICAND_BITS) as u32;
} else {
let a_exp: u32 = (a_abs >> F64::SIGNIFICAND_BITS) as u32;
let shift = src_exp_bias - dst_exp_bias - a_exp + 1;
let significand = (a.repr() & src_significand_mask) | src_min_normal;
if shift > F64::SIGNIFICAND_BITS {
abs_result = dst_zero;
} else {
let sticky = if (significand << (src_bits - shift)) != src_zero {
src_one
} else {
src_zero
};
let denormalized_significand: u64 = significand >> shift | sticky;
abs_result = (denormalized_significand
>> (F64::SIGNIFICAND_BITS - F32::SIGNIFICAND_BITS)) as u32;
let round_bits = denormalized_significand & round_mask;
if round_bits > halfway {
abs_result += dst_one;
}
else if round_bits == halfway {
abs_result += abs_result & dst_one;
};
}
}
F32::from_repr(abs_result | sign.wrapping_shr(src_bits - dst_bits) as u32)
}
pub const fn u32_to_f64_bits(i: u32) -> u64 {
if i == 0 {
return 0;
}
let n = i.leading_zeros();
let m = (i as u64) << (21 + n); let e = 1053 - n as u64; (e << 52) + m }
pub const fn i32_to_f64(i: i32) -> F64 {
let sign_bit = ((i >> 31) as u64) << 63;
F64::from_bits(u32_to_f64_bits(i.unsigned_abs()) | sign_bit)
}
pub const fn f64_to_i32(f: F64) -> i32 {
let fbits = f.to_bits() & !0 >> 1; if fbits < 1023 << 52 {
0
} else if fbits < 1054 << 52 {
let m = 1 << 31 | (fbits >> 21) as u32; let s = 1054 - (fbits >> 52); let u = (m >> s) as i32; if f.is_sign_negative() {
-u
} else {
u
}
} else if fbits <= 2047 << 52 {
if f.is_sign_negative() {
i32::MIN
} else {
i32::MAX
}
} else {
0
}
}
const fn u32_to_f32_bits(i: u32) -> u32 {
if i == 0 {
return 0;
}
let n = i.leading_zeros();
let a = (i << n) >> 8; let b = (i << n) << 24; let m = a + ((b - (b >> 31 & !a)) >> 31); let e = 157 - n; (e << 23) + m }
pub const fn u32_to_f32(i: u32) -> F32 {
F32::from_bits(u32_to_f32_bits(i))
}
pub const fn f32_to_u32(f: F32) -> u32 {
let fbits = f.to_bits();
if fbits < 127 << 23 {
0
} else if fbits < 159 << 23 {
let m = 1 << 31 | fbits << 8; let s = 158 - (fbits >> 23); m >> s
} else if fbits <= 255 << 23 {
u32::MAX
} else {
0
}
}