diff --git a/src/edwards.rs b/src/edwards.rs index 98512fa..68e6b9f 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -556,21 +556,31 @@ impl MultiscalarMul for EdwardsPoint { J: IntoIterator, J::Item: Borrow, { - // XXX later when we do more fancy multiscalar mults, we can - // delegate based on the iter's size hint -- hdevalence + // Sanity-check lengths of input iterators + let mut scalars = scalars.into_iter(); + let mut points = points.into_iter(); + + // Lower and upper bounds on iterators + let (s_lo, s_hi) = scalars.by_ref().size_hint(); + let (p_lo, p_hi) = points.by_ref().size_hint(); + + // They should all be equal + assert_eq!(s_lo, p_lo); + assert_eq!(s_hi, Some(s_lo)); + assert_eq!(p_hi, Some(p_lo)); + + // Now we know there's a single size. When we do + // size-dependent algorithm dispatch, use this as the hint. + let _size = s_lo; // If we built with AVX2, use the AVX2 backend. #[cfg(all(feature="avx2_backend", target_feature="avx2"))] - { - use backend::avx2::scalar_mul::straus::Straus; - Straus::multiscalar_mul(scalars, points) - } + use backend::avx2::scalar_mul::straus::Straus; // Otherwise, proceed as normal: #[cfg(not(all(feature="avx2_backend", target_feature="avx2")))] - { - use scalar_mul::straus::Straus; - Straus::multiscalar_mul(scalars, points) - } + use scalar_mul::straus::Straus; + + Straus::multiscalar_mul(scalars, points) } } @@ -584,21 +594,31 @@ impl VartimeMultiscalarMul for EdwardsPoint { I::Item: Borrow, J: IntoIterator>, { - // XXX later when we do more fancy multiscalar mults, we can - // delegate based on the iter's size hint -- hdevalence + // Sanity-check lengths of input iterators + let mut scalars = scalars.into_iter(); + let mut points = points.into_iter(); + + // Lower and upper bounds on iterators + let (s_lo, s_hi) = scalars.by_ref().size_hint(); + let (p_lo, p_hi) = points.by_ref().size_hint(); + + // They should all be equal + assert_eq!(s_lo, p_lo); + assert_eq!(s_hi, Some(s_lo)); + assert_eq!(p_hi, Some(p_lo)); + + // Now we know there's a single size. When we do + // size-dependent algorithm dispatch, use this as the hint. + let _size = s_lo; // If we built with AVX2, use the AVX2 backend. #[cfg(all(feature="avx2_backend", target_feature="avx2"))] - { - use backend::avx2::scalar_mul::straus::Straus; - Straus::optional_multiscalar_mul(scalars, points) - } + use backend::avx2::scalar_mul::straus::Straus; // Otherwise, proceed as normal: #[cfg(not(all(feature="avx2_backend", target_feature="avx2")))] - { - use scalar_mul::straus::Straus; - Straus::optional_multiscalar_mul(scalars, points) - } + use scalar_mul::straus::Straus; + + Straus::optional_multiscalar_mul(scalars, points) } }