diff --git a/scripts/integer-tests.sh b/scripts/integer-tests.sh index 216d94310..9e527f992 100755 --- a/scripts/integer-tests.sh +++ b/scripts/integer-tests.sh @@ -28,14 +28,12 @@ if [[ "${BIG_TESTS_INSTANCE}" != TRUE ]]; then # block pbs are too slow for high params # mul_crt_4_4 is extremely flaky (~80% failure) # test_wopbs_bivariate_crt_wopbs_param_message generate tables that are too big at the moment - # same for test_wopbs_bivariate_radix_wopbs_param_message_4_carry_4 # test_integer_smart_mul_param_message_4_carry_4 is too slow filter_expression=''\ 'test(/^integer::.*$/)'\ 'and not test(/.*_block_pbs(_base)?_param_message_[34]_carry_[34]$/)'\ 'and not test(~mul_crt_param_message_4_carry_4)'\ 'and not test(/.*test_wopbs_bivariate_crt_wopbs_param_message_[34]_carry_[34]$/)'\ -'and not test(/.*test_wopbs_bivariate_radix_wopbs_param_message_4_carry_4$/)'\ 'and not test(/.*test_integer_smart_mul_param_message_4_carry_4$/)' cargo ${1:+"${1}"} nextest run \ @@ -57,14 +55,12 @@ else # block pbs are too slow for high params # mul_crt_4_4 is extremely flaky (~80% failure) # test_wopbs_bivariate_crt_wopbs_param_message generate tables that are too big at the moment - # same for test_wopbs_bivariate_radix_wopbs_param_message_4_carry_4 # test_integer_smart_mul_param_message_4_carry_4 is too slow filter_expression=''\ 'test(/^integer::.*$/)'\ 'and not test(/.*_block_pbs(_base)?_param_message_[34]_carry_[34]$/)'\ 'and not test(~mul_crt_param_message_4_carry_4)'\ 'and not test(/.*test_wopbs_bivariate_crt_wopbs_param_message_[34]_carry_[34]$/)'\ -'and not test(/.*test_wopbs_bivariate_radix_wopbs_param_message_4_carry_4$/)'\ 'and not test(/.*test_integer_smart_mul_param_message_4_carry_4$/)' cargo ${1:+"${1}"} nextest run \ diff --git a/tfhe/src/high_level_api/integers/server_key.rs b/tfhe/src/high_level_api/integers/server_key.rs index a6246843c..a5d281f3e 100644 --- a/tfhe/src/high_level_api/integers/server_key.rs +++ b/tfhe/src/high_level_api/integers/server_key.rs @@ -120,10 +120,30 @@ impl ) -> crate::high_level_api::integers::server_key::RadixCiphertextDyn { match ct { RadixCiphertextDyn::Big(ct) => { + let mut tmp_ct: crate::integer::ciphertext::RadixCiphertextBig; + + let ct = if ct.block_carries_are_empty() { + ct + } else { + tmp_ct = ct.clone(); + sks.full_propagate_parallelized(&mut tmp_ct); + &tmp_ct + }; + let res = wopbs_radix(self, sks, ct, f); RadixCiphertextDyn::Big(res) } RadixCiphertextDyn::Small(ct) => { + let mut tmp_ct: crate::integer::ciphertext::RadixCiphertextSmall; + + let ct = if ct.block_carries_are_empty() { + ct + } else { + tmp_ct = ct.clone(); + sks.full_propagate_parallelized(&mut tmp_ct); + &tmp_ct + }; + let res = wopbs_radix(self, sks, ct, f); RadixCiphertextDyn::Small(res) } @@ -139,10 +159,66 @@ impl ) -> crate::high_level_api::integers::server_key::RadixCiphertextDyn { match (lhs, rhs) { (RadixCiphertextDyn::Big(lhs), RadixCiphertextDyn::Big(rhs)) => { + let mut tmp_lhs: crate::integer::ciphertext::RadixCiphertextBig; + let mut tmp_rhs: crate::integer::ciphertext::RadixCiphertextBig; + + // Clean carries to have a small wopbs to compute + let (lhs, rhs) = + match (lhs.block_carries_are_empty(), rhs.block_carries_are_empty()) { + (true, true) => (lhs, rhs), + (true, false) => { + tmp_rhs = rhs.clone(); + sks.full_propagate_parallelized(&mut tmp_rhs); + (lhs, &tmp_rhs) + } + (false, true) => { + tmp_lhs = lhs.clone(); + sks.full_propagate_parallelized(&mut tmp_lhs); + (&tmp_lhs, rhs) + } + (false, false) => { + tmp_lhs = lhs.clone(); + tmp_rhs = rhs.clone(); + rayon::join( + || sks.full_propagate_parallelized(&mut tmp_lhs), + || sks.full_propagate_parallelized(&mut tmp_rhs), + ); + (&tmp_lhs, &tmp_rhs) + } + }; + let res = bivariate_wopbs_radix(self, sks, lhs, rhs, f); RadixCiphertextDyn::Big(res) } (RadixCiphertextDyn::Small(lhs), RadixCiphertextDyn::Small(rhs)) => { + let mut tmp_lhs: crate::integer::ciphertext::RadixCiphertextSmall; + let mut tmp_rhs: crate::integer::ciphertext::RadixCiphertextSmall; + + // Clean carries to have a small wopbs to compute + let (lhs, rhs) = + match (lhs.block_carries_are_empty(), rhs.block_carries_are_empty()) { + (true, true) => (lhs, rhs), + (true, false) => { + tmp_rhs = rhs.clone(); + sks.full_propagate_parallelized(&mut tmp_rhs); + (lhs, &tmp_rhs) + } + (false, true) => { + tmp_lhs = lhs.clone(); + sks.full_propagate_parallelized(&mut tmp_lhs); + (&tmp_lhs, rhs) + } + (false, false) => { + tmp_lhs = lhs.clone(); + tmp_rhs = rhs.clone(); + rayon::join( + || sks.full_propagate_parallelized(&mut tmp_lhs), + || sks.full_propagate_parallelized(&mut tmp_rhs), + ); + (&tmp_lhs, &tmp_rhs) + } + }; + let res = bivariate_wopbs_radix(self, sks, lhs, rhs, f); RadixCiphertextDyn::Small(res) } diff --git a/tfhe/src/shortint/engine/wopbs/mod.rs b/tfhe/src/shortint/engine/wopbs/mod.rs index 0ebd9fb00..fb476c94a 100644 --- a/tfhe/src/shortint/engine/wopbs/mod.rs +++ b/tfhe/src/shortint/engine/wopbs/mod.rs @@ -396,9 +396,11 @@ impl ShortintEngine { &mut buffer_lwe_after_ks, ); + // The identity lut wrongly sets the max degree in the ciphertext, when in reality the + // degree of the ciphertext has no changed, we manage this case manually here Ok(CiphertextBase { ct: buffer_lwe_after_ks, - degree: ct_clean.degree, + degree: ct_in.degree, message_modulus: ct_clean.message_modulus, carry_modulus: ct_clean.carry_modulus, _order_marker: Default::default(),