unums 0.0.1

A crate for using Unums
Documentation
#![allow(dead_code)]

pub trait ToUnumHelpers {
    fn abs_val(self) -> Self;
    // replaces: scale
    fn floor_log_2_abs(self) -> i8;
    fn ceil_log_2_abs(self) -> i8;
    // replaces: ne
    fn min_exp_bits(self) -> i8;
}

macro_rules! ImplIntToUnumHelpers {
    ($T:ty, $E:path) => {
        impl ToUnumHelpers for $T {
            #[inline(always)]
            fn abs_val(self) -> $T {
                $E(self)
            }
            fn floor_log_2_abs(self) -> i8 {
                let mut result = 1;
                let mut comp_val : $T = 2 as $T;
                let abs_self = self.abs_val();
                loop {
                    //println!("n: {}, result: {}, comp_val: {}", n, result, comp_val);
                    if abs_self < comp_val { break };
                    result += 1;
                    comp_val *= 2 as $T;
                }
                result - 1
            }

            fn ceil_log_2_abs(self) -> i8 {
                let mut result = 0;
                let mut comp_val : $T = 1 as $T;
                let abs_self = self.abs_val();
                loop {
                    //println!("n: {}, result: {}, comp_val: {}", n, result, comp_val);
                    if abs_self <= comp_val { break };
                    result += 1;
                    comp_val *= 2 as $T;
                }
                result
            }

            fn min_exp_bits(self) -> i8 {
                let self_abs_log_2 = self.floor_log_2_abs();
                if self_abs_log_2 == 1 || self == (0 as $T) {
                    1
                } else {
                    let n1 = 1 + (self_abs_log_2 - 1).abs();
                    let n2 = n1.ceil_log_2_abs() + 1;
                    n2
                }
            }

        }
    };
}

ImplIntToUnumHelpers!(isize, isize::abs);
ImplIntToUnumHelpers!(i8,  i8::abs);
ImplIntToUnumHelpers!(i16, i16::abs);
ImplIntToUnumHelpers!(i32, i32::abs);
ImplIntToUnumHelpers!(i64, i64::abs);

#[inline(always)]
fn mirror<T>(x: T) -> T {x}

ImplIntToUnumHelpers!(usize, mirror);
ImplIntToUnumHelpers!(u8,  mirror);
ImplIntToUnumHelpers!(u16, mirror);
ImplIntToUnumHelpers!(u32, mirror);
ImplIntToUnumHelpers!(u64, mirror);




macro_rules! ImplFloatToUnumHelpers {
    ($T:ty, $E:path) => {
        impl ToUnumHelpers for $T {
            #[inline(always)]
            fn abs_val(self) -> $T {
                $E(self)
            }
            fn floor_log_2_abs(self) -> i8 {
                let mut result = 1;
                let mut comp_val : $T = 2;
                let abs_self = self.abs_val();
                loop {
                    //println!("n: {}, result: {}, comp_val: {}", n, result, comp_val);
                    if abs_self < comp_val { break };
                    result += 1;
                    comp_val *= 2;
                }
                result - 1
            }

            fn ceil_log_2_abs(self) -> i8 {
                let mut result = 0;
                let mut comp_val : $T = 1;
                let abs_self = self.abs_val();
                loop {
                    //println!("n: {}, result: {}, comp_val: {}", n, result, comp_val);
                    if abs_self <= comp_val { break };
                    result += 1;
                    comp_val *= 2;
                }
                result
            }

            fn min_exp_bits(self) -> i8 {
                let self_abs_log_2 = self.floor_log_2_abs();
                if self_abs_log_2 == 1 || self == 0 {
                    1
                } else {
                    let n1 = 1 + (self_abs_log_2 - 1).abs();
                    let n2 = n1.ceil_log_2_abs() + 1;
                    n2
                }
            }

        }
    };
}

ImplIntToUnumHelpers!(f32, f32::abs);
ImplIntToUnumHelpers!(f64, f64::abs);


/////////////// TESTS ///////////////

macro_rules! create_test {
    ($T:ty, $test_name:ident, $func:path, $in_val:expr, $out_val: expr) => {
        #[test]
        fn $test_name() { assert_eq!($func($in_val as $T), $out_val); }
    };
}

