// This file was autogenerated, do not modify by hand.
#![allow(unused_parens)]
#![allow(clippy::neg_multiply)]
#![allow(clippy::suspicious_operation_groupings)]

use crate::core_crypto::commons::dispersion::Variance;
use crate::core_crypto::commons::parameters::*;

/// This formula is only valid when going from a larger to a smaller modulus
pub fn multi_bit_modulus_switch_additive_variance(
    input_lwe_dimension: LweDimension,
    grouping_factor: f64,
    modulus: f64,
    new_modulus: f64,
) -> Variance {
    Variance(multi_bit_modulus_switch_additive_variance_impl(
        input_lwe_dimension.0 as f64,
        grouping_factor,
        modulus,
        new_modulus,
    ))
}

/// This formula is only valid when going from a larger to a smaller modulus
pub fn multi_bit_modulus_switch_additive_variance_impl(
    input_lwe_dimension: f64,
    grouping_factor: f64,
    modulus: f64,
    new_modulus: f64,
) -> f64 {
    grouping_factor.recip()
        * input_lwe_dimension
        * modulus.powf(-2.0)
        * (1.0 - 1.0 * (-1.0 * grouping_factor).exp2())
        * ((-1.0 * grouping_factor - 2.0).exp2()
            + (1_f64 / 12.0)
                * new_modulus.powf(-2.0)
                * (modulus.powf(2.0) - 1.0 * new_modulus.powf(2.0)))
        - 1_f64 / 12.0 * modulus.powf(-2.0)
        + (1_f64 / 12.0) * new_modulus.powf(-2.0)
}
