Understanding the GetLevel behavior in CiphertextImpl class

Hello everyone!

I have a question regarding the CiphertextImpl class in OpenFHE, specifically about the GetLevel function. According to the documentation, the function is described as:

inline size_t GetLevel() const

Get the number of scalings performed

The term “level” here refers to the number of scalings that have been performed. For CKKS, you need to perform bootstrapping once the value of GetLevel reaches the multiplicative depth.

I’m a bit confused about the terminology. In the papers I’ve read, the level typically decreases as multiplications are performed, but here it seems to increase. There’s also a LevelReduce function in CiphertextImpl that removes unnecessary RNS limbs, which reduces the level after multiplication. This seems to follow the convention from papers, where the level decreases, unlike GetLevel, which increases.

I’m curious about the reasoning behind counting the levels up from zero, rather than down from the multiplicative depth, which is more common in the literature and is consistent with the behavior of LevelReduce. Can anyone explain the motivation for this approach?

Thank you in advance!

From original CKKS bootstrapping paper:

From original CKKS paper:

Thank you for asking the question. There is a little bit history behind this. I agree there is a confusion here. The reasoning is that in OpenFHE the level is referred to as the current level of computation. First we compute at level 0, then at level 1 (until we reach the maximum number of levels, i.e., multiplicative depth). This is typically more intuitive for a user. In leveled FHE papers (for cryptographers), the focus is the on the internals of the scheme, i.e., rescaling/mod switching is done is after every level. The focus there is on the ciphertext modulus Q_L and how it decreases as the computation progresses. This is where the discrepancy comes from.

Thank you very much for answering, now I understand the reasons behind the naming!