use super::PxE2;
use crate::u32_with_sign;
use core::f64;
impl<const N: u32> From<PxE2<{ N }>> for f32 {
#[inline]
fn from(a: PxE2<{ N }>) -> Self {
a.to_f32()
}
}
impl<const N: u32> From<PxE2<{ N }>> for f64 {
#[inline]
fn from(p_a: PxE2<{ N }>) -> Self {
p_a.to_f64()
}
}
impl<const N: u32> From<f32> for PxE2<{ N }> {
#[inline]
fn from(float: f32) -> Self {
Self::from_f32(float)
}
}
impl<const N: u32> From<f64> for PxE2<{ N }> {
#[inline]
fn from(float: f64) -> Self {
Self::from_f64(float)
}
}
impl<const N: u32> From<i32> for PxE2<{ N }> {
#[inline]
fn from(i_a: i32) -> Self {
Self::from_i32(i_a)
}
}
impl<const N: u32> From<u32> for PxE2<{ N }> {
#[inline]
fn from(a: u32) -> Self {
Self::from_u32(a)
}
}
impl<const N: u32> From<i64> for PxE2<{ N }> {
#[inline]
fn from(i_a: i64) -> Self {
Self::from_i64(i_a)
}
}
impl<const N: u32> From<u64> for PxE2<{ N }> {
#[inline]
fn from(a: u64) -> Self {
Self::from_u64(a)
}
}
impl<const N: u32> From<PxE2<{ N }>> for i32 {
#[inline]
fn from(p_a: PxE2<{ N }>) -> Self {
crate::P32E2::from_bits(p_a.to_bits()).to_i32()
}
}
impl<const N: u32> From<PxE2<{ N }>> for u32 {
#[inline]
fn from(p_a: PxE2<{ N }>) -> Self {
crate::P32E2::from_bits(p_a.to_bits()).to_u32()
}
}
impl<const N: u32> From<PxE2<{ N }>> for u64 {
#[inline]
fn from(p_a: PxE2<{ N }>) -> Self {
crate::P32E2::from_bits(p_a.to_bits()).to_u64()
}
}
impl<const N: u32> From<PxE2<{ N }>> for i64 {
#[inline]
fn from(p_a: PxE2<{ N }>) -> Self {
crate::P32E2::from_bits(p_a.to_bits()).to_i64()
}
}
impl<const N: u32> PxE2<{ N }> {
#[inline]
pub fn to_f32(self) -> f32 {
self.to_f64() as f32
}
pub fn to_f64(self) -> f64 {
let mut ui_a = self.to_bits();
if self.is_zero() {
0.
} else if self.is_nar() {
f64::NAN
} else {
let sign_a = ui_a & 0x_8000_0000;
if sign_a != 0 {
ui_a = ui_a.wrapping_neg();
}
let (k_a, tmp) = PxE2::<{ N }>::separate_bits_tmp(ui_a);
let frac_a = ((tmp << 3) as u64) << 20;
let exp_a = (((k_a as u64) << 2) + ((tmp >> 29) as u64)).wrapping_add(1023) << 52;
f64::from_bits(exp_a + frac_a + ((sign_a as u64) << 32))
}
}
#[inline]
pub fn from_f32(float: f32) -> Self {
Self::from_f64(float as f64)
}
#[allow(clippy::cognitive_complexity)]
pub fn from_f64(mut float: f64) -> Self {
let mut reg: u32;
let mut frac = 0_u32;
let mut exp = 0_i32;
let mut bit_n_plus_one = false;
let mut bits_more = false;
if float == 0. {
return Self::ZERO;
} else if !float.is_finite() {
return Self::NAR;
}
let sign = float < 0.;
let u_z: u32 = if float == 1. {
0x4000_0000
} else if float == -1. {
0xC000_0000
} else if !(-1. ..=1.).contains(&float) {
if sign {
float = -float;
}
let reg_s = true;
reg = 1; if (N == 2) && (float <= 7.523_163_845_262_64_e-37) {
1
} else {
while float >= 16. {
float *= 0.0625; reg += 1;
}
while float >= 2. {
float *= 0.5;
exp += 1;
}
let frac_length = (N - 4) as isize - (reg as isize);
if frac_length < 0 {
if reg == N - 3 {
bit_n_plus_one = (exp & 0x1) != 0;
exp &= 0x2;
} else {
bit_n_plus_one = (exp >> 1) != 0;
bits_more = (exp & 0x1) != 0;
exp = 0;
}
if float != 1. {
bits_more = true;
frac = 0;
}
} else {
frac = crate::convert_fraction_p32(
float,
frac_length as u16,
&mut bit_n_plus_one,
&mut bits_more,
);
}
u32_with_sign(
if reg > (N - 2) {
if reg_s {
0x_7FFF_FFFF & Self::mask()
} else {
0x1 << (32 - N)
}
} else {
let regime = if reg_s { ((1 << reg) - 1) << 1 } else { 1_u32 };
if (N == 32) && (reg == 29) {
exp >>= 1;
} else if reg <= 28 {
exp <<= 28 - reg;
}
let mut u_z = ((regime as u32) << (30 - reg))
+ (exp as u32)
+ ((frac << (32 - N)) as u32);
if (u_z == 0) && (frac > 0) {
u_z = 0x1 << (32 - N);
}
if bit_n_plus_one {
u_z += (((u_z >> (32 - N)) & 0x1) | (bits_more as u32)) << (32 - N);
}
u_z
},
sign,
)
}
} else if (float < 1.) || (float > -1.) {
if sign {
float = -float;
}
let reg_s = false;
reg = 0;
while float < 1. {
float *= 16.;
reg += 1;
}
while float >= 2. {
float *= 0.5;
exp += 1;
}
let frac_length = (N - 4) as isize - (reg as isize);
if frac_length < 0 {
if reg == N - 3 {
bit_n_plus_one = (exp & 0x1) != 0;
exp &= 0x2;
} else {
bit_n_plus_one = (exp >> 1) != 0;
bits_more = (exp & 0x1) != 0;
exp = 0;
}
if float != 1. {
bits_more = true;
frac = 0;
}
} else {
frac = crate::convert_fraction_p32(
float,
frac_length as u16,
&mut bit_n_plus_one,
&mut bits_more,
);
}
u32_with_sign(
if reg > (N - 2) {
if reg_s {
0x_7FFF_FFFF & Self::mask()
} else {
0x1 << (32 - N)
}
} else {
let regime = if reg_s { ((1 << reg) - 1) << 1 } else { 1_u32 };
if (N == 32) && (reg == 29) {
exp >>= 1;
} else if reg <= 28 {
exp <<= 28 - reg;
}
let mut u_z = ((regime as u32) << (30 - reg))
+ (exp as u32)
+ ((frac << (32 - N)) as u32);
if (u_z == 0) && (frac > 0) {
u_z = 0x1 << (32 - N);
}
if bit_n_plus_one {
u_z += (((u_z >> (32 - N)) & 0x1) | (bits_more as u32)) << (32 - N);
}
u_z
},
sign,
)
} else {
0x8000_0000
};
Self::from_bits(u_z)
}
pub const fn from_i32(mut i_a: i32) -> Self {
if i_a < -2_147_483_135 {
Self::from_bits(0x_8050_0000);
}
let sign = i_a.is_negative();
if sign {
i_a = -i_a;
}
let ui_a = if (N == 2) && (i_a > 0) {
0x_4000_0000
} else if i_a > 2_147_483_135 {
let mut ui_a = 0x_7FB0_0000; if N < 10 {
ui_a &= Self::mask();
} else if N < 12 {
ui_a = 0x_7FF0_0000 & Self::mask();
}
ui_a
} else {
convert_u32_to_px2bits::<{ N }>(i_a as u32)
};
Self::from_bits(u32_with_sign(ui_a, sign))
}
pub const fn from_u32(a: u32) -> Self {
let ui_a = if (N == 2) && (a > 0) {
0x_4000_0000
} else if a > 0x_FFFF_FBFF {
let mut ui_a = 0x_7FC0_0000; if N < 12 {
ui_a &= Self::mask();
}
ui_a
} else {
convert_u32_to_px2bits::<{ N }>(a)
};
Self::from_bits(ui_a)
}
pub const fn from_i64(mut i_a: i64) -> Self {
let sign = i_a.is_negative();
if sign {
i_a = -i_a;
}
let ui_a = if (N == 2) && (i_a > 0) {
0x_4000_0000
} else if i_a > 0x_7FFD_FFFF_FFFF_FFFF {
let mut ui_a = 0x_7FFF_B000; if N < 18 {
ui_a &= Self::mask();
}
ui_a
} else {
convert_u32_to_px2bits::<{ N }>(i_a as u32)
};
Self::from_bits(u32_with_sign(ui_a, sign))
}
pub const fn from_u64(a: u64) -> Self {
let ui_a = if (N == 2) && (a > 0) {
0x_4000_0000
} else if a > 0x_FFFB_FFFF_FFFF_FFFF {
let mut ui_a = 0x_7FFF_C000; if N < 18 {
ui_a &= Self::mask();
}
ui_a
} else {
convert_u64_to_px2bits::<{ N }>(a)
};
Self::from_bits(ui_a)
}
#[inline]
pub const fn to_i32(self) -> i32 {
crate::P32E2::from_bits(self.to_bits()).to_i32()
}
#[inline]
pub const fn to_u32(self) -> u32 {
crate::P32E2::from_bits(self.to_bits()).to_u32()
}
#[inline]
pub const fn to_u64(self) -> u64 {
crate::P32E2::from_bits(self.to_bits()).to_u64()
}
#[inline]
pub const fn to_i64(self) -> i64 {
crate::P32E2::from_bits(self.to_bits()).to_i64()
}
}
const fn convert_u32_to_px2bits<const N: u32>(a: u32) -> u32 {
let mut log2 = 31_i8; let mut mask = 0x_8000_0000_u32;
if a < 0x2 {
a << 30
} else {
let mut frac_a = a;
while (frac_a & mask) == 0 {
log2 -= 1;
frac_a <<= 1;
}
let k = (log2 >> 2) as u32;
let exp_a = (log2 & 0x3) as u32;
frac_a ^= mask;
let mut ui_a: u32;
if k >= (N - 2) {
ui_a = 0x_7FFF_FFFF & PxE2::<{ N }>::mask();
} else if k == (N - 3) {
ui_a = 0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k);
if ((exp_a & 0x2) != 0) && (((exp_a & 0x1) | frac_a) != 0) {
ui_a |= 0x_8000_0000_u32 >> (N - 1);
}
} else if k == (N - 4) {
ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | ((exp_a & 0x2) << (27 - k));
if ((exp_a & 0x1) != 0) && ((((0x_8000_0000_u32 >> (N - 1)) & ui_a) | frac_a) != 0) {
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
} else if k == (N - 5) {
ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | (exp_a << (27 - k));
mask = 0x8 << (k - N);
if ((mask & frac_a) != 0) && ((((mask - 1) & frac_a) | (exp_a & 0x1)) != 0) {
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
} else {
ui_a = ((0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | (exp_a << (27 - k)) | frac_a >> (k + 4))
& PxE2::<{ N }>::mask();
mask = 0x8 << (k - N); if ((mask & frac_a) != 0) && ((((mask - 1) & frac_a) | ((mask << 1) & frac_a)) != 0) {
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
}
ui_a
}
}
const fn convert_u64_to_px2bits<const N: u32>(a: u64) -> u32 {
let mut log2 = 63_i8; let mut mask = 0x_8000_0000_0000_0000_u64;
if a < 0x2 {
(a as u32) << 30
} else {
let mut frac64_a = a;
while (frac64_a & mask) == 0 {
log2 -= 1;
frac64_a <<= 1;
}
let k = (log2 >> 2) as u32;
let exp_a = (log2 & 0x3) as u32;
frac64_a ^= mask;
let mut ui_a: u32;
if k >= (N - 2) {
ui_a = 0x_7FFF_FFFF & PxE2::<{ N }>::mask();
} else if k == (N - 3) {
ui_a = 0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k);
if ((exp_a & 0x2) != 0) && (((exp_a & 0x1) as u64 | frac64_a) != 0) {
ui_a |= 0x_8000_0000_u32 >> (N - 1);
}
} else if k == (N - 4) {
ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | ((exp_a & 0x2) << (27 - k));
if ((exp_a & 0x1) != 0)
&& ((((0x_8000_0000_u32 >> (N - 1)) & ui_a) != 0) || (frac64_a != 0))
{
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
} else if k == (N - 5) {
ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | (exp_a << (27 - k));
mask = 0x_0008_0000_0000_u64 << (k + 32 - N);
if (mask & frac64_a) != 0 {
if (((mask - 1) & frac64_a) | ((exp_a & 0x1) as u64)) != 0 {
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
}
} else {
ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k))
| (exp_a << (27 - k))
| (((frac64_a >> (k + 36)) as u32) & PxE2::<{ N }>::mask());
mask = 0x_0008_0000_0000_u64 << (k + 32 - N); if ((mask & frac64_a) != 0)
&& ((((mask - 1) & frac64_a) | ((mask << 1) & frac64_a)) != 0)
{
ui_a += 0x_8000_0000_u32 >> (N - 1);
}
}
ui_a
}
}