macro_rules! test_floor_log_2_abs {
    ($T:ty, $( [ $test_name:ident, $in_val:expr, $out_val:expr ], )* ) => {
        mod floor_log_2_abs {
            #[allow(unused_imports)]
            #[allow(unused_variables)]
            use super::super::ToUnumHelpers;
            $( create_test!($T, $test_name, ToUnumHelpers::floor_log_2_abs, $in_val, $out_val); )*
        }
    };
}


macro_rules! test_ceil_log_2_abs {
    ($T:ty, $( [ $test_name:ident, $in_val:expr, $out_val:expr ], )* ) => {
        mod ceil_log_2_abs {
            #[allow(unused_imports)]
            #[allow(unused_variables)]
            use super::super::ToUnumHelpers;
            $( create_test!($T, $test_name, ToUnumHelpers::ceil_log_2_abs, $in_val, $out_val); )*
        }
    };
}



macro_rules! create_to_unum_helper_test_mod {
    ($T:ty, $test_mod:ident, max=127, neg = True) => {
        mod $test_mod {
            test_floor_log_2_abs!($T, [_0, 0, 0],
                                      [pos_1, 1, 0],
                                      [neg_1 , -1, 0],
                                      [pos_2, 2, 1],
                                      [neg_2 , -2, 1],
                                      [pos_3, 3, 1],
                                      [neg_3, -3, 1],
                                      );
            test_ceil_log_2_abs!($T, [_0, 0, 0],
                                     [pos_1, 1, 0],
                                     [neg_1 , -1, 0],
                                     [pos_2, 2, 1],
                                     [neg_2 , -2, 1],
                                     [pos_3, 3, 2],
                                     [neg_3, -3, 2],
                                     );
        }
    };
    ($T:ty, $test_mod:ident, max=127, neg = False) => {
        mod $test_mod {
            test_floor_log_2_abs!($T, [_0, 0, 0],
                                      [pos_1, 1, 0],
                                      [pos_2, 2, 1],
                                      [pos_3, 3, 1],
                                      );
            test_ceil_log_2_abs!($T, [_0, 0, 0],
                                     [pos_1, 1, 0],
                                     [pos_2, 2, 1],
                                     [pos_3, 3, 2],
                                     );
        }
    };
    ($T:ty, $test_mod:ident, max=32767, neg = True) => {
        mod $test_mod {
            test_floor_log_2_abs!($T, [_0, 0, 0],
                                      [pos_1, 1, 0],
                                      [neg_1 , -1, 0],
                                      [pos_2, 2, 1],
                                      [neg_2 , -2, 1],
                                      [pos_3, 3, 1],
                                      [neg_3, -3, 1],
                                      [pos_4101, 4101, 12],
                                      [neg_4101, -4101, 12],
                                      );
            test_ceil_log_2_abs!($T, [_0, 0, 0],
                                     [pos_1, 1, 0],
                                     [neg_1 , -1, 0],
                                     [pos_2, 2, 1],
                                     [neg_2 , -2, 1],
                                     [pos_3, 3, 2],
                                     [neg_3, -3, 2],
                                     [pos_4101, 4101, 13],
                                     [neg_4101, -4101, 13],
                                     );
        }
    };
    ($T:ty, $test_mod:ident, max=32767, neg = False) => {
        mod $test_mod {
            test_floor_log_2_abs!($T, [_0, 0, 0],
                                      [pos_1, 1, 0],
                                      [pos_2, 2, 1],
                                      [pos_3, 3, 1],
                                      [pos_4101, 4101, 12],
                                      );
            test_ceil_log_2_abs!($T, [_0, 0, 0],
                                     [pos_1, 1, 0],
                                     [pos_2, 2, 1],
                                     [pos_3, 3, 2],
                                     [pos_4101, 4101, 13],
                                     );
        }
    };

}

create_to_unum_helper_test_mod!(isize, test_isize, max=32767, neg=True);
create_to_unum_helper_test_mod!(i8,  test_i8,  max=127,   neg=True);
create_to_unum_helper_test_mod!(i16, test_i16, max=32767, neg=True);
create_to_unum_helper_test_mod!(i32, test_i32, max=32767, neg=True);
create_to_unum_helper_test_mod!(i64, test_i64, max=32767, neg=True);

