#![allow(dead_code)]
pub trait ToUnumHelpers {
fn abs_val(self) -> Self;
fn floor_log_2_abs(self) -> i8;
fn ceil_log_2_abs(self) -> i8;
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 {
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 {
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 {
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 {
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);
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 {
}