Skip to content

Commit 5c0d3fa

Browse files
dlrobertsonalexcrichton
authored andcommitted
[Docs] Add more docs to the sse4.2 cmpstr fns (#94)
- Add more examples to _mm_cmpistri - Add basic docs to _mm_cmpestri - Cleanup lib docs
1 parent 6d2730a commit 5c0d3fa

File tree

2 files changed

+191
-27
lines changed

2 files changed

+191
-27
lines changed

src/lib.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,32 +67,28 @@
6767
//! to enable a given feature and use the desired intrinsic.
6868
//!
6969
//! ```
70-
//! #![feature(cfg_target_feature)]
71-
//! #![feature(target_feature)]
72-
//!
73-
//! #[macro_use]
74-
//! extern crate stdsimd;
75-
//!
76-
//! fn main() {
77-
//! if cfg_feature_enabled!("avx2") {
78-
//!
79-
//! // avx2 will work. It is safe to use avx2 specific code here.
80-
//! #[target_feature = "+avx2"]
81-
//! fn and_256() {
82-
//! // avx2 feature specific intrinsics will work here!
83-
//! use stdsimd::vendor::{__m256i, _mm256_and_si256};
84-
//!
85-
//! let a = __m256i::splat(5);
86-
//! let b = __m256i::splat(3);
87-
//! let got = unsafe { _mm256_and_si256(a, b) };
88-
//! assert_eq!(got, __m256i::splat(1));
89-
//! }
90-
//!
91-
//! and_256();
92-
//! } else {
93-
//! println!("avx2 intrinsics will not work, they may generate SIGILL");
94-
//! }
70+
//! # #![feature(cfg_target_feature)]
71+
//! # #![feature(target_feature)]
72+
//! # #[macro_use]
73+
//! # extern crate stdsimd;
74+
//! # fn main() {
75+
//! # if cfg_feature_enabled!("avx2") {
76+
//! // avx2 specific code may be used in this function
77+
//! #[target_feature = "+avx2"]
78+
//! fn and_256() {
79+
//! // avx2 feature specific intrinsics will work here!
80+
//! use stdsimd::vendor::{__m256i, _mm256_and_si256};
81+
//!
82+
//! let a = __m256i::splat(5);
83+
//! let b = __m256i::splat(3);
84+
//!
85+
//! let got = unsafe { _mm256_and_si256(a, b) };
86+
//!
87+
//! assert_eq!(got, __m256i::splat(1));
9588
//! }
89+
//! # and_256();
90+
//! # }
91+
//! # }
9692
//! ```
9793
//!
9894
//! # Status

src/x86/sse42.rs

Lines changed: 170 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ pub unsafe fn _mm_cmpistrm(
5858
}
5959

6060
/// Compare packed strings with implicit lengths in `a` and `b` using the
61-
/// control in `imm8`, and return the generated index.
61+
/// control in `imm8`, and return the generated index. Similar to [`_mm_cmpestri`]
62+
/// with the excception that [`_mm_cmpestri`] requires the lengths of `a` and
63+
/// `b` to be explicitly specified.
6264
///
6365
/// # Control modes
6466
///
@@ -87,6 +89,8 @@ pub unsafe fn _mm_cmpistrm(
8789
///
8890
/// # Examples
8991
///
92+
/// Find a substring using [`_SIDD_CMP_EQUAL_ORDERED`]
93+
///
9094
/// ```
9195
/// # #![feature(cfg_target_feature)]
9296
/// # #![feature(target_feature)]
@@ -126,6 +130,89 @@ pub unsafe fn _mm_cmpistrm(
126130
/// # }
127131
/// ```
128132
///
133+
/// The `_mm_cmpistri` intrinsic may also be used to find the existance of
134+
/// one or more of a given set of characters in the haystack.
135+
///
136+
/// ```
137+
/// # #![feature(cfg_target_feature)]
138+
/// # #![feature(target_feature)]
139+
/// #
140+
/// # #[macro_use] extern crate stdsimd;
141+
/// #
142+
/// # fn main() {
143+
/// # if cfg_feature_enabled!("sse4.2") {
144+
/// # #[target_feature = "+sse4.2"]
145+
/// # fn worker() {
146+
/// use stdsimd::simd::u8x16;
147+
/// use stdsimd::vendor::{__m128i, _mm_cmpistri, _SIDD_CMP_EQUAL_ANY};
148+
///
149+
/// // Ensure your input is 16 byte aligned
150+
/// let password = b"hunter2\0\0\0\0\0\0\0\0\0";
151+
/// let special_chars = b"!@#$%^&*()[]:;<>";
152+
///
153+
/// // Load the input
154+
/// let a = __m128i::from(u8x16::load(special_chars, 0));
155+
/// let b = __m128i::from(u8x16::load(password, 0));
156+
///
157+
/// // Use _SIDD_CMP_EQUAL_ANY to find the index of any bytes in b
158+
/// let idx = unsafe {
159+
/// _mm_cmpistri(a, b, _SIDD_CMP_EQUAL_ANY)
160+
/// };
161+
///
162+
/// if idx < 16 {
163+
/// println!("Congrats! Your password contains a special character");
164+
/// # panic!("{:?} does not contain a special character", password);
165+
/// } else {
166+
/// println!("Your password should contain a special character");
167+
/// }
168+
/// # }
169+
/// # worker();
170+
/// # }
171+
/// # }
172+
/// ```
173+
///
174+
/// Working with 16-bit characters.
175+
///
176+
/// ```
177+
/// # #![feature(cfg_target_feature)]
178+
/// # #![feature(target_feature)]
179+
/// #
180+
/// # #[macro_use] extern crate stdsimd;
181+
/// #
182+
/// # fn main() {
183+
/// # if cfg_feature_enabled!("sse4.2") {
184+
/// # #[target_feature = "+sse4.2"]
185+
/// # fn worker() {
186+
/// use stdsimd::simd::u16x8;
187+
/// use stdsimd::vendor::{__m128i, _mm_cmpistri};
188+
/// use stdsimd::vendor::{_SIDD_UWORD_OPS, _SIDD_CMP_EQUAL_EACH};
189+
///
190+
/// # let mut some_utf16_words = [0u16; 8];
191+
/// # let mut more_utf16_words = [0u16; 8];
192+
/// # '❤'.encode_utf16(&mut some_utf16_words);
193+
/// # '𝕊'.encode_utf16(&mut more_utf16_words);
194+
/// // Load the input
195+
/// let a = __m128i::from(u16x8::load(&some_utf16_words, 0));
196+
/// let b = __m128i::from(u16x8::load(&more_utf16_words, 0));
197+
///
198+
/// // Specify _SIDD_UWORD_OPS to compare words instead of bytes, and
199+
/// // use _SIDD_CMP_EQUAL_EACH to compare the two strings.
200+
/// let idx = unsafe {
201+
/// _mm_cmpistri(a, b, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH)
202+
/// };
203+
///
204+
/// if idx == 0 {
205+
/// println!("16-bit unicode strings were equal!");
206+
/// # panic!("Strings should not be equal!")
207+
/// } else {
208+
/// println!("16-bit unicode strings were not equal!");
209+
/// }
210+
/// # }
211+
/// # worker();
212+
/// # }
213+
/// # }
214+
/// ```
215+
///
129216
/// [`_SIDD_UBYTE_OPS`]: constant._SIDD_UBYTE_OPS.html
130217
/// [`_SIDD_UWORD_OPS`]: constant._SIDD_UWORD_OPS.html
131218
/// [`_SIDD_SBYTE_OPS`]: constant._SIDD_SBYTE_OPS.html
@@ -138,6 +225,7 @@ pub unsafe fn _mm_cmpistrm(
138225
/// [`_SIDD_NEGATIVE_POLARITY`]: constant._SIDD_NEGATIVE_POLARITY.html
139226
/// [`_SIDD_LEAST_SIGNIFICANT`]: constant._SIDD_LEAST_SIGNIFICANT.html
140227
/// [`_SIDD_MOST_SIGNIFICANT`]: constant._SIDD_MOST_SIGNIFICANT.html
228+
/// [`_mm_cmpestri`]: fn._mm_cmpestri.html
141229
#[inline(always)]
142230
#[target_feature = "+sse4.2"]
143231
#[cfg_attr(test, assert_instr(pcmpistri, imm8 = 0))]
@@ -255,7 +343,87 @@ pub unsafe fn _mm_cmpestrm(
255343
}
256344

257345
/// Compare packed strings `a` and `b` with lengths `la` and `lb` using the
258-
/// control in `imm8`, and return the generated index.
346+
/// control in `imm8`, and return the generated index. Similar to [`_mm_cmpistri`]
347+
/// with the excception that [`_mm_cmpistri`] implicityly determines the length of
348+
/// `a` and `b`.
349+
///
350+
/// # Control modes
351+
///
352+
/// The control specified by `imm8` may be one or more of the following.
353+
///
354+
/// ## Data size and signedness
355+
///
356+
/// - [`_SIDD_UBYTE_OPS`] - Default
357+
/// - [`_SIDD_UWORD_OPS`]
358+
/// - [`_SIDD_SBYTE_OPS`]
359+
/// - [`_SIDD_SWORD_OPS`]
360+
///
361+
/// ## Comparison options
362+
/// - [`_SIDD_CMP_EQUAL_ANY`] - Default
363+
/// - [`_SIDD_CMP_RANGES`]
364+
/// - [`_SIDD_CMP_EQUAL_EACH`]
365+
/// - [`_SIDD_CMP_EQUAL_ORDERED`]
366+
///
367+
/// ## Result polarity
368+
/// - [`_SIDD_POSITIVE_POLARITY`] - Default
369+
/// - [`_SIDD_NEGATIVE_POLARITY`]
370+
///
371+
/// ## Bit returned
372+
/// - [`_SIDD_LEAST_SIGNIFICANT`] - Default
373+
/// - [`_SIDD_MOST_SIGNIFICANT`]
374+
///
375+
/// # Examples
376+
///
377+
/// ```
378+
/// # #![feature(cfg_target_feature)]
379+
/// # #![feature(target_feature)]
380+
/// #
381+
/// # #[macro_use] extern crate stdsimd;
382+
/// #
383+
/// # fn main() {
384+
/// # if cfg_feature_enabled!("sse4.2") {
385+
/// # #[target_feature = "+sse4.2"]
386+
/// # fn worker() {
387+
///
388+
/// use stdsimd::simd::u8x16;
389+
/// use stdsimd::vendor::{__m128i, _mm_cmpestri, _SIDD_CMP_EQUAL_ORDERED};
390+
///
391+
/// // The string we want to find a substring in
392+
/// let haystack = b"Split \r\n\t line ";
393+
///
394+
/// // The string we want to search for with some
395+
/// // extra bytes we do not want to search for.
396+
/// let needle = b"\r\n\t ignore this ";
397+
///
398+
/// let a = __m128i::from(u8x16::load(needle, 0));
399+
/// let b = __m128i::from(u8x16::load(haystack, 0));
400+
///
401+
/// // Note: We explicitly specify we only want to search `b` for the
402+
/// // first 3 characters of a.
403+
/// let idx = unsafe {
404+
/// _mm_cmpestri(a, 3, b, 15, _SIDD_CMP_EQUAL_ORDERED)
405+
/// };
406+
///
407+
/// assert_eq!(idx, 6);
408+
/// # }
409+
/// # worker();
410+
/// # }
411+
/// # }
412+
/// ```
413+
///
414+
/// [`_SIDD_UBYTE_OPS`]: constant._SIDD_UBYTE_OPS.html
415+
/// [`_SIDD_UWORD_OPS`]: constant._SIDD_UWORD_OPS.html
416+
/// [`_SIDD_SBYTE_OPS`]: constant._SIDD_SBYTE_OPS.html
417+
/// [`_SIDD_SWORD_OPS`]: constant._SIDD_SWORD_OPS.html
418+
/// [`_SIDD_CMP_EQUAL_ANY`]: constant._SIDD_CMP_EQUAL_ANY.html
419+
/// [`_SIDD_CMP_RANGES`]: constant._SIDD_CMP_RANGES.html
420+
/// [`_SIDD_CMP_EQUAL_EACH`]: constant._SIDD_CMP_EQUAL_EACH.html
421+
/// [`_SIDD_CMP_EQUAL_ORDERED`]: constant._SIDD_CMP_EQUAL_ORDERED.html
422+
/// [`_SIDD_POSITIVE_POLARITY`]: constant._SIDD_POSITIVE_POLARITY.html
423+
/// [`_SIDD_NEGATIVE_POLARITY`]: constant._SIDD_NEGATIVE_POLARITY.html
424+
/// [`_SIDD_LEAST_SIGNIFICANT`]: constant._SIDD_LEAST_SIGNIFICANT.html
425+
/// [`_SIDD_MOST_SIGNIFICANT`]: constant._SIDD_MOST_SIGNIFICANT.html
426+
/// [`_mm_cmpistri`]: fn._mm_cmpistri.html
259427
#[inline(always)]
260428
#[target_feature = "+sse4.2"]
261429
#[cfg_attr(test, assert_instr(pcmpestri, imm8 = 0))]

0 commit comments

Comments
 (0)