Skip to content

Commit

Permalink
Auto merge of #23293 - tbu-:pr_additive_multiplicative, r=alexcrichton
Browse files Browse the repository at this point in the history
Previously it could not be implemented for types outside `libcore/iter.rs` due
to coherence issues.
  • Loading branch information
bors committed Apr 8, 2015
2 parents d9146bf + 97f24a8 commit dd6c4a8
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 133 deletions.
3 changes: 1 addition & 2 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ use core::clone::Clone;
use core::cmp::Ordering::{self, Greater, Less};
use core::cmp::{self, Ord, PartialEq};
use core::iter::Iterator;
use core::iter::MultiplicativeIterator;
use core::marker::Sized;
use core::mem::size_of;
use core::mem;
Expand Down Expand Up @@ -1182,7 +1181,7 @@ impl Iterator for ElementSwaps {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// For a vector of size n, there are exactly n! permutations.
let n = (2..self.sdir.len() + 1).product();
let n: usize = (2..self.sdir.len() + 1).product();
(n - self.swaps_made, Some(n - self.swaps_made))
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ use self::RecompositionState::*;
use self::DecompositionType::*;

use core::clone::Clone;
use core::iter::AdditiveIterator;
use core::iter::{Iterator, Extend};
use core::option::Option::{self, Some, None};
use core::result::Result;
Expand Down Expand Up @@ -116,7 +115,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
// this is wrong without the guarantee that `self` is non-empty
// `len` calculation may overflow but push_str but will check boundaries
let len = sep.len() * (self.len() - 1)
+ self.iter().map(|s| s.as_ref().len()).sum();
+ self.iter().map(|s| s.as_ref().len()).sum::<usize>();
let mut result = String::with_capacity(len);
let mut first = true;

Expand Down
1 change: 0 additions & 1 deletion src/libcollectionstest/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
// except according to those terms.

use std::cmp::Ordering::{Equal, Greater, Less};
use std::iter::AdditiveIterator;
use std::str::{Utf8Error, from_utf8};

#[test]
Expand Down
145 changes: 48 additions & 97 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ use default::Default;
use marker;
use mem;
use num::{Int, Zero, One};
use ops::{self, Add, Sub, FnMut, RangeFrom};
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
use option::Option::{self, Some, None};
use marker::Sized;
use usize;
Expand Down Expand Up @@ -489,15 +489,14 @@ pub trait Iterator {
///
/// ```
/// # #![feature(core)]
/// use std::iter::AdditiveIterator;
///
/// let a = [1, 4, 2, 3, 8, 9, 6];
/// let sum = a.iter()
/// .map(|x| *x)
/// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| println!("{} made it through", x))
/// .sum();
/// let sum: i32 = a.iter()
/// .map(|x| *x)
/// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| println!("{} made it through", x))
/// .sum();
/// println!("{}", sum);
/// ```
#[inline]
Expand Down Expand Up @@ -1022,6 +1021,47 @@ pub trait Iterator {
}
}
}

/// Iterates over the entire iterator, summing up all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
///
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().cloned();
/// assert!(it.sum::<i32>() == 15);
/// ```
#[unstable(feature="core")]
fn sum<S=<Self as Iterator>::Item>(self) -> S where
S: Add<Self::Item, Output=S> + Zero,
Self: Sized,
{
self.fold(Zero::zero(), |s, e| s + e)
}

/// Iterates over the entire iterator, multiplying all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
///
/// fn factorial(n: u32) -> u32 {
/// (1..).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
/// assert!(factorial(5) == 120);
/// ```
#[unstable(feature="core")]
fn product<P=<Self as Iterator>::Item>(self) -> P where
P: Mul<Self::Item, Output=P> + One,
Self: Sized,
{
self.fold(One::one(), |p, e| p * e)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -1222,95 +1262,6 @@ impl<I> RandomAccessIterator for Rev<I>
}
}

/// A trait for iterators over elements which can be added together
#[unstable(feature = "core",
reason = "needs to be re-evaluated as part of numerics reform")]
pub trait AdditiveIterator<A> {
/// Iterates over the entire iterator, summing up all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::AdditiveIterator;
///
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().cloned();
/// assert!(it.sum() == 15);
/// ```
fn sum(self) -> A;
}

