1use rayon::prelude::*;
2
3const OCTILLION: u128 = 1_000_000_000_000_000_000_000_000_000;
4
5/// Produce a parallel iterator for 0u128..10²⁷
6fn octillion() -> rayon::range::Iter<u128> {
7 (0..OCTILLION).into_par_iter()
8}
9
10/// Produce a parallel iterator for 0u128..=10²⁷
11fn 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`
16fn 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)]
41fn 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)]
48fn 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)]
55fn find_first_octillion_flat() {
56 let x = octillion_flat().find_first(|_| true);
57 assert_eq!(x, Some(0));
58}
59
60fn 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(
72 any(
73 not(target_pointer_width = "64"),
74 target_os = "emscripten",
75 target_family = "wasm"
76 ),
77 ignore
78)]
79fn find_last_octillion() {
80 // It would be nice if `find_last` could prioritize the later splits,
81 // basically flipping the `join` args, without needing indexed `rev`.
82 // (or could we have an unindexed `rev`?)
83 let x = two_threads(|| octillion().find_last(|_| true));
84 assert_eq!(x, Some(OCTILLION - 1));
85}
86
87#[test]
88#[cfg_attr(
89 any(
90 not(target_pointer_width = "64"),
91 target_os = "emscripten",
92 target_family = "wasm"
93 ),
94 ignore
95)]
96fn find_last_octillion_inclusive() {
97 let x = two_threads(|| octillion_inclusive().find_last(|_| true));
98 assert_eq!(x, Some(OCTILLION));
99}
100
101#[test]
102#[cfg_attr(
103 any(
104 not(target_pointer_width = "64"),
105 target_os = "emscripten",
106 target_family = "wasm"
107 ),
108 ignore
109)]
110fn find_last_octillion_flat() {
111 let x = two_threads(|| octillion_flat().find_last(|_| true));
112 assert_eq!(x, Some(OCTILLION - 1));
113}
114
115#[test]
116#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
117fn find_any_octillion() {
118 let x = two_threads(|| octillion().find_any(|x| *x > OCTILLION / 2));
119 assert!(x.is_some());
120}
121
122#[test]
123#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
124fn find_any_octillion_flat() {
125 let x = two_threads(|| octillion_flat().find_any(|x| *x > OCTILLION / 2));
126 assert!(x.is_some());
127}
128
129#[test]
130#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
131fn filter_find_any_octillion() {
132 let x = two_threads(|| {
133 octillion()
134 .filter(|x| *x > OCTILLION / 2)
135 .find_any(|_| true)
136 });
137 assert!(x.is_some());
138}
139
140#[test]
141#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
142fn filter_find_any_octillion_flat() {
143 let x = two_threads(|| {
144 octillion_flat()
145 .filter(|x| *x > OCTILLION / 2)
146 .find_any(|_| true)
147 });
148 assert!(x.is_some());
149}
150
151#[test]
152#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
153fn fold_find_any_octillion_flat() {
154 let x = two_threads(|| octillion_flat().fold(|| (), |_, _| ()).find_any(|_| true));
155 assert!(x.is_some());
156}
157