LWE Mod switching

Is there an easier way to grab the output of the lwe mod switching without reading the body and mask separately and reconstructing them both back into a LweCiphertextOwned?

  //mod switch LWE ciphertext modulus to 2N
  println!("Mod switching LWE ciphertext modulus to 2N...");
  let log_modulus = params.polynomial_size.to_blind_rotation_input_modulus_log();
  let (pbs_key, ..) = server_key.clone().into_raw_parts();
  let pbs_key_impl = pbs_key.into_raw_parts();
  let lazy_msed_ct = match pbs_key_impl.atomic_pattern {
      AtomicPatternServerKey::Standard(key_ap) => match key_ap.bootstrapping_key {
          ShortintBootstrappingKey::Classic {
              bsk: _,
              modulus_switch_noise_reduction_key,
          } => modulus_switch_noise_reduction_key
              .lwe_ciphertext_modulus_switch::<u64, Vec<u64>>(
                  &lwe_ciphertext_in,
                  log_modulus,
              ),
          _ => {
              unimplemented!();
          }
      },
      _ => {
          unimplemented!();
      }
  };

  let lwe_ms_mask = lazy_msed_ct.mask();
  let lwe_ms_body = lazy_msed_ct.body(); 

There is none that I know of, you can use this snippet:

fn modswitched_to_lwe(
    modswitched: &LazyStandardModulusSwitchedLweCiphertext<u64, usize, Vec<u64>>,
) -> LweCiphertextOwned<usize> {
    let cont = modswitched
        .mask()
        .chain(std::iter::once(modswitched.body()))
        // The coefficients are converted to use the power of two encoding
        .map(|coeff| coeff << (usize::BITS as usize - modswitched.log_modulus().0))
        .collect();

    LweCiphertext::from_container(
        cont,
        CiphertextModulus::new(1 << modswitched.log_modulus().0),
    )
}

Please beware that the lwe after modswitch are very noisy, so you cannot do much more than a blind rotation with these anyways.

1 Like

Thank you. Yes the output of this LWE mod switch is going directly into the blind rotation anyway in my situation

Actually, I forgot that there is a From implem on main that does just that,
so on the main branch/upcoming tfhe-rs 1.5 you can just do:

let lwe = LweCiphertext::from(lazy_ms_ct);
1 Like