Skip to content

Commit

Permalink
Rollup merge of rust-lang#40832 - pftbest:fix_msp430, r=stjepang
Browse files Browse the repository at this point in the history
libcore: fix compilation on 16bit target (MSP430).

Since PR rust-lang#40601 has been merged, libcore no longer compiles on MSP430.
The reason is this code in `break_patterns`:
```rust
 let mut random = len;
 random ^= random << 13;
 random ^= random >> 17;
 random ^= random << 5;
 random &= modulus - 1;
```
It assumes that `len` is at least a 32 bit integer.
As a workaround replace `break_patterns` with an empty function for 16bit targets.

cc @stjepang
cc @alexcrichton
  • Loading branch information
alexcrichton committed Mar 27, 2017
2 parents 4d93c12 + fda8e15 commit 5e9d918
Showing 1 changed file with 32 additions and 24 deletions.
56 changes: 32 additions & 24 deletions src/libcore/slice/sort.rs
Expand Up @@ -498,32 +498,40 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
#[cold]
fn break_patterns<T>(v: &mut [T]) {
let len = v.len();

if len >= 8 {
// A random number will be taken modulo this one. The modulus is a power of two so that we
// can simply take bitwise "and", thus avoiding costly CPU operations.
let modulus = (len / 4).next_power_of_two();
debug_assert!(modulus >= 1 && modulus <= len / 2);

// Pseudorandom number generation from the "Xorshift RNGs" paper by George Marsaglia.
let mut random = len;
random ^= random << 13;
random ^= random >> 17;
random ^= random << 5;
random &= modulus - 1;
debug_assert!(random < len / 2);

// The first index.
let a = len / 4 * 2;
debug_assert!(a >= 1 && a < len - 2);

// The second index.
let b = len / 4 + random;
debug_assert!(b >= 1 && b < len - 2);

// Swap neighbourhoods of `a` and `b`.
// Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
let mut random = len as u32;
let mut gen_u32 = || {
random ^= random << 13;
random ^= random >> 17;
random ^= random << 5;
random
};
let mut gen_usize = || {
if mem::size_of::<usize>() <= 4 {
gen_u32() as usize
} else {
(((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
}
};

// Take random numbers modulo this number.
// The number fits into `usize` because `len` is not greater than `isize::MAX`.
let modulus = len.next_power_of_two();

// Some pivot candidates will be in the nearby of this index. Let's randomize them.
let pos = len / 4 * 2;

for i in 0..3 {
v.swap(a - 1 + i, b - 1 + i);
// Generate a random number modulo `len`. However, in order to avoid costly operations
// we first take it modulo a power of two, and then decrease by `len` until it fits
// into the range `[0, len - 1]`.
let mut other = gen_usize() & (modulus - 1);
while other >= len {
other -= len;
}

v.swap(pos - 1 + i, other);
}
}
}
Expand Down

0 comments on commit 5e9d918

Please sign in to comment.