create_to_unum_helper_test_mod!(usize, test_usize, max=32767, neg=False);
create_to_unum_helper_test_mod!(u8,  test_u8,  max=127,   neg=False);
create_to_unum_helper_test_mod!(u16, test_u16, max=32767, neg=False);
create_to_unum_helper_test_mod!(u32, test_u32, max=32767, neg=False);
create_to_unum_helper_test_mod!(u64, test_u64, max=32767, neg=False);

#[cfg(test)]
mod tests {

    //#[test]
    //fn floor_log_2_abs_i32_0() { assert_eq!(0_i32.floor_log_2_abs(),0); }
    /*
    #[test]
    fn floor_log_2_abs_i32_1() { assert_eq!(floor_log_2_abs_i32(1),0); }
    
    #[test]
    fn floor_log_2_abs_i32_neg_1() { assert_eq!(floor_log_2_abs_i32(-1),0); }
    
    #[test]
    fn floor_log_2_abs_i32_2() { assert_eq!(floor_log_2_abs_i32(2),1); }
    
    #[test]
    fn floor_log_2_abs_i32_neg_2() { assert_eq!(floor_log_2_abs_i32(-2),1); }
    
    #[test]
    fn floor_log_2_abs_i32_3() { assert_eq!(floor_log_2_abs_i32(3),1); }
    
    #[test]
    fn floor_log_2_abs_i32_neg_3() { assert_eq!(floor_log_2_abs_i32(-3),1); }
    
    #[test]
    fn floor_log_2_abs_i32_4101() { assert_eq!(floor_log_2_abs_i32(4101),12); }
    
    #[test]
    fn floor_log_2_abs_i32_neg_4101() { assert_eq!(floor_log_2_abs_i32(-4101),12); }
   
    // ceil_log_2_abs_i32
    #[test]
    #[should_panic]
    fn ceil_log_2_abs_i32_0() { assert_eq!(ceil_log_2_abs_i32(0),0); }
    
    #[test]
    fn ceil_log_2_abs_i32_1() { assert_eq!(ceil_log_2_abs_i32(1),1); }
    
    #[test]
    fn ceil_log_2_abs_i32_neg_1() { assert_eq!(ceil_log_2_abs_i32(-1),1); }
    
    #[test]
    fn ceil_log_2_abs_i32_2() { assert_eq!(ceil_log_2_abs_i32(2),1); }
    
    #[test]
    fn ceil_log_2_abs_i32_neg_2() { assert_eq!(ceil_log_2_abs_i32(-2),1); }
    
    #[test]
    fn ceil_log_2_abs_i32_3() { assert_eq!(ceil_log_2_abs_i32(3),2); }
    
    #[test]
    fn ceil_log_2_abs_i32_neg_3() { assert_eq!(ceil_log_2_abs_i32(-3),2); }
    
    #[test]
    fn ceil_log_2_abs_i32_4101() { assert_eq!(ceil_log_2_abs_i32(4101),13); }
    
    #[test]
    fn ceil_log_2_abs_i32_neg_4101() { assert_eq!(ceil_log_2_abs_i32(-4101),13); }
   
    // min_exp_bits_i32 
    #[test]
    fn min_exp_bits_i32_0() { assert_eq!(min_exp_bits_i32(0),1) }
   
    #[test]
    fn min_exp_bits_i32_1() { assert_eq!(min_exp_bits_i32(1),2) }
   
    #[test]
    fn min_exp_bits_i32_neg_1() { assert_eq!(min_exp_bits_i32(-1),2) }
   
    #[test]
    fn min_exp_bits_i32_2() { assert_eq!(min_exp_bits_i32(2),1) }
   
    #[test]
    fn min_exp_bits_i32_neg_2() { assert_eq!(min_exp_bits_i32(-2),1) }
   
    #[test]
    fn min_exp_bits_i32_3() { assert_eq!(min_exp_bits_i32(3),1) }
   
    #[test]
    fn min_exp_bits_i32_neg_3() { assert_eq!(min_exp_bits_i32(-3),1) }
   
    #[test]
    fn min_exp_bits_i32_4101() { assert_eq!(min_exp_bits_i32(4101),5) }
   
    #[test]
    fn min_exp_bits_i32_neg_4101() { assert_eq!(min_exp_bits_i32(-4101),5) }
    */
}