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
use crate::integer::{BooleanBlock, IntegerRadixCiphertext, ServerKey};
impl ServerKey {
/// Returns an encryption of true if the value is even
///
/// ct is not required to have clean carries
pub fn unchecked_is_even<T>(&self, ct: &T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
ct.blocks().first().map_or_else(
|| {
// Interpret empty as being 0, which is even
self.create_trivial_boolean_block(true)
},
|first_block| {
let lut = self
.key
.generate_lookup_table(|block| u64::from((block & 1) == 0));
let result = self.key.apply_lookup_table(first_block, &lut);
BooleanBlock::new_unchecked(result)
},
)
}
/// Returns an encryption of true if the value is odd
//
/// ct is not required to have clean carries
pub fn unchecked_is_odd<T>(&self, ct: &T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
ct.blocks().first().map_or_else(
|| {
// Interpret empty as being 0, which is not odd
self.create_trivial_boolean_block(false)
},
|first_block| {
let result = self.key.unchecked_scalar_bitand(first_block, 1);
BooleanBlock::new_unchecked(result)
},
)
}
/// Returns an encryption of true if the value is even
#[allow(unused_mut)]
pub fn smart_is_even_parallelized<T>(&self, ct: &mut T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
self.unchecked_is_even(ct)
}
/// Returns an encryption of true if the value is odd
#[allow(unused_mut)]
pub fn smart_is_odd_parallelized<T>(&self, ct: &mut T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
self.unchecked_is_odd(ct)
}
/// Returns an encryption of true if the value is even
pub fn is_even_parallelized<T>(&self, ct: &T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
// Since the check happens on the first bit of the first block
// no need to worry about carries
self.unchecked_is_even(ct)
}
/// Returns an encryption of true if the value is odd
pub fn is_odd_parallelized<T>(&self, ct: &T) -> BooleanBlock
where
T: IntegerRadixCiphertext,
{
// Since the check happens on the first bit of the first block
// no need to worry about carries
self.unchecked_is_odd(ct)
}
}