fp/
limb.rs

1use crate::constants::BITS_PER_LIMB;
2pub(crate) use crate::constants::Limb;
3
4/// A struct containing the information required to access a specific entry in an array of `Limb`s.
5#[derive(Debug, Copy, Clone)]
6pub(crate) struct LimbBitIndexPair {
7    pub(crate) limb: usize,
8    pub(crate) bit_index: usize,
9}
10
11/// Read an array of `Limb`s.
12pub(crate) fn from_bytes(limbs: &mut [Limb], data: &mut impl std::io::Read) -> std::io::Result<()> {
13    if cfg!(target_endian = "little") {
14        let num_bytes = std::mem::size_of_val(limbs);
15        let buf: &mut [u8] =
16            unsafe { std::slice::from_raw_parts_mut(limbs.as_mut_ptr() as *mut u8, num_bytes) };
17        data.read_exact(buf)
18    } else {
19        for entry in limbs {
20            let mut bytes: [u8; size_of::<Limb>()] = [0; size_of::<Limb>()];
21            data.read_exact(&mut bytes)?;
22            *entry = Limb::from_le_bytes(bytes);
23        }
24        Ok(())
25    }
26}
27
28/// Store an array of `Limb`s.
29pub(crate) fn to_bytes(limbs: &[Limb], data: &mut impl std::io::Write) -> std::io::Result<()> {
30    if cfg!(target_endian = "little") {
31        let num_bytes = std::mem::size_of_val(limbs);
32        let buf: &[u8] =
33            unsafe { std::slice::from_raw_parts(limbs.as_ptr() as *const u8, num_bytes) };
34        data.write_all(buf)
35    } else {
36        for limb in limbs {
37            let bytes = limb.to_le_bytes();
38            data.write_all(&bytes)?;
39        }
40        Ok(())
41    }
42}
43
44pub(crate) fn sign_rule(mut target: Limb, mut source: Limb) -> u32 {
45    let mut result = 0;
46    let mut n = 1;
47    // Empirically, the compiler unrolls this loop because BITS_PER_LIMB is a constant.
48    while 2 * n < BITS_PER_LIMB {
49        // This is 1 every 2n bits.
50        let mask: Limb = !0 / ((1 << (2 * n)) - 1);
51        result ^= (mask & (source >> n) & target).count_ones() % 2;
52        source = source ^ (source >> n);
53        target = target ^ (target >> n);
54        n *= 2;
55    }
56    result ^= (1 & (source >> (BITS_PER_LIMB / 2)) & target) as u32;
57    result
58}