use std::convert::TryFrom;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ReprError<T>(pub T);
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct s15f16(i32);
impl s15f16 {
pub const ZERO: s15f16 = s15f16(0);
pub fn from_bytes(this: i32) -> Self {
s15f16(this)
}
pub fn to_bytes(self) -> i32 {
self.0
}
}
impl fmt::Display for s15f16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let sign = self.0.signum();
let value = self.0.abs();
let whole = (value >> 16) & 0x7FFF;
let fract = value & 0xFFFF;
write!(f, "{}.", sign * whole)?;
let mut fract_float = fract as f64 / 65536.;
fract_float *= 10.;
while fract_float > 0. {
write!(f, "{}", fract_float.floor() as u8)?;
fract_float = 10. * fract_float.fract();
}
Ok(())
}
}
impl fmt::Debug for s15f16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl From<s15f16> for f64 {
fn from(this: s15f16) -> f64 {
let sign = this.0.signum() as f64;
let value = this.0.abs();
let whole = (value >> 16) & 0x7FFF;
let fract = value & 0xFFFF;
sign * (whole as f64) + (fract as f64 / 65536.)
}
}
impl TryFrom<f64> for s15f16 {
type Error = ReprError<f64>;
fn try_from(this: f64) -> Result<s15f16, ReprError<f64>> {
let sign = this.signum() as i32;
let value = this.abs();
let whole = {
let value = value.floor();
if value > 0x7FFF as f64 {
return Err(ReprError(this));
}
value as i32
};
let frac_part = value.fract();
Ok(s15f16(
sign * (((whole & 0x7FFF) << 16) | (((frac_part * 65536.) as i32) & 0xFFFF)),
))
}
}
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct u16f16(u32);
impl u16f16 {
pub const ZERO: u16f16 = u16f16(0);
pub fn from_bytes(this: u32) -> Self {
u16f16(this)
}
pub fn to_bytes(self) -> u32 {
self.0
}
}
impl fmt::Display for u16f16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let value = self.0;
let whole = (value >> 16) & 0xFFFF;
let fract = value & 0xFFFF;
write!(f, "{}.", whole)?;
let mut fract_float = fract as f64 / 65536.;
fract_float *= 10.;
while fract_float > 0. {
write!(f, "{}", fract_float.floor() as u8)?;
fract_float = 10. * fract_float.fract();
}
Ok(())
}
}
impl fmt::Debug for u16f16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl From<u16f16> for f64 {
fn from(this: u16f16) -> f64 {
this.0 as f64 / 65536.
}
}
impl TryFrom<f64> for u16f16 {
type Error = ReprError<f64>;
fn try_from(this: f64) -> Result<u16f16, ReprError<f64>> {
if this < 0. || this > 0xFFFF as f64 {
return Err(ReprError(this));
}
Ok(u16f16((this * 65536.) as u32))
}
}