diff --git a/include/keyswitch.hpp b/include/keyswitch.hpp index 6cf2c35..6d7d239 100644 --- a/include/keyswitch.hpp +++ b/include/keyswitch.hpp @@ -385,4 +385,38 @@ void TLWE2TRLWEChengsPacking(TRLWE

&res, std::vector> &tlwe, const An for (int j = 0; j < (P::k+1) * P::n; j++) res[0][j] += evaledauto[0][j]; } } + +template +void PackLWEsLSB(TRLWE

&res, const std::vector> &tlwe, const AnnihilateKey

&ahk, const uint l, const uint offset, const uint interval) +{ + if(offset >= tlwe.size()) res = {}; + else if(l==0) InvSampleExtractIndex

(res,tlwe[offset],0); + else{ + TRLWE

tempeven; + PackLWEsLSB

(tempeven, tlwe, ahk, l-1, offset, interval*2); + TRLWE

tempodd; + PackLWEsLSB

(tempodd, tlwe, ahk, l-1, offset+interval, interval*2); + TRLWE

tempoddmul; + for(int i = 0; i < P::k+1; i++){ + PolynomialMulByXai

(tempoddmul[i], tempodd[i], P::n>>l); + for(int j = 0; j < P::n; j++){ + tempeven[i][j] /= 2; + tempoddmul[i][j] /= 2; + tempodd[i][j] = tempeven[i][j] - tempoddmul[i][j]; + // tempodd[i][j] = (tempeven[i][j] - tempoddmul[i][j])/2; + } + } + EvalAuto

(res, tempodd, (1< +void TLWE2TRLWEPacking(TRLWE

&res, std::vector> &tlwe, const AnnihilateKey

&ahk) +{ + PackLWEsLSB

(res, tlwe, ahk, P::nbit, 0, 1); +} } // namespace TFHEpp \ No newline at end of file diff --git a/test/tlwe2trlwepacking.cpp b/test/tlwe2trlwepacking.cpp new file mode 100644 index 0000000..c1c94c8 --- /dev/null +++ b/test/tlwe2trlwepacking.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include + +int main() +{ + constexpr uint32_t num_test = 1000; + constexpr uint l = 4; + constexpr uint numtlwe = 1< binary(0, 1); + + std::unique_ptr sk(new TFHEpp::SecretKey()); + + std::vector>> ca(num_test); + + std::vector> pin(num_test); + for (std::vector &i : pin){ + i.resize(numtlwe); + for (uint8_t &p : i) p = binary(engine); + } + for (int i = 0; i < num_test; i++) ca[i] = TFHEpp::bootsSymEncrypt(pin[i], *sk); + + std::vector> cres(num_test); + + std::unique_ptr> ahk(new TFHEpp::AnnihilateKey()); + TFHEpp::annihilatekeygen(*ahk, *sk); + + std::chrono::system_clock::time_point start, end; + start = std::chrono::system_clock::now(); + + for (int test = 0; test < num_test; test++) { + TFHEpp::TLWE2TRLWEPacking(cres[test], ca[test], *ahk); + } + + end = std::chrono::system_clock::now(); + + for (int i = 0; i < num_test; i++){ + std::array pres = TFHEpp::trlweSymDecrypt(cres[i], sk->key.lvl1); + for(int j = 0; j < numtlwe; j++) assert(pres[j] == (pin[i][j] > 0)); + } + + std::cout << "Passed" << std::endl; + double elapsed = std::chrono::duration_cast(end - start).count(); + std::cout << elapsed / num_test << "ms" << std::endl; +} \ No newline at end of file