use crate::params::params::{P, W};
const V: u32 = 0x80000000;
pub fn i16_nonzero_mask(x: i16) -> i16 {
let u = x as u16;
let mut v = u as u32;
v = if v == 0 { 0 } else { !v.wrapping_add(1) };
v >>= 31;
if v != 0 {
-1
} else {
0
}
}
pub fn i16_negative_mask(x: i16) -> i16 {
let u = x as u16;
let u = u >> 15;
-(u as i16)
}
pub fn u32_divmod_u14(x: u32, m: u16) -> (u32, u16) {
let mut v = V;
let mut qpart;
v /= m as u32;
let mut q = 0;
qpart = ((x as u64 * v as u64) >> 31) as u32;
let new_x = x.wrapping_sub(qpart * m as u32);
q += qpart;
qpart = (new_x as u64 * v as u64) as u32 >> 31;
let final_x = new_x.wrapping_sub(qpart * m as u32);
q += qpart;
let sub_x = final_x.wrapping_sub(m as u32);
q += 1;
let mask = if sub_x >> 31 != 0 { u32::MAX } else { 0 };
let added_x = sub_x.wrapping_add(mask & m as u32);
let final_q = q.wrapping_add(mask);
(final_q, added_x as u16)
}
pub fn i32_divmod_u14(x: i32, m: u16) -> (u32, u32) {
let px = V;
let (mut uq, ur) = u32_divmod_u14(px.wrapping_add(x as u32), m);
let mut ur = ur as u32;
let (uq2, ur2) = u32_divmod_u14(px, m);
ur = ur.wrapping_sub(ur2 as u32);
uq = uq.wrapping_sub(uq2);
let mask: u32 = if ur >> 15 != 0 { u32::MAX } else { 0 };
ur = ur.wrapping_add(mask & m as u32);
uq = uq.wrapping_add(mask);
(uq, ur)
}
pub fn i32_mod_u14(x: i32, m: u16) -> u32 {
i32_divmod_u14(x, m).1
}
pub fn u32_mod_u14(x: u32, m: u16) -> u16 {
u32_divmod_u14(x, m).1
}
pub fn weightw_mask(r: &[i8; P]) -> i16 {
let weight: i16 = r.iter().map(|&x| (x & 1) as i16).sum();
i16_nonzero_mask(weight - W as i16)
}
#[test]
fn test_i32_divmod_u14() {
assert_eq!(i32_divmod_u14(100, 30), (3, 10));
assert_eq!(i32_divmod_u14(-100, 30), (4294967292, 20)); }
#[test]
fn test_u32_divmod_u14() {
assert_eq!(u32_divmod_u14(100, 30), (3, 10));
assert_eq!(u32_divmod_u14(223, 300), (0, 223));
assert_eq!(u32_divmod_u14(V, 3000), (715827, 2648));
}
#[test]
fn test_nonzero_mask() {
assert_eq!(i16_nonzero_mask(0), 0);
assert_eq!(i16_nonzero_mask(42), -1);
assert_eq!(i16_nonzero_mask(-42), -1);
assert_eq!(i16_nonzero_mask(i16::MIN), -1);
assert_eq!(i16_nonzero_mask(i16::MAX), -1);
assert_eq!(i16_nonzero_mask(33), -1);
assert_eq!(i16_nonzero_mask(-33), -1);
assert_eq!(i16_nonzero_mask(28), -1);
assert_eq!(i16_nonzero_mask(-28), -1);
assert_eq!(i16_nonzero_mask(12345), -1);
assert_eq!(i16_nonzero_mask(-12345), -1);
}