From e0dbb557d830a53631c408a5fcbac3fcf17111c9 Mon Sep 17 00:00:00 2001 From: Kim Laine Date: Sat, 30 May 2020 22:41:22 -0700 Subject: [PATCH] Added unit tests and changed version to 3.5.3 --- CHANGES.md | 7 +++ CMakeLists.txt | 2 +- native/tests/seal/evaluator.cpp | 79 +++++++++++++++++++++++++++------ 3 files changed, 73 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1766d63f3..aba5c1f7a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,12 @@ # List of Changes +## Version 3.5.3 + +### Bug fixes + +- Fixed a bug in `seal::util::IterTuple<...>` where a part of the `value_type` was constructed incorrectly. +- Fixed a bug in `Evaluator::mod_switch_drop_to_next` that caused non-inplace modulus switching to fail [(Issue 179)](https://github.com/microsoft/SEAL/issues/179). Thanks s0l0ist! + ## Version 3.5.2 ### Bug fixes diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ebfa4867..eeae1432e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.12) # 4. SEAL C++ tests # ################################################### -project(SEAL VERSION 3.5.2 LANGUAGES CXX C) +project(SEAL VERSION 3.5.3 LANGUAGES CXX C) # Check operating system: for Windows, use Visual Studio solution/project files. if(MSVC) diff --git a/native/tests/seal/evaluator.cpp b/native/tests/seal/evaluator.cpp index 4e1202c3e..0593dfc5b 100644 --- a/native/tests/seal/evaluator.cpp +++ b/native/tests/seal/evaluator.cpp @@ -2178,7 +2178,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted1, rlk); evaluator.rescale_to_next_inplace(encrypted1); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); decryptor.decrypt(encrypted1, plainRes); @@ -2246,7 +2246,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted1, rlk); evaluator.rescale_to_next_inplace(encrypted1); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); decryptor.decrypt(encrypted1, plainRes); @@ -2318,7 +2318,7 @@ namespace sealtest auto target_parms = context->first_context_data()->next_context_data()->next_context_data()->parms_id(); evaluator.rescale_to_inplace(encrypted1, target_parms); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted1.parms_id() == target_parms); decryptor.decrypt(encrypted1, plainRes); @@ -2367,7 +2367,7 @@ namespace sealtest // Relinearize now evaluator.relinearize_inplace(encrypted1, rlk); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted1.parms_id() == target_parms); decryptor.decrypt(encrypted1, plainRes); @@ -2431,7 +2431,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted, rlk); evaluator.rescale_to_next_inplace(encrypted); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted.parms_id() == next_parms_id); decryptor.decrypt(encrypted, plainRes); @@ -2490,7 +2490,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted, rlk); evaluator.rescale_to_next_inplace(encrypted); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted.parms_id() == next_parms_id); decryptor.decrypt(encrypted, plainRes); @@ -2508,7 +2508,7 @@ namespace sealtest { EncryptionParameters parms(scheme_type::CKKS); { - // modulo switching without rescaling for random vectors + // modulus switching without rescaling for random vectors size_t slot_size = 64; parms.set_poly_modulus_degree(slot_size * 2); parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60, 60, 60 })); @@ -2547,9 +2547,26 @@ namespace sealtest // check correctness of encryption ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + // Not inplace + Ciphertext destination; + evaluator.mod_switch_to_next(encrypted, destination); + + // check correctness of modulus switching + ASSERT_TRUE(destination.parms_id() == next_parms_id); + + decryptor.decrypt(destination, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + + // Inplace evaluator.mod_switch_to_next_inplace(encrypted); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted.parms_id() == next_parms_id); decryptor.decrypt(encrypted, plainRes); @@ -2563,7 +2580,7 @@ namespace sealtest } } { - // modulo switching without rescaling for random vectors + // modulus switching without rescaling for random vectors size_t slot_size = 32; parms.set_poly_modulus_degree(slot_size * 2); parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 40, 40, 40, 40, 40 })); @@ -2602,9 +2619,26 @@ namespace sealtest // check correctness of encryption ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + // Not inplace + Ciphertext destination; + evaluator.mod_switch_to_next(encrypted, destination); + + // check correctness of modulus switching + ASSERT_TRUE(destination.parms_id() == next_parms_id); + + decryptor.decrypt(destination, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + + // Inplace evaluator.mod_switch_to_next_inplace(encrypted); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted.parms_id() == next_parms_id); decryptor.decrypt(encrypted, plainRes); @@ -2618,7 +2652,7 @@ namespace sealtest } } { - // modulo switching without rescaling for random vectors + // modulus switching without rescaling for random vectors size_t slot_size = 32; parms.set_poly_modulus_degree(128); parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40, 40, 40 })); @@ -2657,9 +2691,26 @@ namespace sealtest // check correctness of encryption ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + // Not inplace + Ciphertext destination; + evaluator.mod_switch_to_next(encrypted, destination); + + // check correctness of modulus switching + ASSERT_TRUE(destination.parms_id() == next_parms_id); + + decryptor.decrypt(destination, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + + // Inplace evaluator.mod_switch_to_next_inplace(encrypted); - // check correctness of modulo switching + // check correctness of modulus switching ASSERT_TRUE(encrypted.parms_id() == next_parms_id); decryptor.decrypt(encrypted, plainRes); @@ -2738,7 +2789,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted1, rlk); evaluator.rescale_to_next_inplace(encrypted1); - // check correctness of modulo switching with rescaling + // check correctness of modulus switching with rescaling ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); // move enc3 to the level of enc1 * enc2 @@ -2821,7 +2872,7 @@ namespace sealtest evaluator.relinearize_inplace(encrypted1, rlk); evaluator.rescale_to_next_inplace(encrypted1); - // check correctness of modulo switching with rescaling + // check correctness of modulus switching with rescaling ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); // move enc3 to the level of enc1 * enc2