usesuper::*; usecrate::prelude::*; use rayon_core::*;
use rand::distributions::Standard; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BinaryHeap, VecDeque}; use std::f64; use std::ffi::OsStr; use std::fmt::Debug; use std::sync::mpsc; use std::usize;
#[test] fn execute_range() { let a = 0i32..1024; letmut b = vec![];
a.into_par_iter().map(|i| i + 1).collect_into_vec(&mut b); let c: Vec<i32> = (0..1024).map(|i| i + 1).collect();
assert_eq!(b, c);
}
#[test] fn execute_unindexed_range() { let a = 0i64..1024; let b: LinkedList<i64> = a.into_par_iter().map(|i| i + 1).collect(); let c: LinkedList<i64> = (0..1024).map(|i| i + 1).collect();
assert_eq!(b, c);
}
#[test] fn execute_pseudo_indexed_range() { let range = i128::MAX - 1024..i128::MAX;
// Given `Some` length, collecting `Vec` will try to act indexed. let a = range.clone().into_par_iter();
assert_eq!(a.opt_len(), Some(1024));
let b: Vec<i128> = a.map(|i| i + 1).collect(); let c: Vec<i128> = range.map(|i| i + 1).collect();
assert_eq!(b, c);
}
#[test] fn check_map_indexed() { let a = [1, 2, 3];
is_indexed(a.par_iter().map(|x| x));
}
#[test] fn map_sum() { let a: Vec<i32> = (0..1024).collect(); let r1: i32 = a.par_iter().map(|&i| i + 1).sum(); let r2 = a.iter().map(|&i| i + 1).sum();
assert_eq!(r1, r2);
}
#[test] fn map_reduce() { let a: Vec<i32> = (0..1024).collect(); let r1 = a.par_iter().map(|&i| i + 1).reduce(|| 0, |i, j| i + j); let r2 = a.iter().map(|&i| i + 1).sum();
assert_eq!(r1, r2);
}
#[test] fn map_reduce_with() { let a: Vec<i32> = (0..1024).collect(); let r1 = a.par_iter().map(|&i| i + 1).reduce_with(|i, j| i + j); let r2 = a.iter().map(|&i| i + 1).sum();
assert_eq!(r1, Some(r2));
}
#[test] fn fold_map_reduce() { // Kind of a weird test, but it demonstrates various // transformations that are taking place. Relies on // `with_max_len(1).fold()` being equivalent to `map()`. // // Take each number from 0 to 32 and fold them by appending to a // vector. Because of `with_max_len(1)`, this will produce 32 vectors, // each with one item. We then collect all of these into an // individual vector by mapping each into their own vector (so we // have Vec<Vec<i32>>) and then reducing those into a single // vector. let r1 = (0_i32..32)
.into_par_iter()
.with_max_len(1)
.fold(Vec::new, |mut v, e| {
v.push(e);
v
})
.map(|v| vec![v])
.reduce_with(|mut v_a, v_b| {
v_a.extend(v_b);
v_a
});
assert_eq!(
r1,
Some(vec![
vec![0],
vec![1],
vec![2],
vec![3],
vec![4],
vec![5],
vec![6],
vec![7],
vec![8],
vec![9],
vec![10],
vec![11],
vec![12],
vec![13],
vec![14],
vec![15],
vec![16],
vec![17],
vec![18],
vec![19],
vec![20],
vec![21],
vec![22],
vec![23],
vec![24],
vec![25],
vec![26],
vec![27],
vec![28],
vec![29],
vec![30],
vec![31]
])
);
}
#[test] fn fold_is_full() { let counter = AtomicUsize::new(0); let a = (0_i32..2048)
.into_par_iter()
.inspect(|_| {
counter.fetch_add(1, Ordering::SeqCst);
})
.fold(|| 0, |a, b| a + b)
.find_any(|_| true);
assert!(a.is_some());
assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one
}
#[test] fn check_step_by() { let a: Vec<i32> = (0..1024).step_by(2).collect(); let b: Vec<i32> = (0..1024).into_par_iter().step_by(2).collect();
assert_eq!(a, b);
}
#[test] fn check_step_by_unaligned() { let a: Vec<i32> = (0..1029).step_by(10).collect(); let b: Vec<i32> = (0..1029).into_par_iter().step_by(10).collect();
assert_eq!(a, b)
}
#[test] fn check_step_by_rev() { let a: Vec<i32> = (0..1024).step_by(2).rev().collect(); let b: Vec<i32> = (0..1024).into_par_iter().step_by(2).rev().collect();
assert_eq!(a, b);
}
#[test] fn check_enumerate() { let a: Vec<usize> = (0..1024).rev().collect();
letmut b = vec![];
a.par_iter()
.enumerate()
.map(|(i, &x)| i + x)
.collect_into_vec(&mut b);
assert!(b.iter().all(|&x| x == a.len() - 1));
}
#[test] fn check_enumerate_rev() { let a: Vec<usize> = (0..1024).rev().collect();
letmut b = vec![];
a.par_iter()
.enumerate()
.rev()
.map(|(i, &x)| i + x)
.collect_into_vec(&mut b);
assert!(b.iter().all(|&x| x == a.len() - 1));
}
#[test] fn check_indices_after_enumerate_split() { let a: Vec<i32> = (0..1024).collect();
a.par_iter().enumerate().with_producer(WithProducer);
struct WithProducer; impl<'a> ProducerCallback<(usize, &'a i32)> for WithProducer { type Output = (); fn callback<P>(self, producer: P) where
P: Producer<Item = (usize, &'a i32)>,
{ let (a, b) = producer.split_at(512); for ((index, value), trusted_index) in a.into_iter().zip(0..) {
assert_eq!(index, trusted_index);
assert_eq!(index, *value as usize);
} for ((index, value), trusted_index) in b.into_iter().zip(512..) {
assert_eq!(index, trusted_index);
assert_eq!(index, *value as usize);
}
}
}
}
// Check that the skipped elements side effects are executed use std::sync::atomic::{AtomicUsize, Ordering}; let num = AtomicUsize::new(0);
a.par_iter()
.map(|&n| num.fetch_add(n, Ordering::Relaxed))
.skip(512)
.count();
assert_eq!(num.load(Ordering::Relaxed), a.iter().sum::<usize>());
}
#[test] fn check_take() { let a: Vec<usize> = (0..1024).collect();
#[test] fn check_cmp_rng_to_seq() { letmut rng = seeded_rng(); let rng = &mut rng; let a: Vec<i32> = rng.sample_iter(&Standard).take(1024).collect(); let b: Vec<i32> = rng.sample_iter(&Standard).take(1024).collect(); for i in0..a.len() { let par_result = a[i..].par_iter().cmp(b[i..].par_iter()); let seq_result = a[i..].iter().cmp(b[i..].iter());
assert_eq!(par_result, seq_result);
}
}
#[test] fn check_cmp_lt_direct() { let a = (0..1024).into_par_iter(); let b = (1..1024).into_par_iter();
#[test] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn check_cmp_short_circuit() { // We only use a single thread in order to make the short-circuit behavior deterministic. let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
let a = vec![0; 1024]; letmut b = a.clone();
b[42] = 1;
pool.install(|| { let expected = ::std::cmp::Ordering::Less;
assert_eq!(a.par_iter().cmp(&b), expected);
for len in1..10 { let counter = AtomicUsize::new(0); let result = a
.par_iter()
.with_max_len(len)
.inspect(|_| {
counter.fetch_add(1, Ordering::SeqCst);
})
.cmp(&b);
assert_eq!(result, expected); // should not have visited every single one
assert!(counter.into_inner() < a.len());
}
});
}
#[test] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn check_partial_cmp_short_circuit() { // We only use a single thread to make the short-circuit behavior deterministic. let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
let a = vec![0; 1024]; letmut b = a.clone();
b[42] = 1;
pool.install(|| { let expected = Some(::std::cmp::Ordering::Less);
assert_eq!(a.par_iter().partial_cmp(&b), expected);
for len in1..10 { let counter = AtomicUsize::new(0); let result = a
.par_iter()
.with_max_len(len)
.inspect(|_| {
counter.fetch_add(1, Ordering::SeqCst);
})
.partial_cmp(&b);
assert_eq!(result, expected); // should not have visited every single one
assert!(counter.into_inner() < a.len());
}
});
}
#[test] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn check_partial_cmp_nan_short_circuit() { // We only use a single thread to make the short-circuit behavior deterministic. let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
let a = vec![0.0; 1024]; letmut b = a.clone();
b[42] = f64::NAN;
pool.install(|| { let expected = None;
assert_eq!(a.par_iter().partial_cmp(&b), expected);
for len in1..10 { let counter = AtomicUsize::new(0); let result = a
.par_iter()
.with_max_len(len)
.inspect(|_| {
counter.fetch_add(1, Ordering::SeqCst);
})
.partial_cmp(&b);
assert_eq!(result, expected); // should not have visited every single one
assert!(counter.into_inner() < a.len());
}
});
}
#[test] fn check_partial_cmp_direct() { let a = (0..1024).into_par_iter(); let b = (0..1024).into_par_iter();
#[test] fn check_partial_cmp_to_seq() { let par_result = (0..1024).into_par_iter().partial_cmp(0..1024); let seq_result = (0..1024).partial_cmp(0..1024);
assert_eq!(par_result, seq_result);
}
#[test] fn check_partial_cmp_rng_to_seq() { letmut rng = seeded_rng(); let rng = &mut rng; let a: Vec<i32> = rng.sample_iter(&Standard).take(1024).collect(); let b: Vec<i32> = rng.sample_iter(&Standard).take(1024).collect(); for i in0..a.len() { let par_result = a[i..].par_iter().partial_cmp(b[i..].par_iter()); let seq_result = a[i..].iter().partial_cmp(b[i..].iter());
assert_eq!(par_result, seq_result);
}
}
#[test] fn check_partial_cmp_lt_direct() { let a = (0..1024).into_par_iter(); let b = (1..1024).into_par_iter();
#[test] fn check_sum_filtermap_ints() { let a: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let par_sum_evens: u32 = a
.par_iter()
.filter_map(|&x| if (x & 1) == 0 { Some(x as u32) } else { None })
.sum(); let seq_sum_evens = a
.iter()
.filter_map(|&x| if (x & 1) == 0 { Some(x as u32) } else { None })
.sum();
assert_eq!(par_sum_evens, seq_sum_evens);
}
#[test] fn check_flat_map_nested_ranges() { // FIXME -- why are precise type hints required on the integers here?
let v: i32 = (0_i32..10)
.into_par_iter()
.flat_map(|i| (0_i32..10).into_par_iter().map(move |j| (i, j)))
.map(|(i, j)| i * j)
.sum();
let w = (0_i32..10)
.flat_map(|i| (0_i32..10).map(move |j| (i, j)))
.map(|(i, j)| i * j)
.sum();
assert_eq!(v, w);
}
#[test] fn check_empty_flat_map_sum() { let a: Vec<i32> = (0..1024).collect(); let empty = &a[..0];
// empty on the inside let b: i32 = a.par_iter().flat_map(|_| empty).sum();
assert_eq!(b, 0);
// empty on the outside let c: i32 = empty.par_iter().flat_map(|_| a.par_iter()).sum();
assert_eq!(c, 0);
}
#[test] fn check_flatten_vec() { let a: Vec<i32> = (0..1024).collect(); let b: Vec<Vec<i32>> = vec![a.clone(), a.clone(), a.clone(), a.clone()]; let c: Vec<i32> = b.par_iter().flatten().cloned().collect(); letmut d = a.clone();
d.extend(&a);
d.extend(&a);
d.extend(&a);
assert_eq!(d, c);
}
#[test] fn check_flatten_vec_empty() { let a: Vec<Vec<i32>> = vec![vec![]]; let b: Vec<i32> = a.par_iter().flatten().cloned().collect();
assert_eq!(vec![] as Vec<i32>, b);
}
#[test] fn check_slice_split() { let v: Vec<_> = (0..1000).collect(); for m in1..100 { let a: Vec<_> = v.split(|x| x % m == 0).collect(); let b: Vec<_> = v.par_split(|x| x % m == 0).collect();
assert_eq!(a, b);
}
// same as std::slice::split() examples let slice = [10, 40, 33, 20]; let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();
assert_eq!(v, &[&slice[..2], &slice[3..]]);
let slice = [10, 40, 33]; let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();
assert_eq!(v, &[&slice[..2], &slice[..0]]);
let slice = [10, 6, 33, 20]; let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();
assert_eq!(v, &[&slice[..1], &slice[..0], &slice[3..]]);
}
#[test] fn check_slice_split_inclusive() { let v: Vec<_> = (0..1000).collect(); for m in1..100 { let a: Vec<_> = v.split_inclusive(|x| x % m == 0).collect(); let b: Vec<_> = v.par_split_inclusive(|x| x % m == 0).collect();
assert_eq!(a, b);
}
// same as std::slice::split_inclusive() examples let slice = [10, 40, 33, 20]; let v: Vec<_> = slice.par_split_inclusive(|num| num % 3 == 0).collect();
assert_eq!(v, &[&slice[..3], &slice[3..]]);
let slice = [3, 10, 40, 33]; let v: Vec<_> = slice.par_split_inclusive(|num| num % 3 == 0).collect();
assert_eq!(v, &[&slice[..1], &slice[1..]]);
}
#[test] fn check_slice_split_mut() { letmut v1: Vec<_> = (0..1000).collect(); letmut v2 = v1.clone(); for m in1..100 { let a: Vec<_> = v1.split_mut(|x| x % m == 0).collect(); let b: Vec<_> = v2.par_split_mut(|x| x % m == 0).collect();
assert_eq!(a, b);
}
// same as std::slice::split_mut() example letmut v = [10, 40, 30, 20, 60, 50];
v.par_split_mut(|num| num % 3 == 0).for_each(|group| {
group[0] = 1;
});
assert_eq!(v, [1, 40, 30, 1, 60, 1]);
}
#[test] fn check_slice_split_inclusive_mut() { letmut v1: Vec<_> = (0..1000).collect(); letmut v2 = v1.clone(); for m in1..100 { let a: Vec<_> = v1.split_inclusive_mut(|x| x % m == 0).collect(); let b: Vec<_> = v2.par_split_inclusive_mut(|x| x % m == 0).collect();
assert_eq!(a, b);
}
// same as std::slice::split_inclusive_mut() example letmut v = [10, 40, 30, 20, 60, 50];
v.par_split_inclusive_mut(|num| num % 3 == 0)
.for_each(|group| { let terminator_idx = group.len() - 1;
group[terminator_idx] = 1;
});
assert_eq!(v, [10, 40, 1, 20, 1, 1]);
}
#[test] fn check_find_not_present() { let counter = AtomicUsize::new(0); let value: Option<i32> = (0_i32..2048).into_par_iter().find_any(|&p| {
counter.fetch_add(1, Ordering::SeqCst);
p >= 2048
});
assert!(value.is_none());
assert!(counter.load(Ordering::SeqCst) == 2048); // should have visited every single one
}
#[test] fn check_find_is_present() { let counter = AtomicUsize::new(0); let value: Option<i32> = (0_i32..2048).into_par_iter().find_any(|&p| {
counter.fetch_add(1, Ordering::SeqCst);
(1024..1096).contains(&p)
}); let q = value.unwrap();
assert!((1024..1096).contains(&q));
assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one
}
#[test] fn check_while_some() { let value = (0_i32..2048).into_par_iter().map(Some).while_some().max();
assert_eq!(value, Some(2047));
let counter = AtomicUsize::new(0); let value = (0_i32..2048)
.into_par_iter()
.map(|x| {
counter.fetch_add(1, Ordering::SeqCst); if x < 1024 {
Some(x)
} else {
None
}
})
.while_some()
.max();
assert!(value < Some(1024));
assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one
}
#[test] fn par_iter_collect_option() { let a: Option<Vec<_>> = (0_i32..2048).map(Some).collect(); let b: Option<Vec<_>> = (0_i32..2048).into_par_iter().map(Some).collect();
assert_eq!(a, b);
let c: Option<Vec<_>> = (0_i32..2048)
.into_par_iter()
.map(|x| if x == 1234 { None } else { Some(x) })
.collect();
assert_eq!(c, None);
}
#[test] fn par_iter_collect_result() { let a: Result<Vec<_>, ()> = (0_i32..2048).map(Ok).collect(); let b: Result<Vec<_>, ()> = (0_i32..2048).into_par_iter().map(Ok).collect();
assert_eq!(a, b);
let c: Result<Vec<_>, _> = (0_i32..2048)
.into_par_iter()
.map(|x| if x == 1234 { Err(x) } else { Ok(x) })
.collect();
assert_eq!(c, Err(1234));
let d: Result<Vec<_>, _> = (0_i32..2048)
.into_par_iter()
.map(|x| if x % 100 == 99 { Err(x) } else { Ok(x) })
.collect();
assert_eq!(d.map_err(|x| x % 100), Err(99));
}
#[test] fn par_iter_collect() { let a: Vec<i32> = (0..1024).collect(); let b: Vec<i32> = a.par_iter().map(|&i| i + 1).collect(); let c: Vec<i32> = (0..1024).map(|i| i + 1).collect();
assert_eq!(b, c);
}
#[test] fn par_iter_collect_vecdeque() { let a: Vec<i32> = (0..1024).collect(); let b: VecDeque<i32> = a.par_iter().cloned().collect(); let c: VecDeque<i32> = a.iter().cloned().collect();
assert_eq!(b, c);
}
#[test] fn par_iter_collect_binaryheap() { let a: Vec<i32> = (0..1024).collect(); letmut b: BinaryHeap<i32> = a.par_iter().cloned().collect();
assert_eq!(b.peek(), Some(&1023));
assert_eq!(b.len(), 1024); for n in (0..1024).rev() {
assert_eq!(b.pop(), Some(n));
assert_eq!(b.len() as i32, n);
}
}
#[test] fn par_iter_collect_btreeset() { let a: Vec<i32> = (0..1024).collect(); let b: BTreeSet<i32> = a.par_iter().cloned().collect();
assert_eq!(b.len(), 1024);
}
#[test] fn par_iter_collect_linked_list() { let a: Vec<i32> = (0..1024).collect(); let b: LinkedList<_> = a.par_iter().map(|&i| (i, format!("{}", i))).collect(); let c: LinkedList<_> = a.iter().map(|&i| (i, format!("{}", i))).collect();
assert_eq!(b, c);
}
#[test] fn par_iter_collect_linked_list_flat_map_filter() { let b: LinkedList<i32> = (0_i32..1024)
.into_par_iter()
.flat_map(|i| (0..i))
.filter(|&i| i % 2 == 0)
.collect(); let c: LinkedList<i32> = (0_i32..1024)
.flat_map(|i| (0..i))
.filter(|&i| i % 2 == 0)
.collect();
assert_eq!(b, c);
}
#[test] fn par_iter_collect_cows() { use std::borrow::Cow;
let s = "Fearless Concurrency with Rust";
// Collects `i32` into a `Vec` let a: Cow<'_, [i32]> = (0..1024).collect(); let b: Cow<'_, [i32]> = a.par_iter().cloned().collect();
assert_eq!(a, b);
// Collects `char` into a `String` let a: Cow<'_, str> = s.chars().collect(); let b: Cow<'_, str> = s.par_chars().collect();
assert_eq!(a, b);
// Collects `str` into a `String` let sw = s.split_whitespace(); let psw = s.par_split_whitespace(); let a: Cow<'_, str> = sw.clone().collect(); let b: Cow<'_, str> = psw.clone().collect();
assert_eq!(a, b);
// Collects `String` into a `String` let a: Cow<'_, str> = sw.map(str::to_owned).collect(); let b: Cow<'_, str> = psw.map(str::to_owned).collect();
assert_eq!(a, b);
// Collects `OsStr` into a `OsString` let sw = s.split_whitespace().map(OsStr::new); let psw = s.par_split_whitespace().map(OsStr::new); let a: Cow<'_, OsStr> = Cow::Owned(sw.clone().collect()); let b: Cow<'_, OsStr> = psw.clone().collect();
assert_eq!(a, b);
// Collects `OsString` into a `OsString` let a: Cow<'_, OsStr> = Cow::Owned(sw.map(OsStr::to_owned).collect()); let b: Cow<'_, OsStr> = psw.map(OsStr::to_owned).collect();
assert_eq!(a, b);
}
#[test] fn par_iter_unindexed_flat_map() { let b: Vec<i64> = (0_i64..1024).into_par_iter().flat_map(Some).collect(); let c: Vec<i64> = (0_i64..1024).flat_map(Some).collect();
assert_eq!(b, c);
}
#[test] fn min_max() { let rng = seeded_rng(); let a: Vec<i32> = rng.sample_iter(&Standard).take(1024).collect(); for i in0..=a.len() { let slice = &a[..i];
assert_eq!(slice.par_iter().min(), slice.iter().min());
assert_eq!(slice.par_iter().max(), slice.iter().max());
}
}
#[test] fn min_max_by() { let rng = seeded_rng(); // Make sure there are duplicate keys, for testing sort stability let r: Vec<i32> = rng.sample_iter(&Standard).take(512).collect(); let a: Vec<(i32, u16)> = r.iter().chain(&r).cloned().zip(0..).collect(); for i in0..=a.len() { let slice = &a[..i];
assert_eq!(
slice.par_iter().min_by(|x, y| x.0.cmp(&y.0)),
slice.iter().min_by(|x, y| x.0.cmp(&y.0))
);
assert_eq!(
slice.par_iter().max_by(|x, y| x.0.cmp(&y.0)),
slice.iter().max_by(|x, y| x.0.cmp(&y.0))
);
}
}
#[test] fn min_max_by_key() { let rng = seeded_rng(); // Make sure there are duplicate keys, for testing sort stability let r: Vec<i32> = rng.sample_iter(&Standard).take(512).collect(); let a: Vec<(i32, u16)> = r.iter().chain(&r).cloned().zip(0..).collect(); for i in0..=a.len() { let slice = &a[..i];
assert_eq!(
slice.par_iter().min_by_key(|x| x.0),
slice.iter().min_by_key(|x| x.0)
);
assert_eq!(
slice.par_iter().max_by_key(|x| x.0),
slice.iter().max_by_key(|x| x.0)
);
}
}
#[test] fn check_rev() { let a: Vec<usize> = (0..1024).rev().collect(); let b: Vec<usize> = (0..1024).collect();
assert!(a.par_iter().rev().zip(b).all(|(&a, b)| a == b));
}
#[test] fn scope_mix() { let counter_p = &AtomicUsize::new(0);
scope(|s| {
s.spawn(move |s| {
divide_and_conquer(s, counter_p, 1024);
});
s.spawn(move |_| { let a: Vec<i32> = (0..1024).collect(); let r1 = a.par_iter().map(|&i| i + 1).reduce_with(|i, j| i + j); let r2 = a.iter().map(|&i| i + 1).sum();
assert_eq!(r1.unwrap(), r2);
});
});
}
#[test] fn check_unzip_into_vecs() { letmut a = vec![]; letmut b = vec![];
(0..1024)
.into_par_iter()
.map(|i| i * i)
.enumerate()
.unzip_into_vecs(&mut a, &mut b);
let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();
assert_eq!(a, c);
assert_eq!(b, d);
}
#[test] fn check_unzip() { // indexed, unindexed let (a, b): (Vec<_>, HashSet<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip(); let (c, d): (Vec<_>, HashSet<_>) = (0..1024).map(|i| i * i).enumerate().unzip();
assert_eq!(a, c);
assert_eq!(b, d);
// unindexed, indexed let (a, b): (HashSet<_>, Vec<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip(); let (c, d): (HashSet<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();
assert_eq!(a, c);
assert_eq!(b, d);
// indexed, indexed let (a, b): (Vec<_>, Vec<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip(); let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();
assert_eq!(a, c);
assert_eq!(b, d);
// unindexed producer let (a, b): (Vec<_>, Vec<_>) = (0..1024)
.into_par_iter()
.filter_map(|i| Some((i, i * i)))
.unzip(); let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| (i, i * i)).unzip();
assert_eq!(a, c);
assert_eq!(b, d);
}
#[test] fn check_partition() { let (a, b): (Vec<_>, Vec<_>) = (0..1024).into_par_iter().partition(|&i| i % 3 == 0); let (c, d): (Vec<_>, Vec<_>) = (0..1024).partition(|&i| i % 3 == 0);
assert_eq!(a, c);
assert_eq!(b, d);
}
#[test] fn check_partition_map() { let input = "a b c 1 2 3 x y z"; let (a, b): (Vec<_>, String) =
input
.par_split_whitespace()
.partition_map(|s| match s.parse::<i32>() {
Ok(n) => Either::Left(n),
Err(_) => Either::Right(s),
});
assert_eq!(a, vec![1, 2, 3]);
assert_eq!(b, "abcxyz");
}
#[test] fn check_either() { type I = crate::vec::IntoIter<i32>; type E = Either<I, I>;
let v: Vec<i32> = (0..1024).collect();
// try iterating the left side let left: E = Either::Left(v.clone().into_par_iter());
assert!(left.eq(v.clone()));
// try iterating the right side let right: E = Either::Right(v.clone().into_par_iter());
assert!(right.eq(v.clone()));
// try an indexed iterator let left: E = Either::Left(v.clone().into_par_iter());
assert!(left.enumerate().eq(v.into_par_iter().enumerate()));
}
#[test] fn check_either_extend() { type E = Either<Vec<i32>, HashSet<i32>>;
let v: Vec<i32> = (0..1024).collect();
// try extending the left side letmut left: E = Either::Left(vec![]);
left.par_extend(v.clone());
assert_eq!(left.as_ref(), Either::Left(&v));
// try extending the right side letmut right: E = Either::Right(HashSet::default());
right.par_extend(v.clone());
assert_eq!(right, Either::Right(v.iter().cloned().collect()));
}
#[test] fn check_interleave_eq() { let xs: Vec<usize> = (0..10).collect(); let ys: Vec<usize> = (10..20).collect();
letmut actual = vec![];
xs.par_iter()
.interleave(&ys)
.map(|&i| i)
.collect_into_vec(&mut actual);
#[test] #[should_panic(expected = "chunk_size must not be zero")] fn check_chunks_zero_size() { let _: Vec<Vec<i32>> = vec![1, 2, 3].into_par_iter().chunks(0).collect();
}
#[test] #[ignore] // it's quick enough on optimized 32-bit platforms, but otherwise... ... ... #[should_panic(expected = "overflow")] #[cfg(debug_assertions)] fn check_repeat_unbounded() { // use just one thread, so we don't get infinite adaptive splitting // (forever stealing and re-splitting jobs that will panic on overflow) let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
pool.install(|| {
println!("counted {} repeats", repeat(()).count());
});
}
#[test] fn check_repeat_find_any() { let even = repeat(4).find_any(|&x| x % 2 == 0);
assert_eq!(even, Some(4));
}
#[test] fn walk_tree_prefix() { let v: Vec<u32> = crate::iter::walk_tree_prefix(0u32..100, |r| { // root is smallest let mid = (r.start + 1 + r.end) / 2; // small indices to the left, large to the right
std::iter::once((r.start + 1)..mid)
.chain(std::iter::once(mid..r.end))
.filter(|r| !r.is_empty())
})
.map(|r| r.start)
.collect();
assert!(v.into_iter().eq(0..100));
}
#[test] fn walk_tree_postfix() { let v: Vec<_> = crate::iter::walk_tree_postfix(0u64..100, |r| { // root is largest let mid = (r.start + r.end - 1) / 2; // small indices to the left, large to the right
std::iter::once(r.start..mid)
.chain(std::iter::once(mid..(r.end - 1)))
.filter(|r| !r.is_empty())
})
.map(|r| r.end - 1)
.collect();
assert!(v.into_iter().eq(0..100));
}
#[test] fn walk_flat_tree_prefix() { let v: Vec<_> = crate::iter::walk_tree_prefix(0, |&e| if e < 99 { Some(e + 1) } else { None }).collect();
assert!(v.into_iter().eq(0..100));
}
#[test] fn walk_flat_tree_postfix() { let v: Vec<_> = crate::iter::walk_tree_postfix(99, |&e| if e > 0 { Some(e - 1) } else { None }).collect();
assert!(v.into_iter().eq(0..100));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.