I am trying to perform an operation that is of the form: (A * B) + C. The multiplication works fine, as all the numbers have the same scale at that point, but the product of A * B has a different scale than C. It makes sense that multiplication would change the scale, but I was wondering if there was a way to perform an operation like this using the SEAL library.
Environment information:
Thank you in advance and let me know if further information is needed.
There are multiple ways of getting this to work. For example, suppose ciphertexts A, B, C all have the same scale Z. Then A * B will have scale Z^2. At this point you should also relinearize A * B unless you have a strong reason not to.
To compute A * B + C, you could for instance:
multiply_plain
to multiply C with a scalar 1.0 plaintext with scale Z to increase the scale to Z^2 but keep the value the same (there is an overload for CKKSEncoder::encode
for this);coeff_modulus
. Now, you could re-encode C to have scale exactly Z^2/q_k (if you have the plaintext), or multiply C with a scalar 1.0 plaintext as explained above to change the scale to exactly Z^2/q_k; double &Ciphertext::scale()
to set the scale of A * B to exactly C.scale()
at the cost of a small multiplicative error ~ Z/q_k. For example, instead of scale 2^60 for A, B, C you could use static_cast<double>(parms.coeff_modulus().back())
. Then Z^2/q_k = Z (exactly) and the addition works immediately without any scale switching. Of course, this doesn't work so well anymore after a second multiply+rescale as the second to last prime can no longer be equal to Z (all primes in coeff_modulus
must be distinct).