Merge #22
22: Implementation of std::iter::{Product, Sum} r=cuviper a=dodomorandi This PR is relative to the [issue 4](https://github.com/rust-num/num-bigint/issues/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`.
This commit is contained in:
commit
01cf35ae3c
@ -6,6 +6,7 @@ use std::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use std::{i64, u64};
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::iter::{Product, Sum};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
@ -1779,6 +1780,9 @@ impl BigInt {
|
||||
}
|
||||
}
|
||||
|
||||
impl_sum_iter_type!(BigInt);
|
||||
impl_product_iter_type!(BigInt);
|
||||
|
||||
/// Perform in-place two's complement of the given binary representation,
|
||||
/// in little-endian byte order.
|
||||
#[inline]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::borrow::Cow;
|
||||
use std::default::Default;
|
||||
use std::iter::repeat;
|
||||
use std::iter::{repeat, Product, Sum};
|
||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub,
|
||||
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign,
|
||||
MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign};
|
||||
@ -1690,6 +1690,9 @@ pub fn trailing_zeros(u: &BigUint) -> Option<usize> {
|
||||
.map(|(i, digit)| i * big_digit::BITS + digit.trailing_zeros() as usize)
|
||||
}
|
||||
|
||||
impl_sum_iter_type!(BigUint);
|
||||
impl_product_iter_type!(BigUint);
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for BigUint {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -314,3 +314,35 @@ macro_rules! promote_all_scalars {
|
||||
promote_signed_scalars!(impl $imp for $res, $method);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_sum_iter_type {
|
||||
($res:ty) => {
|
||||
impl<T> Sum<T> for $res
|
||||
where
|
||||
$res: Add<T, Output=$res>
|
||||
{
|
||||
fn sum<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(Zero::zero(), <$res>::add)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_product_iter_type {
|
||||
($res:ty) => {
|
||||
impl<T> Product<T> for $res
|
||||
where
|
||||
$res: Mul<T, Output=$res>
|
||||
{
|
||||
fn product<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(One::one(), <$res>::mul)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1217,3 +1217,55 @@ fn test_random_shr() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_iter_sum() {
|
||||
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();
|
||||
let data: Vec<BigInt> = vec![
|
||||
FromPrimitive::from_i32(-1000000).unwrap(),
|
||||
FromPrimitive::from_i32(-200000).unwrap(),
|
||||
FromPrimitive::from_i32(-30000).unwrap(),
|
||||
FromPrimitive::from_i32(-4000).unwrap(),
|
||||
FromPrimitive::from_i32(-500).unwrap(),
|
||||
FromPrimitive::from_i32(-60).unwrap(),
|
||||
FromPrimitive::from_i32(-7).unwrap(),
|
||||
];
|
||||
|
||||
assert_eq!(result, data.iter().sum());
|
||||
assert_eq!(result, data.into_iter().sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_product() {
|
||||
let data: Vec<BigInt> = vec![
|
||||
FromPrimitive::from_i32(1001).unwrap(),
|
||||
FromPrimitive::from_i32(-1002).unwrap(),
|
||||
FromPrimitive::from_i32(1003).unwrap(),
|
||||
FromPrimitive::from_i32(-1004).unwrap(),
|
||||
FromPrimitive::from_i32(1005).unwrap(),
|
||||
];
|
||||
let result = data.get(0).unwrap() * data.get(1).unwrap() * data.get(2).unwrap()
|
||||
* data.get(3).unwrap() * data.get(4).unwrap();
|
||||
|
||||
assert_eq!(result, data.iter().product());
|
||||
assert_eq!(result, data.into_iter().product());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_sum_generic() {
|
||||
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();
|
||||
let data = vec![-1000000, -200000, -30000, -4000, -500, -60, -7];
|
||||
|
||||
assert_eq!(result, data.iter().sum());
|
||||
assert_eq!(result, data.into_iter().sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_product_generic() {
|
||||
let data = vec![1001, -1002, 1003, -1004, 1005];
|
||||
let result = data[0].to_bigint().unwrap() * data[1].to_bigint().unwrap()
|
||||
* data[2].to_bigint().unwrap() * data[3].to_bigint().unwrap()
|
||||
* data[4].to_bigint().unwrap();
|
||||
|
||||
assert_eq!(result, data.iter().product());
|
||||
assert_eq!(result, data.into_iter().product());
|
||||
}
|
||||
|
@ -1676,3 +1676,56 @@ fn test_mul_divide_torture() {
|
||||
fn test_mul_divide_torture_long() {
|
||||
test_mul_divide_torture_count(1000000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_sum() {
|
||||
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();
|
||||
let data: Vec<BigUint> = vec![
|
||||
FromPrimitive::from_u32(1000000).unwrap(),
|
||||
FromPrimitive::from_u32(200000).unwrap(),
|
||||
FromPrimitive::from_u32(30000).unwrap(),
|
||||
FromPrimitive::from_u32(4000).unwrap(),
|
||||
FromPrimitive::from_u32(500).unwrap(),
|
||||
FromPrimitive::from_u32(60).unwrap(),
|
||||
FromPrimitive::from_u32(7).unwrap(),
|
||||
];
|
||||
|
||||
assert_eq!(result, data.iter().sum());
|
||||
assert_eq!(result, data.into_iter().sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_product() {
|
||||
let data: Vec<BigUint> = vec![
|
||||
FromPrimitive::from_u32(1001).unwrap(),
|
||||
FromPrimitive::from_u32(1002).unwrap(),
|
||||
FromPrimitive::from_u32(1003).unwrap(),
|
||||
FromPrimitive::from_u32(1004).unwrap(),
|
||||
FromPrimitive::from_u32(1005).unwrap(),
|
||||
];
|
||||
let result = data.get(0).unwrap() * data.get(1).unwrap() * data.get(2).unwrap()
|
||||
* data.get(3).unwrap() * data.get(4).unwrap();
|
||||
|
||||
assert_eq!(result, data.iter().product());
|
||||
assert_eq!(result, data.into_iter().product());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_sum_generic() {
|
||||
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();
|
||||
let data = vec![1000000_u32, 200000, 30000, 4000, 500, 60, 7];
|
||||
|
||||
assert_eq!(result, data.iter().sum());
|
||||
assert_eq!(result, data.into_iter().sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_product_generic() {
|
||||
let data = vec![1001_u32, 1002, 1003, 1004, 1005];
|
||||
let result = data[0].to_biguint().unwrap() * data[1].to_biguint().unwrap()
|
||||
* data[2].to_biguint().unwrap() * data[3].to_biguint().unwrap()
|
||||
* data[4].to_biguint().unwrap();
|
||||
|
||||
assert_eq!(result, data.iter().product());
|
||||
assert_eq!(result, data.into_iter().product());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user