diff --git a/tfhe/src/core_crypto/commons/math/decomposition/tests.rs b/tfhe/src/core_crypto/commons/math/decomposition/tests.rs index 34b6eb0b2..8612e0b8a 100644 --- a/tfhe/src/core_crypto/commons/math/decomposition/tests.rs +++ b/tfhe/src/core_crypto/commons/math/decomposition/tests.rs @@ -242,6 +242,27 @@ fn test_decomposition_edge_case_sign_handling() { } } +#[test] +fn test_decomposition_edge_case_sign_handling_u128() { + let decomposer = SignedDecomposer::new(DecompositionBaseLog(40), DecompositionLevelCount(3)); + // This value triggers a negative state at the start of the decomposition, invalid code using + // logic shift will wrongly compute an intermediate value by not keeping the sign of the + // state on the last level if base_log * (level_count + 1) > Scalar::BITS, the logic shift will + // shift in 0s instead of the 1s to keep the sign information + let val: u128 = 170141183460604905165246226680529368983; + + let rounded = decomposer.closest_representable(val); + let recomp = decomposer.recompose(decomposer.decompose(val)).unwrap(); + let decomp = decomposer.decompose(val); + assert_eq!(rounded, recomp); + + let expected = [-421613125320i128, 482008863255, -549755813888]; + + for (term, expect) in decomp.zip(expected) { + assert_eq!(term.value() as i128, expect, "Problem with term {term:?}"); + } +} + #[test] fn test_recompose_exhaustive() { let base_log = DecompositionBaseLog(10);