A slightly question about EvalDivide function

The first question I’d like to ask is that in cryptocontext.h I see the EvalMult function described as Evaluate approximate division function 1/x where x >= 1 on a ciphertext using the Chebyshev approximation. But in MWE I used x= -5 to do the calculation without any error and the result was calculated (but incorrectly). Is this allowed behavior or a bug?

The second question is whether I have set this parameter incorrectly and when I change x to 5 the calculation is still incorrect. I don’t think the upper and lower bounds for MWE are set incorrectly. Is the result error because of the degree issue?

Here is a MWE that reproduces the issue:

int main() {

    uint32_t multDepth = 5;

 
    uint32_t scaleModSize = 58;


    uint32_t batchSize = 8;

    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetScalingModSize(scaleModSize);
    parameters.SetBatchSize(batchSize);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);


    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);
    std::cout << "CKKS scheme is using ring dimension " << cc->GetRingDimension() << std::endl << std::endl;


    auto keys = cc->KeyGen();

    cc->EvalMultKeyGen(keys.secretKey);


    cc->EvalRotateKeyGen(keys.secretKey, {1, -2});
    
    std::vector<double> x1 = {-5};


    Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x1);
    // Plaintext ptxt2 = cc->MakeCKKSPackedPlaintext(x2);

    std::cout << "Input x1: " << ptxt1 << std::endl;
    // std::cout << "Input x2: " << ptxt2 << std::endl;

    auto c1 = cc->Encrypt(keys.publicKey, ptxt1);
    // auto c2 = cc->Encrypt(keys.publicKey, ptxt2);

    
    double lowerBound = -10;
    double upperBound = 10;
    // std::complex<double> invalid_coefficient(std::nan(""), 0.0);
    std::vector<double> coefficients = {1e-10, -1.0e-10};
    auto result = cc->EvalDivide(c1, lowerBound, upperBound, 1);


    Plaintext res;

    std::cout.precision(8);

    std::cout << std::endl << "Results of homomorphic computations: " << std::endl;

    cc->Decrypt(keys.secretKey, result, &res);
    res->SetLength(1);
    std::cout << res << std::endl;
    
    return 0;
}

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

Best regards,
wowblk

Just my 2 cents here: perhaps it is not the right choice to use [-5,5] as the approximation interval since it contains x=0, where 1/x is not defined.

Plus, the fourth argument of EvalDivide is the polynomial degree, which should be set to a larger value, otherwise you are just creating a line.

I refer you to: https://openfhe.discourse.group/t/how-to-evaluate-approximate-1-x-function-with-high-precision/

Hi @wowblk8,

EvalDivide will only work correctly for x\ge1, as written in the documentation. As @narger noted, there is a discontinuity at 0, which complicates the division for the range you are trying to use. The last argument should be much higher than 1 to achieve reasonable precision (when the right range is used).

I see. but I tried some experiments with x <= 0 and lower/upper bound set to the negative scale. Such as I set x = -5 and lower/upper bound to (-1, -5). Then the calculated result is right. On the other hand, I tried the same number but with a positive one. Like x = 5 and lower/upper bound = (1, 5). they come up with the same result but positive one. So I think there is a gap between EvalDivide. EvalDivide function actually can calculate the negative divide equation. So I think the description is wrong or when in situations evaldivide function can’t guarantee OpenFHE library security. Anyways, I think the EvalDivide function is based on the EvalChebyshevSeries function, it should calculate -1…-∞ except 0. If the developer has any concerns about the negative side of the EvalDivide function. I think it should throw an error when the user setting to a negative one(value and lower/upper bound).

It is indeed normal for the Chebyshev approximation of division to work on intervals [-5, -1] and [1, 5]. The problem is when the interval contains 0, as division is not supported there. I think Yuriy meant |x| \geq 1, not x \geq 1. In theory, it should be |x| \geq \epsilon, but the smaller the \epsilon, the larger the required degree of the approximation.

@andreea.alexandru Thank you for correcting. Indeed, I meant |x| \ge 1.