Skip to content

Commit d6fa4ac

Browse files
dodomorandicuviper
authored andcommitted
Generic implementation for Sum and Product
The succestion came from @cupiver, and it was simple and elegant. Now it should be possible to use `std::iter::{Sum, Product}` with everything that can be Add`-ed and `Mul`-tiplied _against_ `BigInt` and `BigUint`
1 parent 68600a3 commit d6fa4ac

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

src/macros.rs

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -317,42 +317,32 @@ macro_rules! promote_all_scalars {
317317

318318
macro_rules! impl_sum_iter_type {
319319
($res:ty) => {
320-
impl Sum for $res {
321-
impl_sum_iter_type!($res, $res);
322-
}
323-
324-
impl<'a> Sum<&'a $res> for $res {
325-
impl_sum_iter_type!($res, &'a $res);
326-
}
327-
};
328-
329-
($res:ty, $item:ty) => {
330-
fn sum<I>(iter: I) -> Self
320+
impl<T> Sum<T> for $res
331321
where
332-
I: Iterator<Item = $item>
322+
$res: Add<T, Output=Self>
333323
{
334-
iter.fold(Zero::zero(), <$res>::add)
324+
fn sum<I>(iter: I) -> Self
325+
where
326+
I: Iterator<Item = T>
327+
{
328+
iter.fold(Zero::zero(), <$res>::add)
329+
}
335330
}
336331
};
337332
}
338333

339334
macro_rules! impl_product_iter_type {
340335
($res:ty) => {
341-
impl Product for $res {
342-
impl_product_iter_type!($res, $res);
343-
}
344-
345-
impl<'a> Product<&'a $res> for $res {
346-
impl_product_iter_type!($res, &'a $res);
347-
}
348-
};
349-
350-
($res:ty, $item:ty) => {
351-
fn product<I>(iter: I) -> Self
336+
impl<T> Product<T> for $res
352337
where
353-
I: Iterator<Item = $item>
338+
$res: Mul<T, Output=Self>
354339
{
355-
iter.fold(One::one(), <$res>::mul)
340+
fn product<I>(iter: I) -> Self
341+
where
342+
I: Iterator<Item = T>
343+
{
344+
iter.fold(One::one(), <$res>::mul)
345+
}
356346
}
357347
};
358348
}

src/tests/bigint.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,3 +1249,23 @@ fn test_iter_product() {
12491249
assert_eq!(result, data.iter().product());
12501250
assert_eq!(result, data.into_iter().product());
12511251
}
1252+
1253+
#[test]
1254+
fn test_iter_sum_generic() {
1255+
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();
1256+
let data = vec![-1000000, -200000, -30000, -4000, -500, -60, -7];
1257+
1258+
assert_eq!(result, data.iter().sum());
1259+
assert_eq!(result, data.into_iter().sum());
1260+
}
1261+
1262+
#[test]
1263+
fn test_iter_product_generic() {
1264+
let data = vec![1001, -1002, 1003, -1004, 1005];
1265+
let result = data[0].to_bigint().unwrap() * data[1].to_bigint().unwrap()
1266+
* data[2].to_bigint().unwrap() * data[3].to_bigint().unwrap()
1267+
* data[4].to_bigint().unwrap();
1268+
1269+
assert_eq!(result, data.iter().product());
1270+
assert_eq!(result, data.into_iter().product());
1271+
}

src/tests/biguint.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,3 +1709,23 @@ fn test_iter_product() {
17091709
assert_eq!(result, data.iter().product());
17101710
assert_eq!(result, data.into_iter().product());
17111711
}
1712+
1713+
#[test]
1714+
fn test_iter_sum_generic() {
1715+
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();
1716+
let data = vec![1000000_u32, 200000, 30000, 4000, 500, 60, 7];
1717+
1718+
assert_eq!(result, data.iter().sum());
1719+
assert_eq!(result, data.into_iter().sum());
1720+
}
1721+
1722+
#[test]
1723+
fn test_iter_product_generic() {
1724+
let data = vec![1001_u32, 1002, 1003, 1004, 1005];
1725+
let result = data[0].to_biguint().unwrap() * data[1].to_biguint().unwrap()
1726+
* data[2].to_biguint().unwrap() * data[3].to_biguint().unwrap()
1727+
* data[4].to_biguint().unwrap();
1728+
1729+
assert_eq!(result, data.iter().product());
1730+
assert_eq!(result, data.into_iter().product());
1731+
}

0 commit comments

Comments
 (0)