malachite-nz 0.14.0

The bignum types Natural and Integer, with efficient algorithms partially derived from GMP and FLINT.
Documentation
// Copyright © 2026 Mikhail Hogrefe
//
// Uses code adopted from the FLINT Library.
//
//      Copyright © 2019 Daniel Schultz
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.

use crate::natural::InnerNatural::Small;
use crate::natural::Natural;
use crate::platform::Limb;
use core::borrow::Borrow;
use malachite_base::num::arithmetic::traits::ModSum;
use malachite_base::num::basic::traits::Zero;
use malachite_base::num::conversion::traits::ExactFrom;

fn assert_reduced(x: &Natural, m: &Natural) {
    assert!(x < m, "x must be reduced mod m, but {x} >= {m}");
}

// When `m` fits in a `Limb`, so does every reduced summand, and the `Limb` implementation sums
// them. Otherwise the summands are added exactly and the sum is reduced once at the end: it is less
// than `m` times the number of summands, so the final division has a short quotient.
fn mod_sum_helper<B: Borrow<Natural>, I: Iterator<Item = B>>(xs: I, m: &Natural) -> Natural {
    assert_ne!(*m, 0u32, "m cannot be zero");
    if let Natural(Small(small_m)) = *m {
        Natural::from(Limb::mod_sum(
            xs.map(|x| {
                let x = x.borrow();
                assert_reduced(x, m);
                Limb::exact_from(x)
            }),
            small_m,
        ))
    } else {
        let mut sum = Natural::ZERO;
        for x in xs {
            let x = x.borrow();
            assert_reduced(x, m);
            sum += x;
        }
        sum % m
    }
}

impl ModSum<Self, Self> for Natural {
    /// Adds up all the [`Natural`]s in an iterator, modulo another [`Natural`] $m$, taking the
    /// elements by value and the modulus by value. Every [`Natural`] in the iterator must be
    /// already reduced modulo $m$.
    ///
    /// $f((x_i)_ {i=0}^{n-1}, m) = y$, where $y < m$ and $\sum_ {i=0}^{n-1} x_i \equiv y \mod m$.
    ///
    /// # Worst-case complexity
    /// $T(n, m) = O(nm)$
    ///
    /// $M(m) = O(m)$
    ///
    /// where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is
    /// `m.significant_bits()`.
    ///
    /// # Panics
    /// Panics if `m` is zero or if any [`Natural`] in the iterator is greater than or equal to `m`.
    ///
    /// # Examples
    /// ```
    /// use core::str::FromStr;
    /// use malachite_base::num::arithmetic::traits::ModSum;
    /// use malachite_base::vecs::vec_from_str;
    /// use malachite_nz::natural::Natural;
    ///
    /// assert_eq!(
    ///     Natural::mod_sum(
    ///         vec_from_str::<Natural>("[2, 3, 5, 7]").unwrap().into_iter(),
    ///         Natural::from(10u32)
    ///     ),
    ///     7
    /// );
    /// let m = Natural::from_str("1000000000000000000000000000057").unwrap();
    /// let x = Natural::from_str("1000000000000000000000000000056").unwrap();
    /// assert_eq!(
    ///     Natural::mod_sum([x.clone(), x].into_iter(), m).to_string(),
    ///     "1000000000000000000000000000055"
    /// );
    /// ```
    #[inline]
    fn mod_sum<I: Iterator<Item = Self>>(xs: I, m: Self) -> Self {
        mod_sum_helper(xs, &m)
    }
}

impl<'b> ModSum<Self, &'b Self> for Natural {
    /// Adds up all the [`Natural`]s in an iterator, modulo another [`Natural`] $m$, taking the
    /// elements by value and the modulus by reference. Every [`Natural`] in the iterator must be
    /// already reduced modulo $m$.
    ///
    /// $f((x_i)_ {i=0}^{n-1}, m) = y$, where $y < m$ and $\sum_ {i=0}^{n-1} x_i \equiv y \mod m$.
    ///
    /// # Worst-case complexity
    /// $T(n, m) = O(nm)$
    ///
    /// $M(m) = O(m)$
    ///
    /// where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is
    /// `m.significant_bits()`.
    ///
    /// # Panics
    /// Panics if `m` is zero or if any [`Natural`] in the iterator is greater than or equal to `m`.
    ///
    /// # Examples
    /// ```
    /// use core::str::FromStr;
    /// use malachite_base::num::arithmetic::traits::ModSum;
    /// use malachite_base::vecs::vec_from_str;
    /// use malachite_nz::natural::Natural;
    ///
    /// assert_eq!(
    ///     Natural::mod_sum(
    ///         vec_from_str::<Natural>("[2, 3, 5, 7]").unwrap().into_iter(),
    ///         &Natural::from(10u32)
    ///     ),
    ///     7
    /// );
    /// let m = Natural::from_str("1000000000000000000000000000057").unwrap();
    /// let x = Natural::from_str("1000000000000000000000000000056").unwrap();
    /// assert_eq!(
    ///     Natural::mod_sum([x.clone(), x].into_iter(), &m).to_string(),
    ///     "1000000000000000000000000000055"
    /// );
    /// ```
    #[inline]
    fn mod_sum<I: Iterator<Item = Self>>(xs: I, m: &'b Self) -> Self {
        mod_sum_helper(xs, m)
    }
}

