use std::marker::PhantomData;
use std::cmp;
use std::ops;
use std::fmt;
use std::hash;
use std::convert;
use std::i32;
pub struct _1;
pub struct _2;
pub struct _3;
pub struct _4;
pub struct _5;
pub struct _6;
pub struct _7;
pub struct _8;
pub struct _9;
pub struct _10;
pub struct _11;
pub struct _12;
pub struct _13;
pub struct _14;
pub struct _15;
pub struct _16;
pub struct _24;
pub struct _32;
pub trait FractionalBits { fn bits() -> u32; }
impl FractionalBits for _1 { fn bits() -> u32 { 1 } }
impl FractionalBits for _2 { fn bits() -> u32 { 2 } }
impl FractionalBits for _3 { fn bits() -> u32 { 3 } }
impl FractionalBits for _4 { fn bits() -> u32 { 4 } }
impl FractionalBits for _5 { fn bits() -> u32 { 5 } }
impl FractionalBits for _6 { fn bits() -> u32 { 6 } }
impl FractionalBits for _7 { fn bits() -> u32 { 7 } }
impl FractionalBits for _8 { fn bits() -> u32 { 8 } }
impl FractionalBits for _9 { fn bits() -> u32 { 9 } }
impl FractionalBits for _10 { fn bits() -> u32 { 10 } }
impl FractionalBits for _11 { fn bits() -> u32 { 11 } }
impl FractionalBits for _12 { fn bits() -> u32 { 12 } }
impl FractionalBits for _13 { fn bits() -> u32 { 13 } }
impl FractionalBits for _14 { fn bits() -> u32 { 14 } }
impl FractionalBits for _15 { fn bits() -> u32 { 15 } }
impl FractionalBits for _16 { fn bits() -> u32 { 16 } }
impl FractionalBits for _24 { fn bits() -> u32 { 24 } }
impl FractionalBits for _32 { fn bits() -> u32 { 32 } }
pub struct Fp32<F = _16> {
bits: i32,
_fract: PhantomData<F>,
}
pub struct Fp64<F = _24> {
bits: i64,
_fract: PhantomData<F>,
}
macro_rules! impl_fixed_point {
($name:ident: $bits_type:ty) => {
impl<F: FractionalBits> $name<F> {
#[inline]
pub fn raw(self) -> $bits_type { self.bits }
#[inline]
pub fn from_raw(bits: $bits_type) -> Self { $name { bits: bits, _fract: PhantomData } }
#[inline]
pub fn zero() -> Self { Self::from_raw(0) }
#[inline]
pub fn is_zero(self) -> bool { self.bits == 0 }
#[inline]
pub fn epsilon() -> Self { Self::from_raw(1) }
#[inline]
pub fn from_f32(val: f32) -> Self { Self::from_raw((val * (1 << F::bits()) as f32) as $bits_type) }
#[inline]
pub fn to_f32(self) -> f32 { self.bits as f32 / (1 << F::bits()) as f32 }
#[inline]
pub fn from_f64(val: f64) -> Self { Self::from_raw((val * (1 << F::bits()) as f64) as $bits_type) }
#[inline]
pub fn to_f64(self) -> f64 { self.bits as f64 / (1 << F::bits()) as f64 }
#[inline]
pub fn sign(self) -> $bits_type { self.bits / self.bits.abs() }
#[inline]
pub fn rem(self, other: Self) -> Self { Self::from_raw(self.bits % other.bits) }
#[inline]
pub fn min(self, other: Self) -> Self { Self::from_raw(cmp::min(self.bits, other.bits)) }
#[inline]
pub fn max(self, other: Self) -> Self { Self::from_raw(cmp::max(self.bits, other.bits)) }
#[inline]
pub fn abs(self) -> Self { Self::from_raw(self.bits.abs()) }
#[inline]
pub fn to_fixed<NewF: FractionalBits>(self) -> $name<NewF> {
return if F::bits() == NewF::bits() { $name::from_raw(self.bits) }
else if F::bits() < NewF::bits() { $name::from_raw(self.bits << (NewF::bits() - F::bits())) }
else { $name::from_raw(self.bits >> (F::bits() - NewF::bits())) };
}
}
impl<F> Copy for $name<F> {}
impl<F> Clone for $name<F> { fn clone(&self) -> Self { *self } }
impl<F> PartialEq for $name<F> { fn eq(&self, other: &Self) -> bool { self.bits == other.bits } }
impl<F> Eq for $name<F> {}
impl<F:FractionalBits> fmt::Debug for $name<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_f32().fmt(f) }
}
impl<F:FractionalBits> fmt::Display for $name<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_f32().fmt(f) }
}
impl<F> hash::Hash for $name<F> {
fn hash<H: hash::Hasher>(&self, h: &mut H) {
self.bits.hash(h);
}
}
impl<F: FractionalBits> PartialOrd for $name<F> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.bits.partial_cmp(&other.bits)
}
}
impl<F: FractionalBits> Ord for $name<F> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering { self.bits.cmp(&other.bits) }
}
impl<F: FractionalBits> ops::Add<$name<F>> for $name<F> {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
$name::from_raw(self.bits + other.bits)
}
}
impl<F: FractionalBits> ops::Sub<$name<F>> for $name<F> {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
$name::from_raw(self.bits - other.bits)
}
}
impl<F: FractionalBits> ops::Mul<$name<F>> for $name<F> {
type Output = Self;
#[inline]
fn mul(self, other: Self) -> Self {
$name::from_raw(((self.bits as i64 * other.bits as i64) >> F::bits()) as $bits_type)
}
}
impl<F: FractionalBits> ops::Neg for $name<F> {
type Output = Self;
#[inline]
fn neg(self) -> Self { $name::from_raw(-self.bits) }
}
impl<F: FractionalBits> ops::Mul<$bits_type> for $name<F> {
type Output = $name<F>;
#[inline]
fn mul(self, other: $bits_type) -> Self {
$name::from_raw(self.bits * other)
}
}
impl<F: FractionalBits> ops::Div<$bits_type> for $name<F> {
type Output = $name<F>;
#[inline]
fn div(self, other: $bits_type) -> Self {
$name::from_raw(self.bits / other)
}
}
impl<F: FractionalBits> ops::AddAssign<$name<F>> for $name<F> {
#[inline]
fn add_assign(&mut self, other: Self) { self.bits += other.bits; }
}
impl<F: FractionalBits> ops::SubAssign<$name<F>> for $name<F> {
#[inline]
fn sub_assign(&mut self, other: Self) { self.bits -= other.bits; }
}
impl<F: FractionalBits> convert::Into<f32> for $name<F> {
#[inline]
fn into(self) -> f32 { self.to_f32() }
}
impl<F: FractionalBits> convert::From<f32> for $name<F> {
#[inline]
fn from(val: f32) -> Self { Self::from_f32(val) }
}
impl<F: FractionalBits> convert::Into<f64> for $name<F> {
#[inline]
fn into(self) -> f64 { self.to_f64() }
}
impl<F: FractionalBits> convert::From<f64> for $name<F> {
#[inline]
fn from(val: f64) -> Self { Self::from_f64(val) }
}
}
}
impl_fixed_point!(Fp64: i64);
impl_fixed_point!(Fp32: i32);
impl<F: FractionalBits> Fp32<F> {
#[inline]
pub fn one() -> Self { Fp32::from_i32(1) }
#[inline]
pub fn from_i32(val: i32) -> Self { Fp32::from_raw(val << F::bits()) }
#[inline]
pub fn truncate_to_i32(self) -> i32 { self.bits >> F::bits() }
#[inline]
pub fn mul_div(self, m: Self, d: Self) -> Self {
Fp32::from_raw((self.bits as i64 * m.bits as i64 / d.bits as i64) as i32)
}
pub fn min_val() -> Self { Fp32::from_raw(i32::MIN) }
pub fn max_val() -> Self { Fp32::from_raw(i32::MAX) }
pub fn to_fp64<NewF: FractionalBits>(self) -> Fp64<NewF> {
let tmp: Fp64<F> = Fp64::from_raw(self.bits as i64);
return tmp.to_fixed();
}
}
impl<F: FractionalBits> ops::Div<Fp32<F>> for Fp32<F> {
type Output = Self;
fn div(self, other: Self) -> Self {
let self64: i64 = (self.bits as i64) << 32;
let other64: i64 = other.bits as i64;
Fp32::from_raw(((self64 / other64) >> (32 - F::bits())) as i32)
}
}
impl<F: FractionalBits> Fp64<F> {
#[inline]
pub fn one() -> Self { Fp64::from_i64(1) }
#[inline]
pub fn from_i64(val: i64) -> Self { Fp64::from_raw(val << F::bits()) }
#[inline]
pub fn truncate_to_i64(self) -> i64 { self.bits >> F::bits() }
#[inline]
pub fn mul_div(self, m: Self, d: Self) -> Self { Fp64::from_raw(self.bits * m.bits / d.bits) }
pub fn to_fp32<NewF: FractionalBits>(self) -> Fp32<NewF> {
let tmp = self.to_fixed::<NewF>();
return Fp32::from_raw(tmp.bits as i32);
}
}
impl<F: FractionalBits> ops::Div<Fp64<F>> for Fp64<F> {
type Output = Self;
fn div(self, other: Self) -> Self {
Fp64::from_raw((self.bits / other.bits) << F::bits())
}
}
#[test]
fn test_fp32() {
pub fn fixed<F: FractionalBits>(val: f32) -> Fp32<F> { Fp32::from_f32(val) }
pub type Fp = Fp32<_16>;
let zero = fixed(0.0);
let one = fixed(1.0);
let minus_one = Fp::from_f32(-1.0);
let ten = Fp::from_f32(10.0);
let a = Fp::from_f32(1.5);
println!("0: {:?} | {}", zero, zero.bits);
println!("1: {:?} | {}", one, one.bits);
println!("-1: {:?} | {}", minus_one, minus_one.bits);
println!("10: {:?} | {}", ten, ten.bits);
println!("1.5: {:?} | {}", a, a.bits);
println!("1.5 * 10: {:?} | {}", a * ten, (a*ten).bits);
println!("0.5 / 2: {:?} | {}", Fp::from_f32(0.5) / fixed(2.0), (Fp::from_f32(0.5) / fixed(2.0)).bits);
println!("-0.5 / -2: {:?} | {}", Fp::from_f32(-0.5) / fixed(-2.0), (Fp::from_f32(-0.5) / fixed(-2.0)).bits);
println!("-0.5 / 2: {:?} | {}", Fp::from_f32(-0.5) / fixed(2.0), (Fp::from_f32(-0.5) / fixed(2.0)).bits);
println!("-0.5 * 2: {:?} | {}", Fp::from_f32(-0.5) * fixed(2.0), (Fp::from_f32(-0.5) * fixed(2.0)).bits);
println!("0.5 / -2: {:?} | {}", Fp::from_f32(0.5) / fixed(-2.0), (Fp::from_f32(0.5) / fixed(-2.0)).bits);
println!("bits {}", 1<<8 );
assert_eq!(Fp::from_i32(1), one);
assert_eq!(Fp::one(), one);
assert_eq!(Fp::from_i32(-1), minus_one);
assert_eq!(Fp::from_i32(0), zero);
assert_eq!(a.truncate_to_i32(), 1);
assert_eq!(one.sign(), 1);
assert_eq!(minus_one.sign(), -1);
assert_eq!(a.rem(one), Fp::from_f32(0.5));
assert_eq!(-one, minus_one);
assert_eq!(one.to_fixed::<_8>().truncate_to_i32(), one.truncate_to_i32());
assert_eq!(one.to_fixed::<_2>().truncate_to_i32(), one.truncate_to_i32());
println!("min {} max {}", Fp::min_val(), Fp::max_val());
}