-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(integer): add is_even/is_odd functions
These ones are pretty simple and so are also directly done for GPU
- Loading branch information
Showing
9 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
use crate::core_crypto::gpu::CudaStreams; | ||
use crate::integer::gpu::ciphertext::boolean_value::CudaBooleanBlock; | ||
use crate::integer::gpu::ciphertext::CudaIntegerRadixCiphertext; | ||
use crate::integer::gpu::server_key::radix::{ | ||
CudaBlockInfo, CudaLweCiphertextList, CudaRadixCiphertext, CudaRadixCiphertextInfo, | ||
LweCiphertextCount, | ||
}; | ||
use crate::integer::gpu::server_key::CudaServerKey; | ||
use crate::shortint::parameters::{Degree, NoiseLevel}; | ||
|
||
impl CudaServerKey { | ||
/// # Safety | ||
/// | ||
/// - `stream` __must__ be synchronized to guarantee computation has finished, and inputs must | ||
/// not be dropped until stream is synchronised | ||
pub unsafe fn unchecked_is_even_async<T>( | ||
&self, | ||
ct: &T, | ||
streams: &CudaStreams, | ||
) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let radix = ct.as_ref(); | ||
let lut = self.generate_lookup_table(|block| u64::from((block & 1) == 0)); | ||
let mut single_block = CudaRadixCiphertext { | ||
d_blocks: CudaLweCiphertextList::new( | ||
radix.d_blocks.0.lwe_dimension, | ||
LweCiphertextCount(1), | ||
radix.d_blocks.0.ciphertext_modulus, | ||
streams, | ||
), | ||
info: CudaRadixCiphertextInfo { | ||
blocks: vec![CudaBlockInfo { | ||
degree: Degree::new(1), | ||
message_modulus: self.message_modulus, | ||
carry_modulus: self.carry_modulus, | ||
pbs_order: self.pbs_order, | ||
noise_level: NoiseLevel::NOMINAL, | ||
}], | ||
}, | ||
}; | ||
self.apply_lookup_table_async(&mut single_block, radix, &lut, 0..1, streams); | ||
CudaBooleanBlock::from_cuda_radix_ciphertext(single_block) | ||
} | ||
|
||
pub fn unchecked_is_even<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let result = unsafe { self.unchecked_is_even_async(ct, streams) }; | ||
streams.synchronize(); | ||
result | ||
} | ||
|
||
/// # Safety | ||
/// | ||
/// - `stream` __must__ be synchronized to guarantee computation has finished, and inputs must | ||
/// not be dropped until stream is synchronised | ||
pub unsafe fn is_even_async<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
// Since the check is done on the first bit of the first block | ||
// no need to worry about carries | ||
self.unchecked_is_even_async(ct, streams) | ||
} | ||
|
||
pub fn is_even<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let result = unsafe { self.is_even_async(ct, streams) }; | ||
streams.synchronize(); | ||
result | ||
} | ||
|
||
/// # Safety | ||
/// | ||
/// - `stream` __must__ be synchronized to guarantee computation has finished, and inputs must | ||
/// not be dropped until stream is synchronised | ||
pub unsafe fn unchecked_is_odd_async<T>( | ||
&self, | ||
ct: &T, | ||
streams: &CudaStreams, | ||
) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let radix = ct.as_ref(); | ||
let lut = self.generate_lookup_table(|block| block & 1); | ||
let mut single_block = CudaRadixCiphertext { | ||
d_blocks: CudaLweCiphertextList::new( | ||
radix.d_blocks.0.lwe_dimension, | ||
LweCiphertextCount(1), | ||
radix.d_blocks.0.ciphertext_modulus, | ||
streams, | ||
), | ||
info: CudaRadixCiphertextInfo { | ||
blocks: vec![CudaBlockInfo { | ||
degree: Degree::new(1), | ||
message_modulus: self.message_modulus, | ||
carry_modulus: self.carry_modulus, | ||
pbs_order: self.pbs_order, | ||
noise_level: NoiseLevel::NOMINAL, | ||
}], | ||
}, | ||
}; | ||
self.apply_lookup_table_async(&mut single_block, radix, &lut, 0..1, streams); | ||
CudaBooleanBlock::from_cuda_radix_ciphertext(single_block) | ||
} | ||
|
||
pub fn unchecked_is_odd<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let result = unsafe { self.unchecked_is_odd_async(ct, streams) }; | ||
streams.synchronize(); | ||
result | ||
} | ||
|
||
/// # Safety | ||
/// | ||
/// - `stream` __must__ be synchronized to guarantee computation has finished, and inputs must | ||
/// not be dropped until stream is synchronised | ||
pub unsafe fn is_odd_async<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
// Since the check is done on the first bit of the first block | ||
// no need to worry about carries | ||
self.unchecked_is_odd_async(ct, streams) | ||
} | ||
|
||
pub fn is_odd<T>(&self, ct: &T, streams: &CudaStreams) -> CudaBooleanBlock | ||
where | ||
T: CudaIntegerRadixCiphertext, | ||
{ | ||
let result = unsafe { self.is_odd_async(ct, streams) }; | ||
streams.synchronize(); | ||
result | ||
} | ||
} |
Oops, something went wrong.