Setting the special primes p

From this post Question about the composition of the modular chain, I understand the following about the parameters for the modulus Q and its RNS decomposition: 1) multDepth + 1 is equal to the moduli chain length q_0, ..., q_{multDepth}, 2) the bit size of q_0 is firstModSize, 3) scalingModSize determines the bit size of the moduli q_1, ..., q_{multDepth}.

Further I understand that additional primes are added as part of hybrid keyswitching, for a modulus P.
My question is how are these determined in openFHE, both their chain length and bit size?
Also from the link above, is the special auxiliary modulus q_23 considered apart of the modulus chain for P used in hybrid keyswitching?

Finally a library request would be to have the option to set these FHE parameters more directly (such as by manually specifying the moduli chain) as an alternative option for people doing benchmarking/researchers.

Hi, I’d be happy to share some insights on this.

First, the firstModSize and scalingModSize parameters are determined in the file: src/pke/include/scheme/gen-cryptocontext-params.h. The specific code is:

// firstModSize and scalingModSize are used to calculate ciphertext modulus. The ciphertext modulus should be seen as:
    // Q = q_0 * q_1 * ... * q_n * q'
    // where q_0 is first prime, and it's number of bits is firstModSize
    // other q_i have same number of bits and is equal to scalingModSize
    // the prime q' is not explicitly given,
    // but it is used internally in CKKS and BGV schemes (in *EXT scaling methods)
    uint32_t firstModSize;
    uint32_t scalingModSize;

The auxiliary modulus P is determined in the file: src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp with the following code:

#if NATIVEINT == 128
constexpr size_t AUXMODSIZE = 119;
#elif NATIVEINT == 32
constexpr size_t AUXMODSIZE = 28;
#else
constexpr size_t AUXMODSIZE = 60;
#endif

The moduli chain generation is handled in the file: src/pke/include/scheme/ckksrns/ckksrns-parametergeneration.h with this code:

protected:
    void CompositePrimeModuliGen(std::vector<NativeInteger>& moduliQ, std::vector<NativeInteger>& rootsQ,
                                 uint32_t compositeDegree, uint32_t numPrimes, uint32_t firstModSize, uint32_t dcrtBits,
                                 uint32_t cyclOrder, uint32_t registerWordSize) const;

    void SinglePrimeModuliGen(std::vector<NativeInteger>& moduliQ, std::vector<NativeInteger>& rootsQ,
                              ScalingTechnique scalTech, uint32_t numPrimes, uint32_t firstModSize, uint32_t dcrtBits,
                              uint32_t cyclOrder, uint32_t extraModsize) const;

Regarding the special auxiliary modulus q_{23}​, it is not used for hybrid keyswitching. Instead, it is employed for error reduction in FLEXIBLEAUTOEXT mode. You can find more details about this in the paper: Approximate Homomorphic Encryption with Reduced Approximation Error.
As for your final request, while firstModSize and scalingModSize can be relatively easily customized by users, the auxiliary modulus P is more challenging to configure manually. I believe it would be beneficial for the OpenFHE team to provide more flexible interfaces for setting these parameters, especially to support advanced research scenarios. For instance, recent work like: SHIP: A Shallow and Highly Parallelizable CKKS Bootstrapping Algorithm demonstrates innovative uses of the auxiliary modulus P for plaintext-ciphertext multiplication, which can save computational levels. Having more granular control over these parameters would enable researchers to explore such optimizations more effectively.

3 Likes

Thank you so much @haohaohao.

Soooooo Helpful !!! You are so intelligent.