1 use rayon::prelude::*;
2 
3 const OCTILLION: u128 = 1_000_000_000_000_000_000_000_000_000;
4 
5 /// Produce a parallel iterator for 0u128..10²⁷
octillion() -> rayon::range::Iter<u128>6 fn octillion() -> rayon::range::Iter<u128> {
7     (0..OCTILLION).into_par_iter()
8 }
9 
10 /// Produce a parallel iterator for 0u128..=10²⁷
octillion_inclusive() -> rayon::range_inclusive::Iter<u128>11 fn octillion_inclusive() -> rayon::range_inclusive::Iter<u128> {
12     (0..=OCTILLION).into_par_iter()
13 }
14 
15 /// Produce a parallel iterator for 0u128..10²⁷ using `flat_map`
octillion_flat() -> impl ParallelIterator<Item = u128>16 fn octillion_flat() -> impl ParallelIterator<Item = u128> {
17     (0u32..1_000_000_000)
18         .into_par_iter()
19         .with_max_len(1_000)
20         .map(|i| u64::from(i) * 1_000_000_000)
21         .flat_map(|i| {
22             (0u32..1_000_000_000)
23                 .into_par_iter()
24                 .with_max_len(1_000)
25                 .map(move |j| i + u64::from(j))
26         })
27         .map(|i| u128::from(i) * 1_000_000_000)
28         .flat_map(|i| {
29             (0u32..1_000_000_000)
30                 .into_par_iter()
31                 .with_max_len(1_000)
32                 .map(move |j| i + u128::from(j))
33         })
34 }
35 
36 // NOTE: `find_first` and `find_last` currently take too long on 32-bit targets,
37 // because the `AtomicUsize` match position has much too limited resolution.
38 
39 #[test]
40 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_first_octillion()41 fn find_first_octillion() {
42     let x = octillion().find_first(|_| true);
43     assert_eq!(x, Some(0));
44 }
45 
46 #[test]
47 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_first_octillion_inclusive()48 fn find_first_octillion_inclusive() {
49     let x = octillion_inclusive().find_first(|_| true);
50     assert_eq!(x, Some(0));
51 }
52 
53 #[test]
54 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_first_octillion_flat()55 fn find_first_octillion_flat() {
56     let x = octillion_flat().find_first(|_| true);
57     assert_eq!(x, Some(0));
58 }
59 
two_threads<F: Send + FnOnce() -> R, R: Send>(f: F) -> R60 fn two_threads<F: Send + FnOnce() -> R, R: Send>(f: F) -> R {
61     // FIXME: If we don't use at least two threads, then we end up walking
62     // through the entire iterator sequentially, without the benefit of any
63     // short-circuiting.  We probably don't want testing to wait that long. ;)
64     let builder = rayon::ThreadPoolBuilder::new().num_threads(2);
65     let pool = builder.build().unwrap();
66 
67     pool.install(f)
68 }
69 
70 #[test]
71 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_last_octillion()72 fn find_last_octillion() {
73     // It would be nice if `find_last` could prioritize the later splits,
74     // basically flipping the `join` args, without needing indexed `rev`.
75     // (or could we have an unindexed `rev`?)
76     let x = two_threads(|| octillion().find_last(|_| true));
77     assert_eq!(x, Some(OCTILLION - 1));
78 }
79 
80 #[test]
81 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_last_octillion_inclusive()82 fn find_last_octillion_inclusive() {
83     let x = two_threads(|| octillion_inclusive().find_last(|_| true));
84     assert_eq!(x, Some(OCTILLION));
85 }
86 
87 #[test]
88 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
find_last_octillion_flat()89 fn find_last_octillion_flat() {
90     let x = two_threads(|| octillion_flat().find_last(|_| true));
91     assert_eq!(x, Some(OCTILLION - 1));
92 }
93 
94 #[test]
find_any_octillion()95 fn find_any_octillion() {
96     let x = two_threads(|| octillion().find_any(|x| *x > OCTILLION / 2));
97     assert!(x.is_some());
98 }
99 
100 #[test]
find_any_octillion_flat()101 fn find_any_octillion_flat() {
102     let x = two_threads(|| octillion_flat().find_any(|x| *x > OCTILLION / 2));
103     assert!(x.is_some());
104 }
105 
106 #[test]
filter_find_any_octillion()107 fn filter_find_any_octillion() {
108     let x = two_threads(|| {
109         octillion()
110             .filter(|x| *x > OCTILLION / 2)
111             .find_any(|_| true)
112     });
113     assert!(x.is_some());
114 }
115 
116 #[test]
filter_find_any_octillion_flat()117 fn filter_find_any_octillion_flat() {
118     let x = two_threads(|| {
119         octillion_flat()
120             .filter(|x| *x > OCTILLION / 2)
121             .find_any(|_| true)
122     });
123     assert!(x.is_some());
124 }
125 
126 #[test]
fold_find_any_octillion_flat()127 fn fold_find_any_octillion_flat() {
128     let x = two_threads(|| octillion_flat().fold(|| (), |_, _| ()).find_any(|_| true));
129     assert!(x.is_some());
130 }
131