use super::utils::ToUnumHelpers;
use super::env;
use std::marker::PhantomData;
#[derive(Debug)]
struct Unum<E> where E: env::UnumEnv {
env: PhantomData<E>,
sign: bool,
exp_bits: u32,
frac_bits: u32,
ubit: bool,
exp_size: u8,
frac_size: u8,
}
impl<E> Unum<E> where E: env::UnumEnv {
fn nan() -> Unum<E> { Unum::zero() } fn infinity() -> Unum<E> { Unum::zero() }
fn zero() -> Unum<E> {
Unum{
env: PhantomData,
sign: true,
exp_bits: 0x00000000,
frac_bits: 0x00000000,
ubit: false,
exp_size: 0,
frac_size: 0,
}
}
fn from_i32_old(n: i32) -> Unum<E> {
match n {
0 => Unum::zero(),
_ => {
let mut counter = 0;
let n_f64 : f64 = n.into();
let mut y : f64 = n_f64.abs() / (2_f64).powi(n.floor_log_2_abs() as i32);
println!("floor_log_2_abs_i32(n) = {}", n.floor_log_2_abs());
println!("(2_f64).powi(floor_log_2_abs_i32(n)) = {}", (2_f64).powi(n.floor_log_2_abs() as i32));
println!("pre y = {}", y);
println!("pre y.floor() = {}", y.floor());
while y.floor() != y && counter < (E::f_size_size() as i32) {
counter += 1;
y *= 2_f64;
}
println!("final y = {}", y);
println!("final y.floor() = {}", y.floor());
if y == y.floor() {
let y_int : i64 = y as i64;
return Unum {
env: PhantomData,
sign: n >= 0,
exp_bits: ((n.floor_log_2_abs() as i32) + 2_i32.pow((n.min_exp_bits() as u32) - 1) -1) as u32,
frac_bits: if counter == 0 {0} else {(y_int - 2_i64.pow(y_int.floor_log_2_abs() as u32)) as u32},
ubit: false,
exp_size: (n.min_exp_bits() - 1) as u8,
frac_size: (counter - if counter>0 {1} else {0}) as u8,
}
} else {
panic!("Failed to find floor of int equal to int.")
}
}
}
}
}
macro_rules! FromIntForUnum {
($T:ty) => {
impl<E> From<$T> for Unum<E> where E: env::UnumEnv {
#[allow(unused_comparisons)]
fn from(n: $T) -> Unum<E> {
match n {
0 => Unum::zero(),
_ => {
let counter = n.floor_log_2_abs() as i32;
let y_int : i64 = n.abs_val() as i64;
Unum {
env: PhantomData,
sign: n >= 0,
exp_bits: (counter + 2_i32.pow((n.min_exp_bits() as u32) - 1) -1) as u32,
frac_bits: if counter == 0 {0} else {(y_int - 2_i64.pow(counter as u32)) as u32},
ubit: false,
exp_size: (n.min_exp_bits() - 1) as u8,
frac_size: (counter - if counter>0 {1} else {0}) as u8,
}
}
}
}
}
}
}
FromIntForUnum!(usize);
FromIntForUnum!(u8);
FromIntForUnum!(u16);
FromIntForUnum!(u32);
FromIntForUnum!(u64);
FromIntForUnum!(isize);
FromIntForUnum!(i8);
FromIntForUnum!(i16);
FromIntForUnum!(i32);
FromIntForUnum!(i64);
macro_rules! FromFloatForUnum {
($T:ty) => {
impl<E> From<$T> for Unum<E> where E: env::UnumEnv {
#[allow(unused_comparisons)]
fn from(n: $T) -> Unum<E> {
let f_zero = 0 as $T;
match n {
_ if n == f_zero => Unum::zero(),
n if n.is_nan() => Unum::nan(),
n if n.is_infinite() => Unum::infinity(),
_ => {
let counter = n.floor_log_2_abs() as i32;
let y_int : i64 = n.abs_val() as i64;
Unum {
env: PhantomData,
sign: n.is_sign_positive(),
exp_bits: (counter + 2_i32.pow((n.min_exp_bits() as u32) - 1) -1) as u32,
frac_bits: if counter == 0 {0} else {(y_int - 2_i64.pow(counter as u32)) as u32},
ubit: false,
exp_size: (n.min_exp_bits() - 1) as u8,
frac_size: (counter - if counter>0 {1} else {0}) as u8,
}
}
}
}
}
}
}
FromFloatForUnum!(f32);
FromFloatForUnum!(f64);
#[cfg(test)]
mod tests {
use super::{Unum};
use super::super::env;
#[test]
fn create_unum_from_i32() {
let _ : Unum<env::Exp3Frac4> = 0_i32.into();
}
#[test]
fn create_unum_from_i32_0() {
let un : Unum<env::Exp3Frac4> = 0_i32.into();
assert_eq!(un.sign, true);
assert_eq!(un.exp_bits, 0);
assert_eq!(un.frac_bits, 0);
assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 0);
assert_eq!(un.frac_size, 0);
}
#[test]
fn create_unum_from_i32_1() {
let un = Unum::<env::Exp3Frac4>::from(1_i32);
assert_eq!(un.sign, true);
assert_eq!(un.exp_bits, 1);
assert_eq!(un.frac_bits, 0);
assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 1);
assert_eq!(un.frac_size, 0);
}
#[test]
fn create_unum_from_i32_neg_1() {
let un = Unum::<env::Exp3Frac4>::from(-1_i32);
assert_eq!(un.sign, false);
assert_eq!(un.exp_bits, 1);
assert_eq!(un.frac_bits, 0);
assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 1);
assert_eq!(un.frac_size, 0);
}
#[test]
fn create_unum_from_i32_509() {
let un = Unum::<env::Exp3Frac4>::from(509_i32);
assert_eq!(un.sign, true);
assert_eq!(un.exp_bits, 15); assert_eq!(un.frac_bits, 253); assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 3); assert_eq!(un.frac_size, 7); }
#[test]
fn create_unum_from_i32_neg_509() {
let un = Unum::<env::Exp3Frac4>::from(-509_i32);
assert_eq!(un.sign, false);
assert_eq!(un.exp_bits, 15); assert_eq!(un.frac_bits, 253); assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 3); assert_eq!(un.frac_size, 7); }
#[test]
#[should_panic]
fn create_unum_from_i32_old_67_867_967() {
let _ = Unum::<env::Exp3Frac4>::from_i32_old(67_867_967);
}
#[test]
fn create_unum_from_i32_67_867_967() {
let un = Unum::<env::Exp3Frac4>::from(67_867_967_i32);
assert_eq!(un.sign, true);
assert_eq!(un.exp_bits, 57); assert_eq!(un.frac_bits, 759_103); assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 5); assert_eq!(un.frac_size, 25); }
#[test]
fn create_unum_from_i32_neg_67_867_967() {
let un = Unum::<env::Exp3Frac4>::from(-67_867_967_i32);
assert_eq!(un.sign, false);
assert_eq!(un.exp_bits, 57); assert_eq!(un.frac_bits, 759_103); assert_eq!(un.ubit, false);
assert_eq!(un.exp_size, 5); assert_eq!(un.frac_size, 25); }
}