core::arch::x86

Function _mm_cmpistri

1.27.0 · source
pub unsafe fn _mm_cmpistri(a: __m128i, b: __m128i, const IMM8: i32) -> i32
Available on (x86 or x86-64) and target feature sse4.2 and x86 only.
Expand description

Compares packed strings with implicit lengths in a and b using the control in IMM8 and return the generated index. Similar to _mm_cmpestri with the exception that _mm_cmpestri requires the lengths of a and b to be explicitly specified.

§Control modes

The control specified by IMM8 may be one or more of the following.

§Data size and signedness

§Comparison options

§Result polarity

§Bit returned

§Examples

Finds a substring using _SIDD_CMP_EQUAL_ORDERED

#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;

let haystack = b"This is a long string of text data\r\n\tthat extends
multiple lines";
let needle = b"\r\n\t\0\0\0\0\0\0\0\0\0\0\0\0\0";

let a = _mm_loadu_si128(needle.as_ptr() as *const _);
let hop = 16;
let mut indexes = Vec::new();

// Chunk the haystack into 16 byte chunks and find
// the first "\r\n\t" in the chunk.
for (i, chunk) in haystack.chunks(hop).enumerate() {
    let b = _mm_loadu_si128(chunk.as_ptr() as *const _);
    let idx = _mm_cmpistri(a, b, _SIDD_CMP_EQUAL_ORDERED);
    if idx != 16 {
        indexes.push((idx as usize) + (i * hop));
    }
}
assert_eq!(indexes, vec![34]);

The _mm_cmpistri intrinsic may also be used to find the existence of one or more of a given set of characters in the haystack.

#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;

// Ensure your input is 16 byte aligned
let password = b"hunter2\0\0\0\0\0\0\0\0\0";
let special_chars = b"!@#$%^&*()[]:;<>";

// Load the input
let a = _mm_loadu_si128(special_chars.as_ptr() as *const _);
let b = _mm_loadu_si128(password.as_ptr() as *const _);

// Use _SIDD_CMP_EQUAL_ANY to find the index of any bytes in b
let idx = _mm_cmpistri(a.into(), b.into(), _SIDD_CMP_EQUAL_ANY);

if idx < 16 {
    println!("Congrats! Your password contains a special character");
} else {
    println!("Your password should contain a special character");
}

Finds the index of the first character in the haystack that is within a range of characters.

#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;


// Specify the ranges of values to be searched for [A-Za-z0-9].
let a = b"AZaz09\0\0\0\0\0\0\0\0\0\0";
let a = _mm_loadu_si128(a.as_ptr() as *const _);

// Use _SIDD_CMP_RANGES to find the index of first byte in ranges.
// Which in this case will be the first alpha numeric byte found
// in the string.
let idx = _mm_cmpistri(a, b, _SIDD_CMP_RANGES);

if idx < 16 {
    println!("Found an alpha numeric character");
} else {
    println!("Did not find an alpha numeric character");
}

Working with 16-bit characters.

#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;

// Load the input
let a = _mm_loadu_si128(some_utf16_words.as_ptr() as *const _);
let b = _mm_loadu_si128(more_utf16_words.as_ptr() as *const _);

// Specify _SIDD_UWORD_OPS to compare words instead of bytes, and
// use _SIDD_CMP_EQUAL_EACH to compare the two strings.
let idx = _mm_cmpistri(a, b, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH);

if idx == 0 {
    println!("16-bit unicode strings were equal!");
} else {
    println!("16-bit unicode strings were not equal!");
}

Intel’s documentation