# Multiplying a ciphertext by a constant

Multiplying a ciphertext by a constant means multiplying a ciphertext by a constant (plaintext value). This is a leveled operation that increases noise, optionally consume padding, and optionally changes the encoding.

 ​ ​ Operation ​$E[m_1] * m_2 = E[m_1 * m_2]$​ Type Leveled Side effects Increases noise Potentially consumes padding Potentially modifies encoding

# Multiplying an LWE by a integer constant

By default, LWE ciphertexts can only be multiplied by integer constants. Under the hood, this is done by multiplying the ciphertext's body and mask by the constant. This is only currently implemented statically, i.e. without modifying the encoder, via the mul_constant_static_encoder method (and its mutable form mul_constant_static_encoder_inplace).

Because integer constant addition is implemented using a static encoder, the result of the multiplication should be in the interval of the ciphertext's encoder to avoid wrapping around with undefined behavior.

Here is an example using the mutable form:

/// file: main.rsuse concrete::*;​fn main() -> Result<(), CryptoAPIError> {    // encoder    let encoder = Encoder::new(-30., 30., 8, 0)?;​    // generate a secret key    let secret_key = LWESecretKey::new(&LWE128_1024);​    // encrypt the message    let message: f64 = 6.2;    let mut ciphertext = LWE::encode_encrypt(&secret_key, message, &encoder)?;    // multiply in place by an integer constant    let constant: i32 = -4;    ciphertext.mul_constant_static_encoder_inplace(constant)?;​    // decrypt    let output: f64 = ciphertext.decrypt_decode(&secret_key)?;​    println!("{} * {} = {}", message, constant, output);    Ok(())}

This operation is also available in vectorized form for VectorLWE instances, simply by passing a vector of integers to the mul_constant_static_encoder method:

// encode and encryptlet messages: Vec<f64> = vec![6.1, 5.4, -2.7];let mut ciphertext_vector = VectorLWE::encode_encrypt(&secret_key, &messages, &encoder)?;​// vector multiplication between ciphertext and constantslet constants: Vec<i32> = vec![-4, 5, 3];ciphertext_vector.mul_constant_static_encoder_inplace(&constants)?;​// decryptionlet outputs: Vec<f64> = ciphertext_vector.decrypt_decode(&secret_key)?;

# Multiplying an LWE by a real constant

Multiplying a ciphertext by a real-valued constant is supported in Concrete thanks to the use of padding in the encoder, via the mul_constant_with_padding method (and its mutable counterpart mul_constant_with_padding_inplace). The method take 3 arguments:

• constant: the constant to multiply the ciphertext by, as a float64

• max_constant: the maximum value the constant can take. This is necessary to determine the encoding of the result of the multiplication, and particularly useful when multiplying several ciphertexts by different constants (for example when working with VectorLWE), as the output encoding of the ciphertexts will end up being the same.

• nb_bit_padding: the number of bits of padding to be consumed by the multiplication, which also represents the precision of the constant being multiplied. This cannot be bigger than the remaining bits of padding in the ciphertext being multiplied.

Here is an example code:

use concrete::*;​fn main() -> Result<(), CryptoAPIError> {    // encoder    let encoder = Encoder::new(-10., 10., 10, 4)?;​    // generate a secret key    let secret_key = LWESecretKey::new(&LWE128_1024);​    // encrypt the message    let message: f64 = 4.;    let mut ciphertext = LWE::encode_encrypt(&secret_key, message, &encoder)?;        // multiply in place by a 4-bit real constant    let constant: f64 = 2.5;    let max_constant: f64 = 3.;    let nb_bit_padding = 4;    ciphertext.mul_constant_with_padding_inplace(constant, max_constant, nb_bit_padding)?;​    // decrypt    let output: f64 = ciphertext.decrypt_decode(&secret_key)?;​    println!("{} * {} = {}", message, constant, output);    Ok(())}

And in vectorized form, where all ciphertexts end up with the same encoder interval:

// encode and encryptlet messages: Vec<f64> = vec![6.1, 5.4, -2.7];let mut ciphertext_vector = VectorLWE::encode_encrypt(&secret_key, &messages, &encoder)?;​// vector multiplication between ciphertext and constantslet constants: Vec<f64> = vec![-2.1, 1.4, 3.2];let max_constant: f64 = 4.;let nb_bit_padding = 4;ciphertext_vector.mul_constant_with_padding_inplace(&constants, max_constant, nb_bit_padding)?;​// decryptionlet outputs: Vec<f64> = ciphertext_vector.decrypt_decode(&secret_key)?;