[Docs] Improve documentation (#87)

- Add "How to write and example" section to CONTRIBUTING.md
 - Add a basic example using `target_feature` to the main page
 - Improve documentation of SSE 4.2
   - Improve documentation of constants
   - Improve documentation of _mm_cmpistri
This commit is contained in:
Dan Robertson 2017-10-04 05:15:39 -04:00 committed by Alex Crichton
parent 3202558c98
commit c1da3bad76
3 changed files with 169 additions and 14 deletions

View file

@ -24,13 +24,57 @@ particularly use some help. You may be most interested in [#40][vendor],
implementing all vendor intrinsics on x86. That issue's got some good pointers
about where to get started!
If you've got general questions feel free to [join us on gitter][gitter] and ask
around! Feel free to ping either @BurntSushi or @alexcrichton with questions.
[gitter]: https://gitter.im/rust-impl-period/WG-libs-simd
# How to write examples for stdsimd intrinsics
There are a few features that must be enabled for the given intrinsic to work
properly and the example must only be run by `cargo test --doc` when the feature
is supported by the CPU. As a result, the default `fn main` that is generated by
`rustdoc` will not work (in most cases). Consider using the following as a guide
to ensure your example works as expected.
```rust
/// # // We need cfg_target_feature to ensure the example is only
/// # // run by `cargo test --doc` when the CPU supports the feature
/// # #![feature(cfg_target_feature)]
/// # // We need target_feature for the intrinsic to work
/// # #![feature(target_feature)]
/// #
/// # // rustdoc by default uses `extern crate stdsimd`, but we need the
/// # // `#[macro_use]`
/// # #[macro_use] extern crate stdsimd;
/// #
/// # // The real main function
/// # fn main() {
/// # // Only run this if `<target feature>` is supported
/// # if cfg_feature_enabled!("<target feature>") {
/// # // Create a `worker` function that will only be run if the target feature
/// # // is supported and ensure that `target_feature` is enabled for your worker
/// # // function
/// # #[target_feature = "+<target feature>"]
/// # fn worker() {
///
/// // Write your example here. Feature specific intrinsics will work here! Go wild!
///
/// # }
/// # worker();
/// # }
/// # }
```
If some of the above syntax does not look familiar, the [Documentation as tests] section
of the [Rust Book] describes the `rustdoc` syntax quite well. As always, feel free
to [join us on gitter][gitter] and ask us if you hit any snags, and thank you for helping
to improve the documentation of `stdsimd`!
[new]: https://github.com/rust-lang-nursery/stdsimd/issues/new
[issues]: https://github.com/rust-lang-nursery/stdsimd/issues
[help]: https://github.com/rust-lang-nursery/stdsimd/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
[impl]: https://github.com/rust-lang-nursery/stdsimd/issues?q=is%3Aissue+is%3Aopen+label%3Aimpl-period
[vendor]: https://github.com/rust-lang-nursery/stdsimd/issues/40
If you've got general questions feel free to [join us on gitter][gitter] and ask
around! Feel free to ping either @BurntSushi or @alexcrichton with questions.
[gitter]: https://gitter.im/rust-impl-period/WG-libs-simd
[Documentation as tests]: https://doc.rust-lang.org/book/first-edition/documentation.html#documentation-as-tests
[Rust Book]: https://doc.rust-lang.org/book/first-edition

View file

@ -63,6 +63,38 @@
//! }
//! ```
//!
//! After verifying that a specified feature is available, use `target_feature`
//! 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");
//! }
//! }
//! ```
//!
//! # Status
//!
//! This crate is intended for eventual inclusion into the standard library, but

View file

@ -4,7 +4,7 @@ use stdsimd_test::assert_instr;
use v128::*;
use x86::__m128i;
/// String contains unsigned 8-bit characters
/// String contains unsigned 8-bit characters *(Default)*
pub const _SIDD_UBYTE_OPS: i8 = 0b00000000;
/// String contains unsigned 16-bit characters
pub const _SIDD_UWORD_OPS: i8 = 0b00000001;
@ -13,16 +13,16 @@ pub const _SIDD_SBYTE_OPS: i8 = 0b00000010;
/// String contains unsigned 16-bit characters
pub const _SIDD_SWORD_OPS: i8 = 0b00000011;
/// For each character in `a`, find if it is in `b`
/// For each character in `a`, find if it is in `b` *(Default)*
pub const _SIDD_CMP_EQUAL_ANY: i8 = 0b00000000;
/// For each character in `a`, determine if `b[0] <= c <= b[1] or b[1] <= c <= b[2]...`
pub const _SIDD_CMP_RANGES: i8 = 0b00000100;
/// String equality
/// The strings defined by `a` and `b` are equal
pub const _SIDD_CMP_EQUAL_EACH: i8 = 0b00001000;
/// Substring search
/// Search for the defined substring in the target
pub const _SIDD_CMP_EQUAL_ORDERED: i8 = 0b00001100;
/// Do not negate results
/// Do not negate results *(Default)*
pub const _SIDD_POSITIVE_POLARITY: i8 = 0b00000000;
/// Negate results
pub const _SIDD_NEGATIVE_POLARITY: i8 = 0b00010000;
@ -31,14 +31,14 @@ pub const _SIDD_MASKED_POSITIVE_POLARITY: i8 = 0b00100000;
/// Negate results only before the end of the string
pub const _SIDD_MASKED_NEGATIVE_POLARITY: i8 = 0b00110000;
/// Index only: return the least significant bit
/// **Index only**: return the least significant bit *(Default)*
pub const _SIDD_LEAST_SIGNIFICANT: i8 = 0b00000000;
/// Index only: return the most significant bit
/// **Index only**: return the most significant bit
pub const _SIDD_MOST_SIGNIFICANT: i8 = 0b01000000;
/// Mask only: return the bit mask
/// **Mask only**: return the bit mask
pub const _SIDD_BIT_MASK: i8 = 0b00000000;
/// Mask only: return the byte mask
/// **Mask only**: return the byte mask
pub const _SIDD_UNIT_MASK: i8 = 0b01000000;
/// Compare packed strings with implicit lengths in `a` and `b` using the
@ -59,6 +59,85 @@ 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 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_cmpistri, _SIDD_CMP_EQUAL_ORDERED};
///
/// 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 = __m128i::from(u8x16::load(needle, 0));
/// 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 = __m128i::from(u8x16::load(chunk, 0));
/// let idx = unsafe {
/// _mm_cmpistri(a, b, _SIDD_CMP_EQUAL_ORDERED)
/// };
/// if idx != 16 {
/// indexes.push((idx as usize) + (i * hop));
/// }
/// }
/// assert_eq!(indexes, vec![34]);
/// # }
/// # 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
#[inline(always)]
#[target_feature = "+sse4.2"]
#[cfg_attr(test, assert_instr(pcmpistri, imm8 = 0))]