Skip to content

Commit

Permalink
[Docs] Add more docs to the sse4.2 cmpstr fns (rust-lang#94)
Browse files Browse the repository at this point in the history
- Add more examples to _mm_cmpistri
 - Add basic docs to _mm_cmpestri
 - Cleanup lib docs
  • Loading branch information
dlrobertson authored and alexcrichton committed Oct 5, 2017
1 parent 6d2730a commit 5c0d3fa
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 27 deletions.
46 changes: 21 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,32 +67,28 @@
//! to enable a given feature and use the desired intrinsic.
//!
//! ```
//! #![feature(cfg_target_feature)]
//! #![feature(target_feature)]
//!
//! #[macro_use]
//! extern crate stdsimd;
//!
//! fn main() {
//! if cfg_feature_enabled!("avx2") {
//!
//! // avx2 will work. It is safe to use avx2 specific code here.
//! #[target_feature = "+avx2"]
//! fn and_256() {
//! // avx2 feature specific intrinsics will work here!
//! use stdsimd::vendor::{__m256i, _mm256_and_si256};
//!
//! let a = __m256i::splat(5);
//! let b = __m256i::splat(3);
//! let got = unsafe { _mm256_and_si256(a, b) };
//! assert_eq!(got, __m256i::splat(1));
//! }
//!
//! and_256();
//! } else {
//! println!("avx2 intrinsics will not work, they may generate SIGILL");
//! }
//! # #![feature(cfg_target_feature)]
//! # #![feature(target_feature)]
//! # #[macro_use]
//! # extern crate stdsimd;
//! # fn main() {
//! # if cfg_feature_enabled!("avx2") {
//! // avx2 specific code may be used in this function
//! #[target_feature = "+avx2"]
//! fn and_256() {
//! // avx2 feature specific intrinsics will work here!
//! use stdsimd::vendor::{__m256i, _mm256_and_si256};
//!
//! let a = __m256i::splat(5);
//! let b = __m256i::splat(3);
//!
//! let got = unsafe { _mm256_and_si256(a, b) };
//!
//! assert_eq!(got, __m256i::splat(1));
//! }
//! # and_256();
//! # }
//! # }
//! ```
//!
//! # Status
Expand Down
172 changes: 170 additions & 2 deletions src/x86/sse42.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ pub unsafe fn _mm_cmpistrm(
}

/// Compare packed strings with implicit lengths in `a` and `b` using the
/// control in `imm8`, and return the generated index.
/// control in `imm8`, and return the generated index. Similar to [`_mm_cmpestri`]
/// with the excception that [`_mm_cmpestri`] requires the lengths of `a` and
/// `b` to be explicitly specified.
///
/// # Control modes
///
Expand Down Expand Up @@ -87,6 +89,8 @@ pub unsafe fn _mm_cmpistrm(
///
/// # Examples
///
/// Find a substring using [`_SIDD_CMP_EQUAL_ORDERED`]
///
/// ```
/// # #![feature(cfg_target_feature)]
/// # #![feature(target_feature)]
Expand Down Expand Up @@ -126,6 +130,89 @@ pub unsafe fn _mm_cmpistrm(
/// # }
/// ```
///
/// The `_mm_cmpistri` intrinsic may also be used to find the existance of
/// one or more of a given set of characters in the haystack.
///
/// ```
/// # #![feature(cfg_target_feature)]
/// # #![feature(target_feature)]
/// #
/// # #[macro_use] extern crate stdsimd;
/// #
/// # fn main() {
/// # if cfg_feature_enabled!("sse4.2") {
/// # #[target_feature = "+sse4.2"]
/// # fn worker() {
/// use stdsimd::simd::u8x16;
/// use stdsimd::vendor::{__m128i, _mm_cmpistri, _SIDD_CMP_EQUAL_ANY};
///
/// // 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 = __m128i::from(u8x16::load(special_chars, 0));
/// let b = __m128i::from(u8x16::load(password, 0));
///
/// // Use _SIDD_CMP_EQUAL_ANY to find the index of any bytes in b
/// let idx = unsafe {
/// _mm_cmpistri(a, b, _SIDD_CMP_EQUAL_ANY)
/// };
///
/// if idx < 16 {
/// println!("Congrats! Your password contains a special character");
/// # panic!("{:?} does not contain a special character", password);
/// } else {
/// println!("Your password should contain a special character");
/// }
/// # }
/// # worker();
/// # }
/// # }
/// ```
///
/// Working with 16-bit characters.
///
/// ```
/// # #![feature(cfg_target_feature)]
/// # #![feature(target_feature)]
/// #
/// # #[macro_use] extern crate stdsimd;
/// #
/// # fn main() {
/// # if cfg_feature_enabled!("sse4.2") {
/// # #[target_feature = "+sse4.2"]
/// # fn worker() {
/// use stdsimd::simd::u16x8;
/// use stdsimd::vendor::{__m128i, _mm_cmpistri};
/// use stdsimd::vendor::{_SIDD_UWORD_OPS, _SIDD_CMP_EQUAL_EACH};
///
/// # let mut some_utf16_words = [0u16; 8];
/// # let mut more_utf16_words = [0u16; 8];
/// # '❤'.encode_utf16(&mut some_utf16_words);
/// # '𝕊'.encode_utf16(&mut more_utf16_words);
/// // Load the input
/// let a = __m128i::from(u16x8::load(&some_utf16_words, 0));
/// let b = __m128i::from(u16x8::load(&more_utf16_words, 0));
///
/// // Specify _SIDD_UWORD_OPS to compare words instead of bytes, and
/// // use _SIDD_CMP_EQUAL_EACH to compare the two strings.
/// let idx = unsafe {
/// _mm_cmpistri(a, b, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH)
/// };
///
/// if idx == 0 {
/// println!("16-bit unicode strings were equal!");
/// # panic!("Strings should not be equal!")
/// } else {
/// println!("16-bit unicode strings were not equal!");
/// }
/// # }
/// # worker();
/// # }
/// # }
/// ```
///
/// [`_SIDD_UBYTE_OPS`]: constant._SIDD_UBYTE_OPS.html
/// [`_SIDD_UWORD_OPS`]: constant._SIDD_UWORD_OPS.html
/// [`_SIDD_SBYTE_OPS`]: constant._SIDD_SBYTE_OPS.html
Expand All @@ -138,6 +225,7 @@ pub unsafe fn _mm_cmpistrm(
/// [`_SIDD_NEGATIVE_POLARITY`]: constant._SIDD_NEGATIVE_POLARITY.html
/// [`_SIDD_LEAST_SIGNIFICANT`]: constant._SIDD_LEAST_SIGNIFICANT.html
/// [`_SIDD_MOST_SIGNIFICANT`]: constant._SIDD_MOST_SIGNIFICANT.html
/// [`_mm_cmpestri`]: fn._mm_cmpestri.html
#[inline(always)]
#[target_feature = "+sse4.2"]
#[cfg_attr(test, assert_instr(pcmpistri, imm8 = 0))]
Expand Down Expand Up @@ -255,7 +343,87 @@ pub unsafe fn _mm_cmpestrm(
}

/// Compare packed strings `a` and `b` with lengths `la` and `lb` using the
/// control in `imm8`, and return the generated index.
/// control in `imm8`, and return the generated index. Similar to [`_mm_cmpistri`]
/// with the excception that [`_mm_cmpistri`] implicityly determines the length of
/// `a` and `b`.
///
/// # Control modes
///
/// The control specified by `imm8` may be one or more of the following.
///
/// ## Data size and signedness
///
/// - [`_SIDD_UBYTE_OPS`] - Default
/// - [`_SIDD_UWORD_OPS`]
/// - [`_SIDD_SBYTE_OPS`]
/// - [`_SIDD_SWORD_OPS`]
///
/// ## Comparison options
/// - [`_SIDD_CMP_EQUAL_ANY`] - Default
/// - [`_SIDD_CMP_RANGES`]
/// - [`_SIDD_CMP_EQUAL_EACH`]
/// - [`_SIDD_CMP_EQUAL_ORDERED`]
///
/// ## Result polarity
/// - [`_SIDD_POSITIVE_POLARITY`] - Default
/// - [`_SIDD_NEGATIVE_POLARITY`]
///
/// ## Bit returned
/// - [`_SIDD_LEAST_SIGNIFICANT`] - Default
/// - [`_SIDD_MOST_SIGNIFICANT`]
///
/// # Examples
///
/// ```
/// # #![feature(cfg_target_feature)]
/// # #![feature(target_feature)]
/// #
/// # #[macro_use] extern crate stdsimd;
/// #
/// # fn main() {
/// # if cfg_feature_enabled!("sse4.2") {
/// # #[target_feature = "+sse4.2"]
/// # fn worker() {
///
/// use stdsimd::simd::u8x16;
/// use stdsimd::vendor::{__m128i, _mm_cmpestri, _SIDD_CMP_EQUAL_ORDERED};
///
/// // The string we want to find a substring in
/// let haystack = b"Split \r\n\t line ";
///
/// // The string we want to search for with some
/// // extra bytes we do not want to search for.
/// let needle = b"\r\n\t ignore this ";
///
/// let a = __m128i::from(u8x16::load(needle, 0));
/// let b = __m128i::from(u8x16::load(haystack, 0));
///
/// // Note: We explicitly specify we only want to search `b` for the
/// // first 3 characters of a.
/// let idx = unsafe {
/// _mm_cmpestri(a, 3, b, 15, _SIDD_CMP_EQUAL_ORDERED)
/// };
///
/// assert_eq!(idx, 6);
/// # }
/// # worker();
/// # }
/// # }
/// ```
///
/// [`_SIDD_UBYTE_OPS`]: constant._SIDD_UBYTE_OPS.html
/// [`_SIDD_UWORD_OPS`]: constant._SIDD_UWORD_OPS.html
/// [`_SIDD_SBYTE_OPS`]: constant._SIDD_SBYTE_OPS.html
/// [`_SIDD_SWORD_OPS`]: constant._SIDD_SWORD_OPS.html
/// [`_SIDD_CMP_EQUAL_ANY`]: constant._SIDD_CMP_EQUAL_ANY.html
/// [`_SIDD_CMP_RANGES`]: constant._SIDD_CMP_RANGES.html
/// [`_SIDD_CMP_EQUAL_EACH`]: constant._SIDD_CMP_EQUAL_EACH.html
/// [`_SIDD_CMP_EQUAL_ORDERED`]: constant._SIDD_CMP_EQUAL_ORDERED.html
/// [`_SIDD_POSITIVE_POLARITY`]: constant._SIDD_POSITIVE_POLARITY.html
/// [`_SIDD_NEGATIVE_POLARITY`]: constant._SIDD_NEGATIVE_POLARITY.html
/// [`_SIDD_LEAST_SIGNIFICANT`]: constant._SIDD_LEAST_SIGNIFICANT.html
/// [`_SIDD_MOST_SIGNIFICANT`]: constant._SIDD_MOST_SIGNIFICANT.html
/// [`_mm_cmpistri`]: fn._mm_cmpistri.html
#[inline(always)]
#[target_feature = "+sse4.2"]
#[cfg_attr(test, assert_instr(pcmpestri, imm8 = 0))]
Expand Down

0 comments on commit 5c0d3fa

Please sign in to comment.