1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use super::*;

// vector element
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct BitSharing64(pub(super) u64);

impl LocalOperation for BitSharing64 {}

impl Add for BitSharing64 {
    type Output = Self;

    #[allow(clippy::suspicious_arithmetic_impl)]
    fn add(self, other: Self) -> Self::Output {
        Self(self.0 ^ other.0)
    }
}

impl Sub for BitSharing64 {
    type Output = Self;

    #[allow(clippy::suspicious_arithmetic_impl)]
    fn sub(self, other: Self) -> Self::Output {
        self + other
    }
}

impl Mul for BitSharing64 {
    type Output = Self;

    #[allow(clippy::suspicious_arithmetic_impl)]
    fn mul(self, other: Self) -> Self::Output {
        Self(self.0 & other.0)
    }
}

impl RingElement for BitSharing64 {
    const ONE: Self = Self(0xffff_ffff_ffff_ffff);
    const ZERO: Self = Self(0x0);
}

impl RingModule<BitScalar> for BitSharing64 {
    const DIMENSION: usize = 64;

    #[inline(always)]
    fn action(&self, s: BitScalar) -> Self {
        debug_assert!(s.0 < 2, "scalar is not bit");
        BitSharing64(if s.0 == 0 { 0 } else { self.0 })
    }

    fn get(&self, i: usize) -> BitScalar {
        debug_assert!(i < 64);
        let i = 63 - i;
        BitScalar(((self.0 >> i) & 1) as u8)
    }

    fn set(&mut self, i: usize, s: BitScalar) {
        debug_assert!(i < 64);
        let i = 63 - i;
        self.0 &= !(1 << i);
        self.0 |= (s.0 as u64) << i;
    }

    /*
    #[inline(always)]
    fn get(&self, n: usize) -> Self::Scalar {
        debug_assert!(n < Self::DIMENSION, "get out of range");
        let n = 63 - n;
        BitScalar(((self.0 >> n) & 1) as u8)
    }

    #[inline(always)]
    fn set(&self, s: Self::Scalar, n: usize) -> Self {
        debug_assert!(s.0 < 2, "scalar is not bit");
        debug_assert!(n < Self::DIMENSION, "set out of range");
        let n = 63 - n;

        let mut r = self.0;
        r &= !(1 << n); // clear nth bit
        r |= (s.0 as u64) << n; // set nth bit
        BitSharing64(r)
    }
    */
}

impl Serializable for BitSharing64 {
    fn serialize<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        w.write_all(&self.0.to_le_bytes())
    }
}

impl Sharing<BitScalar> for BitSharing64 {
    // Reconstruction for the share module is the sum of the ring elements
    // This can be implemented by xoring all the bits together,
    // but calculating the parity via count_ones is faster on x86.
    fn reconstruct(&self) -> BitScalar {
        BitScalar((self.0.count_ones() & 1) as u8)
    }
}