FLEXIBLEAUTO ScalingTechnique, GetNoiseScaleDeg and decryption in CKKS

Just for the record, this is the program that tries to decrypt with two and with one prime left.

#include "openfhe.h"

using namespace lbcrypto;

int get_number_primes(const Ciphertext<DCRTPoly>& ctxt1){
    const DCRTPoly& poly = ctxt1->GetElements()[0];
    return poly.GetNumOfElements();
}

int main(int argc, char* argv[]) {
    int numSlots = 8;
    // Step 1: Set CryptoContext
    CCParams<CryptoContextCKKSRNS> parameters;

    SecretKeyDist secretKeyDist = UNIFORM_TERNARY;
    parameters.SetSecretKeyDist(secretKeyDist);

    parameters.SetSecurityLevel(HEStd_NotSet);
    parameters.SetRingDim(1 << 12);

    parameters.SetNumLargeDigits(3);
    parameters.SetKeySwitchTechnique(HYBRID);

    ScalingTechnique rescaleTech = FLEXIBLEAUTO;
    usint dcrtBits               = 59;
    usint firstMod               = 60;

    parameters.SetScalingModSize(dcrtBits);
    parameters.SetScalingTechnique(rescaleTech);
    parameters.SetFirstModSize(firstMod);

	parameters.SetBatchSize(numSlots); // fix the number of slots for all plaintexts
	std::cout << "Parameters " << parameters << std::endl << std::endl;

    int depth = 5;
    parameters.SetMultiplicativeDepth(depth);

    // Generate crypto context.
    CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);

    // Enable features that you wish to use. Note, we must enable FHE to use bootstrapping.
    cryptoContext->Enable(PKE); 
    cryptoContext->Enable(KEYSWITCH);
    cryptoContext->Enable(LEVELEDSHE);
    cryptoContext->Enable(ADVANCEDSHE);

    usint ringDim = cryptoContext->GetRingDimension();
    std::cout << "CKKS scheme is using ring dimension " << ringDim << std::endl << std::endl;

    auto keyPair = cryptoContext->KeyGen();
    cryptoContext->EvalMultKeyGen(keyPair.secretKey);
   
    // Step 4: Encoding and encryption of inputs
    // Generate random input
    std::vector<double> x1;
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, 1.0);
    for (size_t i = 0; i < numSlots; i++)
        x1.push_back(dis(gen));
    
    Plaintext ptxt1 = cryptoContext->MakeCKKSPackedPlaintext(x1);
    ptxt1->SetLength(numSlots);
    std::cout << "Input 1: " << ptxt1 << std::endl;

    // Encrypt the encoded vector
    Ciphertext<DCRTPoly> ctxt1 = cryptoContext->Encrypt(keyPair.publicKey, ptxt1);

    std::cout << "Initial level ctxt1: " << ctxt1->GetLevel() << std::endl;
    std::cout << "depth: " << depth << std::endl;

    std::cout << "Number of primes in the moduli chain of ctxt1: " << get_number_primes(ctxt1) << std::endl;

	Ciphertext<DCRTPoly> cMul = cryptoContext->EvalMult(ctxt1, ctxt1);
    std::cout << "Number of primes in the moduli chain of cMul: " << get_number_primes(ctxt1) << std::endl << std::endl;
	
    while (get_number_primes(cMul) > 2)
        cMul = cryptoContext->EvalMult(cMul, ctxt1);
    
    std::cout << "Decrypting cMul while it has " << get_number_primes(cMul) << " primes in the moduli chain" << std::endl;
    Plaintext result;
    cryptoContext->Decrypt(keyPair.secretKey, cMul, &result);
    result->SetLength(numSlots);
    std::cout << "Decrypted result: " << result << std::endl << std::endl;

    cMul = cryptoContext->EvalMult(cMul, ctxt1); // this should drop one of the two remaining primes
    if (1 == get_number_primes(cMul)){
        std::cout << "Decrypting cMul while it has only 1 prime in the moduli chain" << std::endl;
        cryptoContext->Decrypt(keyPair.secretKey, cMul, &result);
        result->SetLength(numSlots);
        std::cout << "Decrypted result: " << result << std::endl;
    }
    return 0;
}

And this the ouput I get

Parameters scheme: CKKSRNS; ptModulus: 0; digitSize: 0; standardDeviation: 3.19; secretKeyDist: UNIFORM_TERNARY; maxRelinSkDeg: 2; ksTech: HYBRID; scalTech: FLEXIBLEAUTO; batchSize: 8; firstModSize: 60; numLargeDigits: 3; multiplicativeDepth:1; scalingModSize: 59; securityLevel: HEStd_NotSet; ringDim: 4096; evalAddCount: 0; keySwitchCount: 0; encryptionTechnique: STANDARD; multiplicationTechnique: HPS; PRENumHops: 0; PREMode: INDCPA; multipartyMode: FIXED_NOISE_MULTIPARTY; executionMode: EXEC_EVALUATION; decryptionNoiseMode: FIXED_NOISE_DECRYPT; noiseEstimate: 0; desiredPrecision: 25; statisticalSecurity: 30; numAdversarialQueries: 1; thresholdNumOfParties: 1; interactiveBootCompressionLevel: SLACK

CKKS scheme is using ring dimension 4096

Input 1: (0.937898, 0.798491, 0.889802, 0.0889563, 0.0410105, 0.435597, 0.0616124, 0.207677, … ); Estimated precision: 59 bits

Initial level ctxt1: 0
depth: 5
Number of primes in the moduli chain of ctxt1: 6
Number of primes in the moduli chain of cMul: 6

Decrypting cMul while it has 2 primes in the moduli chain
Decrypted result: (0.680667, 0.259191, 0.496319, 4.95521e-07, 4.75742e-09, 0.0068314, 5.47028e-08, 8.02298e-05, … ); Estimated precision: 49 bits

Decrypting cMul while it has only 1 prime in the moduli chain
terminate called after throwing an instance of ‘lbcrypto::OpenFHEException’
what(): /home/hilder/Documents/gitRepos/openfhe-src/src/pke/lib/encoding/ckkspackedencoding.cpp:l.537:Decode(): The decryption failed because the approximation error is too high. Check the parameters.
Aborted (core dumped)