Skip to content

Commit

Permalink
SIMD-optimized is_ascii based on rust-lang#30740
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrubeck committed Jun 29, 2016
1 parent 3908913 commit 32b1d10
Showing 1 changed file with 50 additions and 2 deletions.
52 changes: 50 additions & 2 deletions src/libstd/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl AsciiExt for str {

#[inline]
fn is_ascii(&self) -> bool {
self.bytes().all(|b| b.is_ascii())
self.as_bytes().is_ascii()
}

#[inline]
Expand Down Expand Up @@ -204,7 +204,55 @@ impl AsciiExt for [u8] {
type Owned = Vec<u8>;
#[inline]
fn is_ascii(&self) -> bool {
self.iter().all(|b| b.is_ascii())
// NOTE: This is largely copied from core::str::run_utf8_validation.

// use truncation to fit u64 into usize
const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;

/// Return `true` if any byte in the word `x` is nonascii (>= 128).
#[inline]
fn contains_nonascii(x: usize) -> bool {
(x & NONASCII_MASK) != 0
}

let mut offset = 0;
let len = self.len();
while offset < len {
if self[offset] >= 128 {
return false;
}
// When the pointer is aligned, read 2 words of data per iteration
// until we find a word containing a non-ascii byte.
let usize_bytes = mem::size_of::<usize>();
let bytes_per_iteration = 2 * usize_bytes;
let ptr = self.as_ptr();
let align = (ptr as usize + offset) & (usize_bytes - 1);
if align == 0 {
if len >= bytes_per_iteration {
while offset <= len - bytes_per_iteration {
unsafe {
let u = *(ptr.offset(offset as isize) as *const usize);
let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);

// return if there is a nonascii byte
let zu = contains_nonascii(u);
let zv = contains_nonascii(v);
if zu || zv {
return false;
}
}
offset += bytes_per_iteration;
}
}
// step from the point where the wordwise loop stopped
while offset < len && self[offset] < 128 {
offset += 1;
}
} else {
offset += 1;
}
}
true
}

#[inline]
Expand Down

0 comments on commit 32b1d10

Please sign in to comment.