macro_rules! impl_additive {
($A:ty, $init:expr) => {
#[unstable(feature = "core", reason = "trait is experimental")]
impl<T: Iterator<Item=$A>> AdditiveIterator<$A> for T {
#[inline]
fn sum(self) -> $A {
self.fold($init, |acc, x| acc + x)
}
}
};
}
impl_additive! { i8, 0 }
impl_additive! { i16, 0 }
impl_additive! { i32, 0 }
impl_additive! { i64, 0 }
impl_additive! { isize, 0 }
impl_additive! { u8, 0 }
impl_additive! { u16, 0 }
impl_additive! { u32, 0 }
impl_additive! { u64, 0 }
impl_additive! { usize, 0 }
impl_additive! { f32, 0.0 }
impl_additive! { f64, 0.0 }

/// A trait for iterators over elements which can be multiplied together.
#[unstable(feature = "core",
reason = "needs to be re-evaluated as part of numerics reform")]
pub trait MultiplicativeIterator<A> {
/// Iterates over the entire iterator, multiplying all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::MultiplicativeIterator;
///
/// fn factorial(n: usize) -> usize {
/// (1..).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
/// assert!(factorial(5) == 120);
/// ```
fn product(self) -> A;
}

macro_rules! impl_multiplicative {
($A:ty, $init:expr) => {
#[unstable(feature = "core", reason = "trait is experimental")]
impl<T: Iterator<Item=$A>> MultiplicativeIterator<$A> for T {
#[inline]
fn product(self) -> $A {
self.fold($init, |acc, x| acc * x)
}
}
};
}
impl_multiplicative! { i8, 1 }
impl_multiplicative! { i16, 1 }
impl_multiplicative! { i32, 1 }
impl_multiplicative! { i64, 1 }
impl_multiplicative! { isize, 1 }
impl_multiplicative! { u8, 1 }
impl_multiplicative! { u16, 1 }
impl_multiplicative! { u32, 1 }
impl_multiplicative! { u64, 1 }
impl_multiplicative! { usize, 1 }
impl_multiplicative! { f32, 1.0 }
impl_multiplicative! { f64, 1.0 }

/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
/// more detail.
#[derive(Clone, PartialEq, Debug)]
Expand Down
14 changes: 14 additions & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ macro_rules! zero_one_impl {
}
zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }

macro_rules! zero_one_impl_float {
($($t:ty)*) => ($(
impl Zero for $t {
#[inline]
fn zero() -> $t { 0.0 }
}
impl One for $t {
#[inline]
fn one() -> $t { 1.0 }
}
)*)
}
zero_one_impl_float! { f32 f64 }

/// A built-in signed or unsigned integer.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0",
Expand Down
12 changes: 6 additions & 6 deletions src/libcoretest/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,17 +329,17 @@ fn test_iterator_len() {
#[test]
fn test_iterator_sum() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(v[..4].iter().cloned().sum(), 6);
assert_eq!(v.iter().cloned().sum(), 55);
assert_eq!(v[..0].iter().cloned().sum(), 0);
assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
assert_eq!(v.iter().cloned().sum::<i32>(), 55);
assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
}

#[test]
fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(v[..4].iter().cloned().product(), 0);
assert_eq!(v[1..5].iter().cloned().product(), 24);
assert_eq!(v[..0].iter().cloned().product(), 1);
assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use middle::ty::*;
use middle::ty;
use std::cmp::Ordering;
use std::fmt;
use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat};
use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
use std::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
use syntax::ast_util;
Expand Down Expand Up @@ -76,7 +76,7 @@ impl<'a> fmt::Debug for Matrix<'a> {
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
}).collect();

