malachite_nz/integer_vector/arithmetic/sum.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::integer_vector::IntegerVector;
10use core::iter::Sum;
11
12const EMPTY: &str = "cannot sum an empty iterator of vectors: the dimension is unknown";
13
14impl Sum for IntegerVector {
15 /// Adds up all the [`IntegerVector`]s in an iterator, entry by entry.
16 ///
17 /// The vectors must all have the same dimension, which is also the dimension of the sum. Since
18 /// the dimension of the zero vector cannot be inferred from an empty iterator, an empty
19 /// iterator panics rather than summing to zero.
20 ///
21 /// $$
22 /// f((v_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} v_i.
23 /// $$
24 ///
25 /// # Worst-case complexity
26 /// $T(n) = O(n^2)$
27 ///
28 /// $M(n) = O(n)$
29 ///
30 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
31 /// elements of all the vectors.
32 ///
33 /// # Panics
34 /// Panics if the iterator is empty or if the vectors do not all have the same dimension.
35 ///
36 /// # Examples
37 /// ```
38 /// use core::iter::Sum;
39 /// use core::str::FromStr;
40 /// use malachite_nz::integer_vector::IntegerVector;
41 ///
42 /// let vs = ["(1, -2, 3)", "(-4, 5, -6)", "(7, 8, -9)"]
43 /// .map(|s| IntegerVector::from_str(s).unwrap());
44 /// assert_eq!(
45 /// IntegerVector::sum(vs.into_iter()).to_string(),
46 /// "(4, 11, -12)"
47 /// );
48 ///
49 /// let vs = [
50 /// "(18446744073709551615, -1)",
51 /// "(-18446744073709551616, 1267650600228229401496703205376)",
52 /// ]
53 /// .map(|s| IntegerVector::from_str(s).unwrap());
54 /// assert_eq!(
55 /// IntegerVector::sum(vs.into_iter()).to_string(),
56 /// "(-1, 1267650600228229401496703205375)"
57 /// );
58 /// ```
59 fn sum<I>(mut xs: I) -> Self
60 where
61 I: Iterator<Item = Self>,
62 {
63 let mut sum = xs.next().expect(EMPTY);
64 for v in xs {
65 sum += v;
66 }
67 sum
68 }
69}
70
71impl<'a> Sum<&'a Self> for IntegerVector {
72 /// Adds up all the [`IntegerVector`]s in an iterator of references, entry by entry.
73 ///
74 /// The vectors must all have the same dimension, which is also the dimension of the sum. Since
75 /// the dimension of the zero vector cannot be inferred from an empty iterator, an empty
76 /// iterator panics rather than summing to zero.
77 ///
78 /// $$
79 /// f((v_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} v_i.
80 /// $$
81 ///
82 /// # Worst-case complexity
83 /// $T(n) = O(n^2)$
84 ///
85 /// $M(n) = O(n)$
86 ///
87 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
88 /// elements of all the vectors.
89 ///
90 /// # Panics
91 /// Panics if the iterator is empty or if the vectors do not all have the same dimension.
92 ///
93 /// # Examples
94 /// ```
95 /// use core::iter::Sum;
96 /// use core::str::FromStr;
97 /// use malachite_nz::integer_vector::IntegerVector;
98 ///
99 /// let vs = ["(1, -2, 3)", "(-4, 5, -6)", "(7, 8, -9)"]
100 /// .map(|s| IntegerVector::from_str(s).unwrap());
101 /// assert_eq!(IntegerVector::sum(vs.iter()).to_string(), "(4, 11, -12)");
102 ///
103 /// let vs = [
104 /// "(18446744073709551615, -1)",
105 /// "(-18446744073709551616, 1267650600228229401496703205376)",
106 /// ]
107 /// .map(|s| IntegerVector::from_str(s).unwrap());
108 /// assert_eq!(
109 /// IntegerVector::sum(vs.iter()).to_string(),
110 /// "(-1, 1267650600228229401496703205375)"
111 /// );
112 /// ```
113 fn sum<I>(mut xs: I) -> Self
114 where
115 I: Iterator<Item = &'a Self>,
116 {
117 let mut sum = xs.next().expect(EMPTY).clone();
118 for v in xs {
119 sum += v;
120 }
121 sum
122 }
123}