use super::Q16E1;
use crate::u16_with_sign;
use crate::P16E1;
impl From<P16E1> for Q16E1 {
#[inline]
fn from(a: P16E1) -> Self {
let mut q = Self::ZERO;
q += (a, P16E1::ONE);
q
}
}
impl From<Q16E1> for P16E1 {
#[inline]
fn from(q_a: Q16E1) -> Self {
(&q_a).into()
}
}
impl From<&Q16E1> for P16E1 {
#[inline]
fn from(q_a: &Q16E1) -> Self {
q_a.to_posit()
}
}
impl Q16E1 {
pub const fn to_posit(&self) -> P16E1 {
if self.is_zero() {
return P16E1::ZERO;
} else if self.is_nar() {
return P16E1::NAR;
}
let u_z: [u64; 2] = unsafe { core::mem::transmute(self.to_bits()) };
let mut u_z = [u_z[1], u_z[0]];
let sign = (u_z[0] & 0x_8000_0000_0000_0000) != 0;
if sign {
if u_z[1] == 0 {
u_z[0] = u_z[0].wrapping_neg();
} else {
u_z[1] = u_z[1].wrapping_neg();
u_z[0] = !(u_z[0]);
}
}
let mut no_lz = 0_i8;
let mut frac64_a;
let mut bits_more = false;
if u_z[0] == 0 {
no_lz += 64;
let mut tmp = u_z[1];
while (tmp >> 63) == 0 {
no_lz += 1;
tmp <<= 1;
}
frac64_a = tmp;
} else {
let mut tmp = u_z[0];
let mut no_lztmp = 0_i8;
while (tmp >> 63) == 0 {
no_lztmp += 1;
tmp <<= 1;
}
no_lz += no_lztmp;
frac64_a = tmp;
frac64_a += u_z[1] >> (64 - no_lztmp);
if (u_z[1] << no_lztmp) != 0 {
bits_more = true;
}
}
let k_a = (71 - no_lz) >> 1;
let exp_a = 71 - no_lz - (k_a << 1);
let (regime, reg_sa, reg_a) = P16E1::calculate_regime(k_a);
let u_a = if reg_a > 14 {
if reg_sa {
0x7FFF
} else {
0x1
}
} else {
frac64_a &= 0x7FFF_FFFF_FFFF_FFFF;
let shift = reg_a + 50; let mut frac_a = (if let Some(val) = frac64_a.checked_shr(shift as u32) {
val
} else {
0
}) as u16;
let mut bit_n_plus_one = false;
if reg_a != 14 {
bit_n_plus_one = ((frac64_a >> (shift - 1)) & 0x1) != 0;
if (frac64_a << (65 - shift)) != 0 {
bits_more = true;
}
} else if frac64_a > 0 {
frac_a = 0;
bits_more = true;
}
if (reg_a == 14) && (exp_a != 0) {
bit_n_plus_one = true;
}
let mut u_a = P16E1::pack_to_ui(regime, reg_a, exp_a as u16, frac_a);
if bit_n_plus_one {
u_a += (u_a & 1) | (bits_more as u16);
}
u_a
};
P16E1::from_bits(u16_with_sign(u_a, sign))
}
}