let total_width = column_widths.iter().cloned().sum() + column_count * 3 + 1;
let total_width = column_widths.iter().cloned().sum::<usize>() + column_count * 3 + 1;
let br = repeat('+').take(total_width).collect::<String>();
try!(write!(f, "{}\n", br));
for row in pretty_printed_matrix {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ use util::ppaux::{Repr, vec_map_to_string};

use std;
use std::cmp::Ordering;
use std::iter::AdditiveIterator;
use std::rc::Rc;
use syntax::ast;
use syntax::ast::{DUMMY_NODE_ID, NodeId};
Expand Down
15 changes: 8 additions & 7 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::ppaux::{self, Repr, UserString};

use std::iter::{repeat, AdditiveIterator};
use std::iter::repeat;
use std::rc::Rc;
use std::slice;
use syntax::{abi, ast, ast_util};
Expand Down Expand Up @@ -517,12 +517,13 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
lifetimes_for_params.push((input_pat, accumulator.len()));
}

let implied_output_region = if lifetimes_for_params.iter().map(|&(_, n)| n).sum() == 1 {
assert!(possible_implied_output_region.is_some());
possible_implied_output_region
} else {
None
};
let implied_output_region =
if lifetimes_for_params.iter().map(|&(_, n)| n).sum::<usize>() == 1 {
assert!(possible_implied_output_region.is_some());
possible_implied_output_region
} else {
None
};
(implied_output_region, lifetimes_for_params)
}

Expand Down
5 changes: 2 additions & 3 deletions src/libstd/old_path/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use fmt;
use hash;
use old_io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, Map};
use iter::{Extend, Iterator, Map};
use marker::Sized;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
Expand Down Expand Up @@ -351,7 +350,7 @@ impl Path {
Some(vec![SEP_BYTE])
} else {
let n = if is_abs { comps.len() } else { comps.len() - 1} +
comps.iter().map(|v| v.len()).sum();
comps.iter().map(|v| v.len()).sum::<usize>();
let mut v = Vec::with_capacity(n);
let mut it = comps.into_iter();
if !is_abs {
Expand Down
5 changes: 2 additions & 3 deletions src/libstd/old_path/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use fmt;
use hash;
use old_io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, Map, repeat};
use iter::{Extend, Iterator, Map, repeat};
use mem;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
Expand Down Expand Up @@ -785,7 +784,7 @@ impl Path {
let prefix_ = &s[..prefix_len(prefix)];
let n = prefix_.len() +
if is_abs { comps.len() } else { comps.len() - 1} +
comps.iter().map(|v| v.len()).sum();
comps.iter().map(|v| v.len()).sum::<usize>();
let mut s = String::with_capacity(n);
match prefix {
Some(DiskPrefix) => {
Expand Down
2 changes: 1 addition & 1 deletion src/libunicode/u_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use core::prelude::*;

use core::char;
use core::cmp;
use core::iter::{Filter, AdditiveIterator};
use core::iter::Filter;
use core::mem;
use core::slice;
use core::str::Split;
Expand Down
3 changes: 1 addition & 2 deletions src/rustbook/book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use std::io::prelude::*;
use std::io::BufReader;
use std::iter;
use std::iter::AdditiveIterator;
use std::path::{Path, PathBuf};

pub struct BookItem {
Expand Down Expand Up @@ -151,7 +150,7 @@ pub fn parse_summary(input: &mut Read, src: &Path) -> Result<Book, Vec<String>>
'\t' => 4,
_ => unreachable!()
}
}).sum() / 4 + 1;
}).sum::<usize>() / 4 + 1;

if level > stack.len() + 1 {
errors.push(format!("section '{}' is indented too deeply; \
Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/shootout-spectralnorm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#![allow(non_snake_case)]
#![feature(unboxed_closures, core, os)]

use std::iter::{repeat, AdditiveIterator};
use std::iter::repeat;
use std::thread;
use std::mem;
use std::num::Float;
Expand Down
3 changes: 1 addition & 2 deletions src/test/run-pass/issue-15673.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

#![feature(core)]

use std::iter::AdditiveIterator;
fn main() {
let x: [u64; 3] = [1, 2, 3];
assert_eq!(6, (0..3).map(|i| x[i]).sum());
assert_eq!(6, (0..3).map(|i| x[i]).sum::<u64>());
}
Loading

0 comments on commit dd6c4a8

Please sign in to comment.