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