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(
72 any(
73 not(target_pointer_width = "64"),
74 target_os = "emscripten",
75 target_family = "wasm"
76 ),
77 ignore
78 )]
find_last_octillion()79 fn 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 )]
find_last_octillion_inclusive()96 fn 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 )]
find_last_octillion_flat()110 fn 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)]
find_any_octillion()117 fn 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)]
find_any_octillion_flat()124 fn 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)]
filter_find_any_octillion()131 fn 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)]
filter_find_any_octillion_flat()142 fn 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)]
fold_find_any_octillion_flat()153 fn fold_find_any_octillion_flat() {
154 let x = two_threads(|| octillion_flat().fold(|| (), |_, _| ()).find_any(|_| true));
155 assert!(x.is_some());
156 }
157