use std::ops::{Div, Rem, Shr};
#[derive(Debug, Default, Clone, Copy)]
pub struct OddDivider<T> {
pub divisor: T,
pub multiplier: T,
pub shift: u32,
}
impl<T> OddDivider<T>
where
T: Copy + Shr<u32, Output = T> + Div<Output = T> + Rem<Output = T> + Arithmetic,
{
#[inline(always)]
fn div_non_power_of_two(&self, x: T) -> T {
let (_, hi) = x.widening_mul(self.multiplier);
let y = ((x.wrapping_sub(hi)) >> 1).wrapping_add(hi);
y >> self.shift
}
#[inline(always)]
pub fn div_rem(&self, x: T) -> (T, T) {
let q = self.div_non_power_of_two(x);
let r = x.wrapping_sub(q.wrapping_mul(self.divisor));
(q, r)
}
}
pub trait Arithmetic: Sized {
fn wrapping_add(self, other: Self) -> Self;
fn wrapping_sub(self, other: Self) -> Self;
fn wrapping_mul(self, other: Self) -> Self;
fn widening_mul(self, other: Self) -> (Self, Self);
}
impl Arithmetic for u16 {
#[inline(always)]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline(always)]
fn wrapping_sub(self, other: Self) -> Self {
self.wrapping_sub(other)
}
#[inline(always)]
fn wrapping_mul(self, other: Self) -> Self {
self.wrapping_mul(other)
}
#[inline(always)]
fn widening_mul(self, other: Self) -> (Self, Self) {
self.carrying_mul(other, 0)
}
}
impl Arithmetic for u32 {
#[inline(always)]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline(always)]
fn wrapping_sub(self, other: Self) -> Self {
self.wrapping_sub(other)
}
#[inline(always)]
fn wrapping_mul(self, other: Self) -> Self {
self.wrapping_mul(other)
}
#[inline(always)]
fn widening_mul(self, other: Self) -> (Self, Self) {
self.carrying_mul(other, 0)
}
}
impl Arithmetic for u64 {
#[inline(always)]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline(always)]
fn wrapping_sub(self, other: Self) -> Self {
self.wrapping_sub(other)
}
#[inline(always)]
fn wrapping_mul(self, other: Self) -> Self {
self.wrapping_mul(other)
}
#[inline(always)]
fn widening_mul(self, other: Self) -> (Self, Self) {
self.carrying_mul(other, 0)
}
}