impl<'a> ModSum<&'a Self, Self> for Natural {
    /// Adds up all the [`Natural`]s in an iterator, modulo another [`Natural`] $m$, taking the
    /// elements by reference and the modulus by value. Every [`Natural`] in the iterator must be
    /// already reduced modulo $m$.
    ///
    /// $f((x_i)_ {i=0}^{n-1}, m) = y$, where $y < m$ and $\sum_ {i=0}^{n-1} x_i \equiv y \mod m$.
    ///
    /// # Worst-case complexity
    /// $T(n, m) = O(nm)$
    ///
    /// $M(m) = O(m)$
    ///
    /// where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is
    /// `m.significant_bits()`.
    ///
    /// # Panics
    /// Panics if `m` is zero or if any [`Natural`] in the iterator is greater than or equal to `m`.
    ///
    /// # Examples
    /// ```
    /// use core::str::FromStr;
    /// use malachite_base::num::arithmetic::traits::ModSum;
    /// use malachite_base::vecs::vec_from_str;
    /// use malachite_nz::natural::Natural;
    ///
    /// assert_eq!(
    ///     Natural::mod_sum(
    ///         vec_from_str::<Natural>("[2, 3, 5, 7]").unwrap().iter(),
    ///         Natural::from(10u32)
    ///     ),
    ///     7
    /// );
    /// let m = Natural::from_str("1000000000000000000000000000057").unwrap();
    /// let x = Natural::from_str("1000000000000000000000000000056").unwrap();
    /// assert_eq!(
    ///     Natural::mod_sum([x.clone(), x].iter(), m).to_string(),
    ///     "1000000000000000000000000000055"
    /// );
    /// ```
    #[inline]
    fn mod_sum<I: Iterator<Item = &'a Self>>(xs: I, m: Self) -> Self {
        mod_sum_helper(xs, &m)
    }
}

impl<'a, 'b> ModSum<&'a Self, &'b Self> for Natural {
    /// Adds up all the [`Natural`]s in an iterator, modulo another [`Natural`] $m$, taking the
    /// elements by reference and the modulus by reference. Every [`Natural`] in the iterator must
    /// be already reduced modulo $m$.
    ///
    /// $f((x_i)_ {i=0}^{n-1}, m) = y$, where $y < m$ and $\sum_ {i=0}^{n-1} x_i \equiv y \mod m$.
    ///
    /// # Worst-case complexity
    /// $T(n, m) = O(nm)$
    ///
    /// $M(m) = O(m)$
    ///
    /// where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is
    /// `m.significant_bits()`.
    ///
    /// # Panics
    /// Panics if `m` is zero or if any [`Natural`] in the iterator is greater than or equal to `m`.
    ///
    /// # Examples
    /// ```
    /// use core::str::FromStr;
    /// use malachite_base::num::arithmetic::traits::ModSum;
    /// use malachite_base::vecs::vec_from_str;
    /// use malachite_nz::natural::Natural;
    ///
    /// assert_eq!(
    ///     Natural::mod_sum(
    ///         vec_from_str::<Natural>("[2, 3, 5, 7]").unwrap().iter(),
    ///         &Natural::from(10u32)
    ///     ),
    ///     7
    /// );
    /// let m = Natural::from_str("1000000000000000000000000000057").unwrap();
    /// let x = Natural::from_str("1000000000000000000000000000056").unwrap();
    /// assert_eq!(
    ///     Natural::mod_sum([x.clone(), x].iter(), &m).to_string(),
    ///     "1000000000000000000000000000055"
    /// );
    /// ```
    #[inline]
    fn mod_sum<I: Iterator<Item = &'a Self>>(xs: I, m: &'b Self) -> Self {
        mod_sum_helper(xs, m)
    }
}