Skip to content

Commit 01cf35a

Browse files
committed
Merge #22
22: Implementation of std::iter::{Product, Sum} r=cuviper a=dodomorandi This PR is relative to the [issue 4](#4). This is a very simple implementation, based on two macros. Maybe a more elegant solution is possible for these, feel free to suggest. Two tests for both `BigInt` and `BigUInt` have been added, one relative to the `Sum`, the other to the `Product`.
2 parents 65214f7 + 6091089 commit 01cf35a

File tree

5 files changed

+145
-1
lines changed

5 files changed

+145
-1
lines changed

src/bigint.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::cmp::Ordering::{self, Less, Greater, Equal};
66
use std::{i64, u64};
77
#[allow(unused_imports)]
88
use std::ascii::AsciiExt;
9+
use std::iter::{Product, Sum};
910

1011
#[cfg(feature = "serde")]
1112
use serde;
@@ -1779,6 +1780,9 @@ impl BigInt {
17791780
}
17801781
}
17811782

1783+
impl_sum_iter_type!(BigInt);
1784+
impl_product_iter_type!(BigInt);
1785+
17821786
/// Perform in-place two's complement of the given binary representation,
17831787
/// in little-endian byte order.
17841788
#[inline]

src/biguint.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22
use std::default::Default;
3-
use std::iter::repeat;
3+
use std::iter::{repeat, Product, Sum};
44
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub,
55
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign,
66
MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign};
@@ -1690,6 +1690,9 @@ pub fn trailing_zeros(u: &BigUint) -> Option<usize> {
16901690
.map(|(i, digit)| i * big_digit::BITS + digit.trailing_zeros() as usize)
16911691
}
16921692

1693+
impl_sum_iter_type!(BigUint);
1694+
impl_product_iter_type!(BigUint);
1695+
16931696
#[cfg(feature = "serde")]
16941697
impl serde::Serialize for BigUint {
16951698
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

src/macros.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,35 @@ macro_rules! promote_all_scalars {
314314
promote_signed_scalars!(impl $imp for $res, $method);
315315
}
316316
}
317+
318+
macro_rules! impl_sum_iter_type {
319+
($res:ty) => {
320+
impl<T> Sum<T> for $res
321+
where
322+
$res: Add<T, Output=$res>
323+
{
324+
fn sum<I>(iter: I) -> Self
325+
where
326+
I: Iterator<Item = T>
327+
{
328+
iter.fold(Zero::zero(), <$res>::add)
329+
}
330+
}
331+
};
332+
}
333+
334+
macro_rules! impl_product_iter_type {
335+
($res:ty) => {
336+
impl<T> Product<T> for $res
337+
where
338+
$res: Mul<T, Output=$res>
339+
{
340+
fn product<I>(iter: I) -> Self
341+
where
342+
I: Iterator<Item = T>
343+
{
344+
iter.fold(One::one(), <$res>::mul)
345+
}
346+
}
347+
};
348+
}

src/tests/bigint.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,3 +1217,55 @@ fn test_random_shr() {
12171217
}
12181218
}
12191219
}
1220+
#[test]
1221+
fn test_iter_sum() {
1222+
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();
1223+
let data: Vec<BigInt> = vec![
1224+
FromPrimitive::from_i32(-1000000).unwrap(),
1225+
FromPrimitive::from_i32(-200000).unwrap(),
1226+
FromPrimitive::from_i32(-30000).unwrap(),
1227+
FromPrimitive::from_i32(-4000).unwrap(),
1228+
FromPrimitive::from_i32(-500).unwrap(),
1229+
FromPrimitive::from_i32(-60).unwrap(),
1230+
FromPrimitive::from_i32(-7).unwrap(),
1231+
];
1232+
1233+
assert_eq!(result, data.iter().sum());
1234+
assert_eq!(result, data.into_iter().sum());
1235+
}
1236+
1237+
#[test]
1238+
fn test_iter_product() {
1239+
let data: Vec<BigInt> = vec![
1240+
FromPrimitive::from_i32(1001).unwrap(),
1241+
FromPrimitive::from_i32(-1002).unwrap(),
1242+
FromPrimitive::from_i32(1003).unwrap(),
1243+
FromPrimitive::from_i32(-1004).unwrap(),
1244+
FromPrimitive::from_i32(1005).unwrap(),
1245+
];
1246+
let result = data.get(0).unwrap() * data.get(1).unwrap() * data.get(2).unwrap()
1247+
* data.get(3).unwrap() * data.get(4).unwrap();
1248+
1249+
assert_eq!(result, data.iter().product());
1250+
assert_eq!(result, data.into_iter().product());
1251+
}
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: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,3 +1676,56 @@ fn test_mul_divide_torture() {
16761676
fn test_mul_divide_torture_long() {
16771677
test_mul_divide_torture_count(1000000);
16781678
}
1679+
1680+
#[test]
1681+
fn test_iter_sum() {
1682+
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();
1683+
let data: Vec<BigUint> = vec![
1684+
FromPrimitive::from_u32(1000000).unwrap(),
1685+
FromPrimitive::from_u32(200000).unwrap(),
1686+
FromPrimitive::from_u32(30000).unwrap(),
1687+
FromPrimitive::from_u32(4000).unwrap(),
1688+
FromPrimitive::from_u32(500).unwrap(),
1689+
FromPrimitive::from_u32(60).unwrap(),
1690+
FromPrimitive::from_u32(7).unwrap(),
1691+
];
1692+
1693+
assert_eq!(result, data.iter().sum());
1694+
assert_eq!(result, data.into_iter().sum());
1695+
}
1696+
1697+
#[test]
1698+
fn test_iter_product() {
1699+
let data: Vec<BigUint> = vec![
1700+
FromPrimitive::from_u32(1001).unwrap(),
1701+
FromPrimitive::from_u32(1002).unwrap(),
1702+
FromPrimitive::from_u32(1003).unwrap(),
1703+
FromPrimitive::from_u32(1004).unwrap(),
1704+
FromPrimitive::from_u32(1005).unwrap(),
1705+
];
1706+
let result = data.get(0).unwrap() * data.get(1).unwrap() * data.get(2).unwrap()
1707+
* data.get(3).unwrap() * data.get(4).unwrap();
1708+
1709+
assert_eq!(result, data.iter().product());
1710+
assert_eq!(result, data.into_iter().product());
1711+
}
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)