#[cfg(feature = "gpu")]
use crate::core_crypto::commons::numeric::CastFrom;
use crate::high_level_api::errors::UnwrapResultExt;
use crate::high_level_api::global_state;
use crate::high_level_api::integers::signed::inner::SignedRadixCiphertext;
use crate::high_level_api::integers::FheIntId;
use crate::high_level_api::keys::InternalServerKey;
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
#[cfg(feature = "gpu")]
use crate::high_level_api::traits::{
AddSizeOnGpu, BitAndSizeOnGpu, BitOrSizeOnGpu, BitXorSizeOnGpu, DivRemSizeOnGpu, DivSizeOnGpu,
FheEqSizeOnGpu, FheMaxSizeOnGpu, FheMinSizeOnGpu, FheOrdSizeOnGpu, MulSizeOnGpu, RemSizeOnGpu,
RotateLeftSizeOnGpu, RotateRightSizeOnGpu, ShlSizeOnGpu, ShrSizeOnGpu, SubSizeOnGpu,
};
use crate::high_level_api::traits::{
DivRem, FheEq, FheMax, FheMin, FheOrd, RotateLeft, RotateLeftAssign, RotateRight,
RotateRightAssign,
};
use crate::integer::bigint::{I1024, I2048, U1024, U2048};
use crate::integer::block_decomposition::DecomposableInto;
use crate::integer::{I256, I512, U256, U512};
use crate::{FheBool, FheInt};
use std::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
};
impl<Id, Clear> FheMax<Clear> for FheInt<Id>
where
Clear: DecomposableInto<u64>,
Id: FheIntId,
{
type Output = Self;
fn max(&self, rhs: Clear) -> Self::Output {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_max_parallelized(&*self.ciphertext.on_cpu(), rhs);
Self::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_max(&*self.ciphertext.on_gpu(streams), rhs, streams);
Self::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
}
impl<Id, Clear> FheMin<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
type Output = Self;
fn min(&self, rhs: Clear) -> Self::Output {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_min_parallelized(&*self.ciphertext.on_cpu(), rhs);
Self::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_min(&*self.ciphertext.on_gpu(streams), rhs, streams);
Self::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
}
impl<Id, Clear> FheEq<Clear> for FheInt<Id>
where
Clear: DecomposableInto<u64>,
Id: FheIntId,
{
fn eq(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_eq_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_eq(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
fn ne(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_ne_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_ne(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
}
impl<Id, Clear> FheOrd<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
fn lt(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_lt_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_lt(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
fn le(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_le_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_le(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
fn gt(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_gt_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_gt(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
fn ge(&self, rhs: Clear) -> FheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_ge_parallelized(&*self.ciphertext.on_cpu(), rhs);
FheBool::new(
inner_result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let inner_result =
cuda_key
.key
.key
.scalar_ge(&*self.ciphertext.on_gpu(streams), rhs, streams);
FheBool::new(
inner_result,
cuda_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
}
#[cfg(feature = "gpu")]
impl<Id, Clear> FheOrdSizeOnGpu<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
fn get_gt_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_gt_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
fn get_ge_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_ge_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
fn get_lt_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_lt_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
fn get_le_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_le_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
}
#[cfg(feature = "gpu")]
impl<Id, Clear> FheEqSizeOnGpu<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
fn get_eq_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_eq_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
fn get_ne_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_ne_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
}
#[cfg(feature = "gpu")]
impl<Id, Clear> FheMinSizeOnGpu<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
fn get_min_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_min_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
}
#[cfg(feature = "gpu")]
impl<Id, Clear> FheMaxSizeOnGpu<Clear> for FheInt<Id>
where
Id: FheIntId,
Clear: DecomposableInto<u64>,
{
fn get_max_size_on_gpu(&self, _rhs: Clear) -> u64 {
global_state::with_internal_keys(|key| {
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key
.key
.key
.get_scalar_max_size_on_gpu(&*self.ciphertext.on_gpu(streams), streams)
} else {
0
}
})
}
}
macro_rules! generic_integer_impl_scalar_div_rem {
(
// A 'list' of tuple, where the first element is the concrete Fhe type
// e.g (FheInt8 and the rest is scalar types (i8, i16, etc)
fhe_and_scalar_type: $(
($concrete_type:ty, $($scalar_type:ty),*)
),*
$(,)?
) => {
$( // First repeating pattern
$( // Second repeating pattern
impl DivRem<$scalar_type> for $concrete_type
{
type Output = ($concrete_type, $concrete_type);
fn div_rem(self, rhs: $scalar_type) -> Self::Output {
<&Self as DivRem<$scalar_type>>::div_rem(&self, rhs)
}
}
impl DivRem<$scalar_type> for &$concrete_type
{
type Output = ($concrete_type, $concrete_type);
fn div_rem(self, rhs: $scalar_type) -> Self::Output {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let (q, r) = cpu_key
.pbs_key()
.signed_scalar_div_rem_parallelized(&*self.ciphertext.on_cpu(), rhs);
(
<$concrete_type>::new(q, cpu_key.tag.clone(), ReRandomizationMetadata::default()),
<$concrete_type>::new(r, cpu_key.tag.clone(), ReRandomizationMetadata::default()),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let (inner_q, inner_r) = {let streams = &cuda_key.streams;
cuda_key.key.key.signed_scalar_div_rem(
&*self.ciphertext.on_gpu(streams), rhs, streams
)
};
let (q, r) = (
SignedRadixCiphertext::Cuda(inner_q),
SignedRadixCiphertext::Cuda(inner_r),
);
(
<$concrete_type>::new(q, cuda_key.tag.clone(), ReRandomizationMetadata::default()),
<$concrete_type>::new(r, cuda_key.tag.clone(), ReRandomizationMetadata::default()),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
}
)* )* };
}
#[cfg(feature = "gpu")]
use crate::high_level_api::integers::unsigned::scalar_ops::{
generic_integer_impl_get_scalar_left_operation_size_on_gpu,
generic_integer_impl_get_scalar_operation_size_on_gpu,
};
use crate::high_level_api::integers::unsigned::scalar_ops::{
generic_integer_impl_scalar_left_operation, generic_integer_impl_scalar_operation,
generic_integer_impl_scalar_operation_assign,
};
macro_rules! define_scalar_rotate_shifts {
(
$(
($concrete_type:ty, $($scalar_type:ty),* $(,)?)
),*
$(,)?
) => {
generic_integer_impl_scalar_operation!(
rust_trait: Shl(shl),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_left_shift_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_left_shift(
&*lhs.ciphertext.on_gpu(streams), u64::cast_from(rhs), streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: ShlSizeOnGpu(get_left_shift_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_left_shift_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Shr(shr),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_right_shift_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_right_shift(
&*lhs.ciphertext.on_gpu(streams), u64::cast_from(rhs), streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: ShrSizeOnGpu(get_right_shift_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_right_shift_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: RotateLeft(rotate_left),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_rotate_left_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_rotate_left(
&*lhs.ciphertext.on_gpu(streams), u64::cast_from(rhs), streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: RotateLeftSizeOnGpu(get_rotate_left_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_rotate_left_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: RotateRight(rotate_right),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_rotate_right_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_rotate_right(
&*lhs.ciphertext.on_gpu(streams), u64::cast_from(rhs), streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: RotateRightSizeOnGpu(get_rotate_right_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_rotate_right_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: ShlAssign(shl_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_left_shift_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) =>
{let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_left_shift_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: ShrAssign(shr_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_right_shift_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_right_shift_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: RotateLeftAssign(rotate_left_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_rotate_left_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) =>
{let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_rotate_left_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: RotateRightAssign(rotate_right_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_rotate_right_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
{let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_rotate_right_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type,)*),
)*
);
};
}
define_scalar_rotate_shifts!(
(super::FheInt2, u8, u16, u32, u64, u128),
(super::FheInt4, u8, u16, u32, u64, u128),
(super::FheInt6, u8, u16, u32, u64, u128),
(super::FheInt8, u8, u16, u32, u64, u128),
(super::FheInt10, u8, u16, u32, u64, u128),
(super::FheInt12, u8, u16, u32, u64, u128),
(super::FheInt14, u8, u16, u32, u64, u128),
(super::FheInt16, u8, u16, u32, u64, u128),
(super::FheInt32, u8, u16, u32, u64, u128),
(super::FheInt64, u8, u16, u32, u64, u128),
(super::FheInt128, u8, u16, u32, u64, u128),
(super::FheInt160, u8, u16, u32, u64, u128, U256),
(super::FheInt256, u8, u16, u32, u64, u128, U256),
(super::FheInt512, u8, u16, u32, u64, u128, U256, U512),
(
super::FheInt1024,
u8,
u16,
u32,
u64,
u128,
U256,
U512,
U1024
),
(
super::FheInt2048,
u8,
u16,
u32,
u64,
u128,
U256,
U512,
U1024,
U2048
),
);
#[cfg(feature = "extended-types")]
define_scalar_rotate_shifts!(
(super::FheInt24, u8, u16, u32, u64, u128),
(super::FheInt40, u8, u16, u32, u64, u128),
(super::FheInt48, u8, u16, u32, u64, u128),
(super::FheInt56, u8, u16, u32, u64, u128),
(super::FheInt72, u8, u16, u32, u64, u128),
(super::FheInt80, u8, u16, u32, u64, u128),
(super::FheInt88, u8, u16, u32, u64, u128),
(super::FheInt96, u8, u16, u32, u64, u128),
(super::FheInt104, u8, u16, u32, u64, u128),
(super::FheInt112, u8, u16, u32, u64, u128),
(super::FheInt120, u8, u16, u32, u64, u128),
(super::FheInt136, u8, u16, u32, u64, u128, U256),
(super::FheInt144, u8, u16, u32, u64, u128, U256),
(super::FheInt152, u8, u16, u32, u64, u128, U256),
(super::FheInt168, u8, u16, u32, u64, u128, U256),
(super::FheInt176, u8, u16, u32, u64, u128, U256),
(super::FheInt184, u8, u16, u32, u64, u128, U256),
(super::FheInt192, u8, u16, u32, u64, u128, U256),
(super::FheInt200, u8, u16, u32, u64, u128, U256),
(super::FheInt208, u8, u16, u32, u64, u128, U256),
(super::FheInt216, u8, u16, u32, u64, u128, U256),
(super::FheInt224, u8, u16, u32, u64, u128, U256),
(super::FheInt232, u8, u16, u32, u64, u128, U256),
(super::FheInt240, u8, u16, u32, u64, u128, U256),
(super::FheInt248, u8, u16, u32, u64, u128, U256),
);
macro_rules! define_scalar_ops {
(
$(
($concrete_type:ty, $($(#[$doc:meta])* $scalar_type:ty),*)
),*
$(,)?
) => {
generic_integer_impl_scalar_div_rem!(
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Add(add),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_add_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_add(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: AddSizeOnGpu(get_add_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_add_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Sub(sub),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_sub_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_sub(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: SubSizeOnGpu(get_sub_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_sub_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Mul(mul),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_mul_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_mul(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: MulSizeOnGpu(get_mul_size_on_gpu),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_mul_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
rhs,
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: BitAnd(bitand),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_bitand_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_bitand(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: BitAndSizeOnGpu(get_bitand_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitand_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: BitOr(bitor),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_bitor_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_bitor(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: BitOrSizeOnGpu(get_bitor_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitor_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: BitXor(bitxor),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.scalar_bitxor_parallelized(&*lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.scalar_bitxor(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: BitXorSizeOnGpu(get_bitxor_size_on_gpu),
implem: {
|lhs: &FheInt<_>, _rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitxor_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Div(div),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.signed_scalar_div_parallelized(&lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.signed_scalar_div(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: DivRemSizeOnGpu(get_div_rem_size_on_gpu),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_signed_scalar_div_rem_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
rhs,
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: DivSizeOnGpu(get_div_size_on_gpu),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_signed_scalar_div_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
rhs,
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation!(
rust_trait: Rem(rem),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let inner_result = cpu_key
.pbs_key()
.signed_scalar_rem_parallelized(&lhs.ciphertext.on_cpu(), rhs);
SignedRadixCiphertext::Cpu(inner_result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let inner_result = {let streams = &cuda_key.streams;
cuda_key.key.key.signed_scalar_rem(
&*lhs.ciphertext.on_gpu(streams), rhs, streams
)
};
SignedRadixCiphertext::Cuda(inner_result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature = "gpu")]
generic_integer_impl_get_scalar_operation_size_on_gpu!(
rust_trait: RemSizeOnGpu(get_rem_size_on_gpu),
implem: {
|lhs: &FheInt<_>, rhs| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_signed_scalar_rem_size_on_gpu(
&*lhs.ciphertext.on_gpu(streams),
rhs,
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: Add(add),
implem: {
|lhs, rhs: &FheInt<_>| {
let result: FheInt<_> = rhs + lhs;
result.ciphertext
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature="gpu")]
generic_integer_impl_get_scalar_left_operation_size_on_gpu!(
rust_trait: AddSizeOnGpu(get_add_size_on_gpu),
implem: {
|_lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_add_size_on_gpu(
&*rhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: Sub(sub),
implem: {
|lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
let result = cpu_key.pbs_key().left_scalar_sub_parallelized(lhs, &*rhs.ciphertext.on_cpu());
SignedRadixCiphertext::Cpu(result)
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
use crate::integer::gpu::ciphertext::CudaSignedRadixCiphertext;
let streams = &cuda_key.streams;
let mut result: CudaSignedRadixCiphertext = cuda_key.pbs_key().create_trivial_radix(
lhs, rhs.ciphertext.on_gpu(streams).ciphertext.info.blocks.len(), streams);
cuda_key.pbs_key().sub_assign(&mut result, &*rhs.ciphertext.on_gpu(streams), streams);
SignedRadixCiphertext::Cuda(result)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature="gpu")]
generic_integer_impl_get_scalar_left_operation_size_on_gpu!(
rust_trait: SubSizeOnGpu(get_sub_size_on_gpu),
implem: {
|_lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_sub_size_on_gpu(
&*rhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: Mul(mul),
implem: {
|lhs, rhs: &FheInt<_>| {
let result: FheInt<_> = rhs * lhs;
result.ciphertext
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: BitAnd(bitand),
implem: {
|lhs, rhs: &FheInt<_>| {
let result: FheInt<_> = rhs & lhs;
result.ciphertext
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature="gpu")]
generic_integer_impl_get_scalar_left_operation_size_on_gpu!(
rust_trait: BitAndSizeOnGpu(get_bitand_size_on_gpu),
implem: {
|_lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitand_size_on_gpu(
&*rhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: BitOr(bitor),
implem: {
|lhs, rhs: &FheInt<_>| {
let result: FheInt<_> = rhs | lhs;
result.ciphertext
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature="gpu")]
generic_integer_impl_get_scalar_left_operation_size_on_gpu!(
rust_trait: BitOrSizeOnGpu(get_bitor_size_on_gpu),
implem: {
|_lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitor_size_on_gpu(
&*rhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_left_operation!(
rust_trait: BitXor(bitxor),
implem: {
|lhs, rhs: &FheInt<_>| {
let result: FheInt<_> = rhs ^ lhs;
result.ciphertext
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
#[cfg(feature="gpu")]
generic_integer_impl_get_scalar_left_operation_size_on_gpu!(
rust_trait: BitXorSizeOnGpu(get_bitxor_size_on_gpu),
implem: {
|_lhs, rhs: &FheInt<_>| {
global_state::with_internal_keys(|key|
if let InternalServerKey::Cuda(cuda_key) = key {
let streams = &cuda_key.streams;
cuda_key.key.key.get_scalar_bitxor_size_on_gpu(
&*rhs.ciphertext.on_gpu(streams),
streams,
)
} else {
0
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: AddAssign(add_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_add_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_add_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type,
$(
#[doc = "Performs an addition assignment operation of a clear to a [FheInt]."]
$scalar_type
)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: SubAssign(sub_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_sub_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_sub_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: MulAssign(mul_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_mul_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_mul_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: BitAndAssign(bitand_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_bitand_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_bitand_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: BitOrAssign(bitor_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_bitor_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_bitor_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: BitXorAssign(bitxor_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.scalar_bitxor_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
cuda_key.key.key
.scalar_bitxor_assign(lhs.ciphertext.as_gpu_mut(streams), rhs, streams);
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: DivAssign(div_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.signed_scalar_div_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {
let streams = &cuda_key.streams;
let cuda_lhs = lhs.ciphertext.as_gpu_mut(streams);
let cuda_result = cuda_key.pbs_key().signed_scalar_div(&cuda_lhs, rhs, streams);
*cuda_lhs = cuda_result;
},
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
generic_integer_impl_scalar_operation_assign!(
rust_trait: RemAssign(rem_assign),
implem: {
|lhs: &mut FheInt<_>, rhs| {
global_state::with_internal_keys(|key| match key {
InternalServerKey::Cpu(cpu_key) => {
cpu_key
.pbs_key()
.signed_scalar_rem_assign_parallelized(lhs.ciphertext.as_cpu_mut(), rhs);
},
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(cuda_key) => {let streams = &cuda_key.streams;
let cuda_lhs = lhs.ciphertext.as_gpu_mut(streams);
let cuda_result = cuda_key.pbs_key().signed_scalar_rem(&cuda_lhs, rhs, streams);
*cuda_lhs = cuda_result;
},
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_device) => {
panic!("Hpu does not support this operation yet.")
}
})
}
},
fhe_and_scalar_type:
$(
($concrete_type, $($scalar_type)*),
)*
);
};
}
define_scalar_ops!(
(super::FheInt2, i8),
(super::FheInt4, i8),
(super::FheInt6, i8),
(super::FheInt8, i8),
(super::FheInt10, i16),
(super::FheInt12, i16),
(super::FheInt14, i16),
(super::FheInt16, i16),
(super::FheInt32, i32),
(super::FheInt64, i64),
(super::FheInt128, i128),
(super::FheInt160, I256),
(super::FheInt256, I256),
(super::FheInt512, I512),
(super::FheInt1024, I1024),
(super::FheInt2048, I2048),
);
#[cfg(feature = "extended-types")]
define_scalar_ops!(
(super::FheInt24, i32),
(super::FheInt40, i64),
(super::FheInt48, i64),
(super::FheInt56, i64),
(super::FheInt72, i128),
(super::FheInt80, i128),
(super::FheInt88, i128),
(super::FheInt96, i128),
(super::FheInt104, i128),
(super::FheInt112, i128),
(super::FheInt120, i128),
(super::FheInt136, I256),
(super::FheInt144, I256),
(super::FheInt152, I256),
(super::FheInt168, I256),
(super::FheInt176, I256),
(super::FheInt184, I256),
(super::FheInt192, I256),
(super::FheInt200, I256),
(super::FheInt208, I256),
(super::FheInt216, I256),
(super::FheInt224, I256),
(super::FheInt232, I256),
(super::FheInt240, I256),
(super::FheInt248, I256),
);