pub fn msm<const NUM_LIMBS: usize, G>(
    cs: &[UnsignedInteger<NUM_LIMBS>],
    points: &[G],
) -> Result<G, MSMError>
where
    G: IsGroup,
{
    if cs.len() != points.len() {
        return Err(MSMError::LengthMismatch(cs.len(), points.len()));
    }

    let window_size = optimum_window_size(cs.len());

    Ok(msm_with(cs, points, window_size))
}
This function computes the multiscalar multiplication (MSM).

Assume a group G of order r is given.
Let `points = [g_1, ..., g_n]` be a tuple of group points in G and
let `cs = [k_1, ..., k_n]` be a tuple of scalars in the Galois field GF(r).

Then, with additive notation, `msm(cs, points)` computes k_1 * g_1 + .... + k_n * g_n.

If `points` and `cs` are empty, then `msm` returns the zero element of the group.

Panics if `cs` and `points` have different lengths.
crates/math/src/msm/pippenger.rs