Hello, my code is as follows. I want to perform a multiplication operation after applying the sign function. In the last iteration, I use EvalFBTNoDecoding to obtain ctxtAfterFBT, and then apply EvalHomDecoding. The decrypted result is correctly [0 1 0 1 0 0 0 1]. However, after encrypting [2 2 2 2 2 2 2 2], the multiplication result is different each time. Is the plaintext modulus set incorrectly, or is the final EvalHomDecoding setting wrong? Ultimately, I want their ciphertext modulus to be the original Q, and the plaintext modulus to be the original Pinput.
while (go) {
auto encryptedDigit = ctxtBFV;
encryptedDigit[0].SwitchModulus(Bigq, 1, 0, 0);
encryptedDigit[1].SwitchModulus(Bigq, 1, 0, 0);
auto ctxt = SchemeletRLWEMP::ConvertRLWEToCKKS(*cc, encryptedDigit, keyPair.publicKey, Bigq, numSlotsCKKS,depth - (levelsAvailableBeforeBootstrap > 0));
Ciphertext<DCRTPoly> ctxtAfterFBT;
//Ciphertext<DCRTPoly> ctxtAfterFBT1;
bool isLastIteration = step || (checkeq2 && (QBFVBits - pDigitBits <= dcrtBits));
if (isLastIteration) {
if (binaryLUT)
ctxtAfterFBT = cc->EvalFBTNoDecoding(ctxt, coeffint, pDigitBits, ep->GetModulus(), order);
else
ctxtAfterFBT = cc->EvalFBTNoDecoding(ctxt, coeffcomp, pDigitBits, ep->GetModulus(), order);
//ctxtAfterFBT1 = cc->EvalMult(ctxtAfterFBT, scaleTHI * (1 << postScalingBits));
auto ctxtAfterFBT3 = cc->EvalHomDecoding(ctxtAfterFBT, scaleTHI, 0);
auto ctxtResult = SchemeletRLWEMP::ConvertCKKSToRLWE(ctxtAfterFBT3, Qorig);
auto computed11 =
SchemeletRLWEMP::DecryptCoeff(ctxtResult, Qorig, pOrig, keyPair.secretKey, ep, numSlotsCKKS, numSlots);
std::cerr << "First 8 elements of the obtained digit in last iteration: [";
std::copy_n(computed11.begin(), 8, std::ostream_iterator<int64_t>(std::cerr, " "));
std::cerr << "]" << std::endl;
ctxtAfterFBT1 = ctxtAfterFBT;
std::cout << "ctxtAfterFBT->GetLevel:" <<ctxtAfterFBT->GetLevel() << std::endl;
std::cout << "ep->GetModulus():" <<ep->GetModulus() << std::endl;
} else {
if (binaryLUT)
ctxtAfterFBT = cc->EvalFBT(ctxt, coeffint, pDigitBits, ep->GetModulus(), scaleTHI * (1 << postScalingBits),
levelsToDrop, order);
else
ctxtAfterFBT = cc->EvalFBT(ctxt, coeffcomp, pDigitBits, ep->GetModulus(), scaleTHI * (1 << postScalingBits),
levelsToDrop, order);
}
auto polys = SchemeletRLWEMP::ConvertCKKSToRLWE(ctxtAfterFBT, Q);
if (!step) {
ctxtBFV[0] = ctxtBFV[0] - polys[0];
ctxtBFV[1] = ctxtBFV[1] - polys[1];
QNew = Q >> pDigitBits;
ctxtBFV[0] = ctxtBFV[0].MultiplyAndRound(QNew, Q);
ctxtBFV[0].SwitchModulus(QNew, 1, 0, 0);
ctxtBFV[1] = ctxtBFV[1].MultiplyAndRound(QNew, Q);
ctxtBFV[1].SwitchModulus(QNew, 1, 0, 0);
Q >>= pDigitBits;
PInput >>= pDigitBits;
QBFVBits -= pDigitBits;
postScalingBits += pDigitBits;
}
//else {
//ctxtBFV[0] = std::move(polys[0]);
//ctxtBFV[1] = std::move(polys[1]);
//}
go = QBFVBits > dcrtBits;
if (step || (checkeq2 && !go)) {
std::vector<double> x_input11 = {2,2,2,2,2,2,2,2};
if (x_input11.size() < numSlots)
x_input11 = Fill<double>(x_input11, numSlots);
Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x_input11, 1, ctxtAfterFBT->GetLevel());
auto c1 = cc->Encrypt(keyPair.publicKey, ptxt1);
auto ctxtAfterFBT2 = cc->EvalMult(ctxtAfterFBT1, c1);
//cc->ModReduceInPlace(ctxtAfterFBT2);
auto ctxtAfterFBT3 = cc->EvalHomDecoding(ctxtAfterFBT2, scaleTHI, 0);
auto ctxtResult = SchemeletRLWEMP::ConvertCKKSToRLWE(ctxtAfterFBT3, Qorig);
auto computed1 =
SchemeletRLWEMP::DecryptCoeff(ctxtResult, Qorig, pOrig, keyPair.secretKey, ep, numSlotsCKKS, numSlots);
std::cerr << "First 8 elements of the last sign: [";
std::copy_n(computed1.begin(), 8, std::ostream_iterator<int64_t>(std::cerr, " "));
std::cerr << "]" << std::endl;
}
if (checkgt2 && !go && !step) {
if (!binaryLUT)
coeffcomp = coeffcompStep;
scaleTHI = scaleStepTHI;
step = true;
go = true;
if (coeffcompMod.size() > 4 && GetMultiplicativeDepthByCoeffVector(coeffcompMod, true) >
GetMultiplicativeDepthByCoeffVector(coeffcompStep, true)) {
levelsToDrop = GetMultiplicativeDepthByCoeffVector(coeffcompMod, true) -
GetMultiplicativeDepthByCoeffVector(coeffcompStep, true);
}
}