Skip to content

Commit 93ce88f

Browse files
bors[bot]Paul Kernfeldcuviper
committed
575: u128 and i128 ranges r=cuviper a=paulkernfeld This is an attempt at rayon-rs#573. I don't have experience with functionality that is conditional on the version of rustc, so I apologize if this PR is completely bonkers. I went with a feature flag in this case, but I would be happy to reimplement this using an alternative method. Co-authored-by: Paul Kernfeld <[email protected]> Co-authored-by: Josh Stone <[email protected]>
2 parents 5b99436 + a9e4666 commit 93ce88f

File tree

4 files changed

+61
-9
lines changed

4 files changed

+61
-9
lines changed

build.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::env;
2+
use std::io::Write;
3+
use std::process::{Command, Stdio};
4+
5+
fn main() {
6+
if probe("fn main() { 0i128; }") {
7+
println!("cargo:rustc-cfg=has_i128");
8+
}
9+
}
10+
11+
/// Test if a code snippet can be compiled
12+
fn probe(code: &str) -> bool {
13+
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
14+
let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR");
15+
16+
let mut child = Command::new(rustc)
17+
.arg("--out-dir")
18+
.arg(out_dir)
19+
.arg("--emit=obj")
20+
.arg("-")
21+
.stdin(Stdio::piped())
22+
.spawn()
23+
.expect("rustc probe");
24+
25+
child
26+
.stdin
27+
.as_mut()
28+
.expect("rustc stdin")
29+
.write_all(code.as_bytes())
30+
.expect("write rustc stdin");
31+
32+
child.wait().expect("rustc probe").success()
33+
}

src/iter/find_first_last/test.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,17 @@ fn find_last_folder_yields_last_match() {
101101
assert_eq!(f.complete(), Some(2_i32));
102102
}
103103

104-
105104
/// Produce a parallel iterator for 0u128..10²⁷
105+
#[cfg(has_i128)]
106106
fn octillion() -> impl ParallelIterator<Item = u128> {
107+
// Using parse because some versions of rust don't allow long literals
108+
let octillion = "1000000000000000000000000000".parse::<u128>().unwrap();
109+
(0u128..octillion).into_par_iter()
110+
}
111+
112+
/// Produce a parallel iterator for 0u128..10²⁷
113+
#[cfg(not(has_i128))]
114+
fn octillion() -> impl ParallelIterator<Item = u128>{
107115
(0u32..1_000_000_000)
108116
.into_par_iter()
109117
.with_max_len(1_000)

src/iter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ impl<T: ParallelIterator> IntoParallelIterator for T {
14361436
/// that you can split it at arbitrary indices and draw data from
14371437
/// those points.
14381438
///
1439-
/// **Note:** Not implemented for `u64` and `i64` ranges
1439+
/// **Note:** Not implemented for `u64`, `i64`, `u128`, or `i128` ranges
14401440
pub trait IndexedParallelIterator: ParallelIterator {
14411441
/// Collects the results of the iterator into the specified
14421442
/// vector. The vector is always truncated before execution

src/range.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::ops::Range;
2323
/// Parallel iterator over a range, implemented for all integer types.
2424
///
2525
/// **Note:** The `zip` operation requires `IndexedParallelIterator`
26-
/// which is not implemented for `u64` or `i64`.
26+
/// which is not implemented for `u64`, `i64`, `u128`, or `i128`.
2727
///
2828
/// ```
2929
/// use rayon::prelude::*;
@@ -128,12 +128,12 @@ macro_rules! indexed_range_impl {
128128
}
129129

130130
macro_rules! unindexed_range_impl {
131-
( $t:ty ) => {
131+
( $t:ty, $len_t:ty ) => {
132132
impl IterProducer<$t> {
133-
fn len(&self) -> u64 {
133+
fn len(&self) -> $len_t {
134134
let Range { start, end } = self.range;
135135
if end > start {
136-
end.wrapping_sub(start) as u64
136+
end.wrapping_sub(start) as $len_t
137137
} else {
138138
0
139139
}
@@ -185,9 +185,10 @@ indexed_range_impl!{i32}
185185
indexed_range_impl!{isize}
186186

187187
// other Range<T> with just Iterator
188-
unindexed_range_impl!{u64}
189-
unindexed_range_impl!{i64}
190-
188+
unindexed_range_impl!{u64, u64}
189+
unindexed_range_impl!{i64, u64}
190+
#[cfg(has_i128)] unindexed_range_impl!{u128, u128}
191+
#[cfg(has_i128)] unindexed_range_impl!{i128, u128}
191192

192193
#[test]
193194
pub fn check_range_split_at_overflow() {
@@ -198,3 +199,13 @@ pub fn check_range_split_at_overflow() {
198199
let r2: i32 = right.range.map(|i| i as i32).sum();
199200
assert_eq!(r1 + r2, -100);
200201
}
202+
203+
#[cfg(has_i128)]
204+
#[test]
205+
pub fn test_i128_len_doesnt_overflow() {
206+
// Using parse because some versions of rust don't allow long literals
207+
let octillion = "1000000000000000000000000000".parse::<i128>().unwrap();
208+
let producer = IterProducer { range: 0..octillion };
209+
210+
assert_eq!(octillion as u128, producer.len());
211+
}

0 commit comments

Comments
 (0)