use epsi::EquisizedPrimitiveSignedIntExt as EPSI;
try_impl_unsafe_generic_const_fn_for_trait!(
MidpointViaNaiveMidpointDiffExt::midpoint_via_naive_midpoint_diff
);
pub trait MidpointViaNaiveMidpointDiffExt {
unsafe fn midpoint_via_naive_midpoint_diff(&self , rhs_ref: &Self) -> Self;
}
macro_rules! impl_midpoint_fn_for_t {
() => {
unsafe fn midpoint_via_naive_midpoint_diff(&self, rhs_ref: &Self) -> Self {
let (lhs, rhs) = (*self, *rhs_ref);
let arg_diff = rhs.wrapping_sub(lhs) as <Self as EPSI>::EquisizedPrimitiveSignedInt;
let midpoint_diff = (arg_diff / 2) as Self;
lhs + midpoint_diff
}
};
}
impl_for_all_prim_ints!(
trait = MidpointViaNaiveMidpointDiffExt,
fn macro = impl_midpoint_fn_for_t
);
#[cfg(test)]
mod tests {
use crate::MidpointViaNaiveMidpointDiffExt;
use epsi::EquisizedPrimitiveSignedIntExt as EPSI;
#[test]
fn midpoint_via_naive_midpoint_diff_rounds_towards_left_arg_including_when_args_are_positive() {
let result: i32 = unsafe { 2.midpoint_via_naive_midpoint_diff(&3) };
assert_eq!(result, 2);
}
#[test]
fn midpoint_via_naive_midpoint_diff_rounds_towards_left_arg_including_when_args_are_negative() {
let result: i32 = unsafe { (-3).midpoint_via_naive_midpoint_diff(&-2) };
assert_eq!(result, -3);
}
#[test]
fn midpoint_via_naive_midpoint_diff_may_return_incorrect_midpoint_for_args_with_diff_signs() {
let result = unsafe { (i32::MIN).midpoint_via_naive_midpoint_diff(&i32::MAX) };
assert!(result != -1);
assert_eq!(result, i32::MIN);
}
#[test]
fn midpoint_via_naive_midpoint_diff_work_when_rhs_sub_lhs_equals_max_of_equisized_int() {
let rhs = <u32 as EPSI>::EquisizedPrimitiveSignedInt::MAX as u32;
let lhs = 0u32;
let result: u32 = unsafe { (lhs).midpoint_via_naive_midpoint_diff(&rhs) };
assert_eq!(result, (i32::MAX / 2) as u32);
}
#[test]
fn midpoint_via_naive_midpoint_diff_work_when_rhs_sub_lhs_equals_min_of_equisized_int() {
let rhs = i32::MIN;
let lhs = 0i32;
let result = unsafe { (lhs).midpoint_via_naive_midpoint_diff(&rhs) };
assert_eq!(result, i32::MIN / 2);
}
}