CKKS EvalMult in some cases pop up negative

With ScaleModSize=58, multiplying by 32 results in -32.
In the case of ScaleModSize=59, multiplying by 16 results in -16.
57 and so on.
The output is: multed 32: (-32, ... ); Estimated precision: 36 bits
Even if I adjust multDepth = 1 to the 50 case, I still get this result. And this result only occurs in FIXEDMANUAL and FIXEDAUTO modes. FLEXIBLEAUTO and FLEXIBLEAUTOEXT modes are correct. And I try the ModReduce after every multipcation in FIXEDMANUAL mode. It just still get this negative result.
I know 2^{58} * value (32 = 2^5) definitely bigger than 2^{60}. you will have an overflow; but why other number did not pop up negative number? Such 2^{58} * value(64=2^6 or 16 = 2^4)
Here is the MWE

int main(int argc, char* argv[]) {
    uint32_t multDepth = 5;
    uint32_t scaleModSize = 58; 
    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetScalingModSize(scaleModSize);
    parameters.SetScalingTechnique(FIXEDMANUAL); 
    parameters.SetFirstModSize(60);
    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);

    std::string version = GetOPENFHEVersion();
    std::cout << "OpenFHE version: " << version << std::endl;

    std::cout << parameters << std::endl;

    cc->Enable(PKE);
    cc->Enable(LEVELEDSHE);
    auto keys = cc->KeyGen();
    auto val = cc->Encrypt(keys.publicKey, cc->MakeCKKSPackedPlaintext(vector<double>{1}));  
    
    for(int i = 0; i< 1000; i++){
        auto multed = cc -> EvalMult(val, i);
        Plaintext p;
        cc->Decrypt(keys.secretKey, multed, &p);
        p->SetLength(1);
        cout << "multed " << to_string(i) << ":\t" << p << endl;
    }
}

Is this a bug?

I would really appreciate any insights or explanations regarding this behavior.
Thank you for your help!

Best regards,
wowblk

1 Like

It is caused by 2^scaleModSize * i = 2^63, which is a corner case on what can be represented as 64-bit signed integers, because int64_t(2^63) is represented as -2^63. Instead of taking some action when the value was < than 2^63 and some other action when >= 2^63, the code is doing <= and >. Thank you for pointing this out, we will fix it!