aboutsummaryrefslogtreecommitdiff
path: root/src/slice.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/slice.rs')
-rw-r--r--src/slice.rs234
1 files changed, 56 insertions, 178 deletions
diff --git a/src/slice.rs b/src/slice.rs
index a8abbb0..f1e9feb 100644
--- a/src/slice.rs
+++ b/src/slice.rs
@@ -1,28 +1,22 @@
-//! Contains utility functions and traits to convert between slices of `u16` bits and `f16` or
-//! `bf16` numbers.
+//! Contains utility functions and traits to convert between slices of [`u16`] bits and [`f16`] or
+//! [`bf16`] numbers.
//!
//! The utility [`HalfBitsSliceExt`] sealed extension trait is implemented for `[u16]` slices,
//! while the utility [`HalfFloatSliceExt`] sealed extension trait is implemented for both `[f16]`
//! and `[bf16]` slices. These traits provide efficient conversions and reinterpret casting of
-//! larger buffers of floating point values, and are automatically included in the [`prelude`]
-//! module.
-//!
-//! [`HalfBitsSliceExt`]: trait.HalfBitsSliceExt.html
-//! [`HalfFloatSliceExt`]: trait.HalfFloatSliceExt.html
-//! [`prelude`]: ../prelude/index.html
+//! larger buffers of floating point values, and are automatically included in the
+//! [`prelude`][crate::prelude] module.
use crate::{bf16, binary16::convert, f16};
-use core::slice;
-
-#[cfg(all(feature = "alloc", not(feature = "std")))]
+#[cfg(feature = "alloc")]
use alloc::vec::Vec;
+use core::slice;
/// Extensions to `[f16]` and `[bf16]` slices to support conversion and reinterpret operations.
///
/// This trait is sealed and cannot be implemented outside of this crate.
pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
- /// Reinterpret a slice of [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
- /// numbers as a slice of `u16` bits.
+ /// Reinterprets a slice of [`f16`] or [`bf16`] numbers as a slice of [`u16`] bits.
///
/// This is a zero-copy operation. The reinterpreted slice has the same lifetime and memory
/// location as `self`.
@@ -36,10 +30,11 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
///
/// assert_eq!(int_buffer, [float_buffer[0].to_bits(), float_buffer[1].to_bits(), float_buffer[2].to_bits()]);
/// ```
+ #[must_use]
fn reinterpret_cast(&self) -> &[u16];
- /// Reinterpret a mutable slice of [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) numbers as a mutable slice of `u16` bits.
+ /// Reinterprets a mutable slice of [`f16`] or [`bf16`] numbers as a mutable slice of [`u16`].
+ /// bits
///
/// This is a zero-copy operation. The transmuted slice has the same lifetime as the original,
/// which prevents mutating `self` as long as the returned `&mut [u16]` is borrowed.
@@ -62,17 +57,17 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
/// // Note that we need to drop int_buffer before using float_buffer again or we will get a borrow error.
/// assert_eq!(float_buffer, [f16::from_f32(0.), f16::from_f32(2.), f16::from_f32(3.)]);
/// ```
+ #[must_use]
fn reinterpret_cast_mut(&mut self) -> &mut [u16];
- /// Convert all of the elements of a `[f32]` slice into [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) values in `self`.
+ /// Converts all of the elements of a `[f32]` slice into [`f16`] or [`bf16`] values in `self`.
///
/// The length of `src` must be the same as `self`.
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// # Panics
///
@@ -94,15 +89,14 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
/// ```
fn convert_from_f32_slice(&mut self, src: &[f32]);
- /// Convert all of the elements of a `[f64]` slice into [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) values in `self`.
+ /// Converts all of the elements of a `[f64]` slice into [`f16`] or [`bf16`] values in `self`.
///
/// The length of `src` must be the same as `self`.
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// # Panics
///
@@ -124,15 +118,14 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
/// ```
fn convert_from_f64_slice(&mut self, src: &[f64]);
- /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
- /// elements of `self` into `f32` values in `dst`.
+ /// Converts all of the [`f16`] or [`bf16`] elements of `self` into [`f32`] values in `dst`.
///
/// The length of `src` must be the same as `self`.
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// # Panics
///
@@ -153,15 +146,14 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
/// ```
fn convert_to_f32_slice(&self, dst: &mut [f32]);
- /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
- /// elements of `self` into `f64` values in `dst`.
+ /// Converts all of the [`f16`] or [`bf16`] elements of `self` into [`f64`] values in `dst`.
///
/// The length of `src` must be the same as `self`.
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// # Panics
///
@@ -182,16 +174,15 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
/// ```
fn convert_to_f64_slice(&self, dst: &mut [f64]);
- // Because trait is sealed, we can get away with different interfaces between features
+ // Because trait is sealed, we can get away with different interfaces between features.
- #[cfg(any(feature = "alloc", feature = "std"))]
- /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
- /// elements of `self` into `f32` values in a new vector.
+ /// Converts all of the [`f16`] or [`bf16`] elements of `self` into [`f32`] values in a new
+ /// vector
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// This method is only available with the `std` or `alloc` feature.
///
@@ -203,15 +194,18 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
///
/// assert_eq!(vec, vec![1., 2., 3., 4.]);
/// ```
+ #[cfg(any(feature = "alloc", feature = "std"))]
+ #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+ #[must_use]
fn to_f32_vec(&self) -> Vec<f32>;
- /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
- /// elements of `self` into `f64` values in a new vector.
+ /// Converts all of the [`f16`] or [`bf16`] elements of `self` into [`f64`] values in a new
+ /// vector.
///
/// The conversion operation is vectorized over the slice, meaning the conversion may be more
/// efficient than converting individual elements on some hardware that supports SIMD
- /// conversions. See [crate documentation](../index.html) for more information on hardware
- /// conversion support.
+ /// conversions. See [crate documentation](crate) for more information on hardware conversion
+ /// support.
///
/// This method is only available with the `std` or `alloc` feature.
///
@@ -223,7 +217,9 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
///
/// assert_eq!(vec, vec![1., 2., 3., 4.]);
/// ```
- #[cfg(any(feature = "alloc", feature = "std"))]
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+ #[must_use]
fn to_f64_vec(&self) -> Vec<f64>;
}
@@ -231,11 +227,9 @@ pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
///
/// This trait is sealed and cannot be implemented outside of this crate.
pub trait HalfBitsSliceExt: private::SealedHalfBitsSlice {
- /// Reinterpret a slice of `u16` bits as a slice of [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) numbers.
+ /// Reinterprets a slice of [`u16`] bits as a slice of [`f16`] or [`bf16`] numbers.
///
- /// `H` is the type to cast to, and must be either the [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) type.
+ /// `H` is the type to cast to, and must be either the [`f16`] or [`bf16`] type.
///
/// This is a zero-copy operation. The reinterpreted slice has the same lifetime and memory
/// location as `self`.
@@ -253,15 +247,15 @@ pub trait HalfBitsSliceExt: private::SealedHalfBitsSlice {
/// // The following is also valid in Rust.
/// let typed_buffer = int_buffer.reinterpret_cast::<f16>();
/// ```
+ #[must_use]
fn reinterpret_cast<H>(&self) -> &[H]
where
H: crate::private::SealedHalf;
- /// Reinterpret a mutable slice of `u16` bits as a mutable slice of [`f16`](../struct.f16.html)
- /// or [`bf16`](../struct.bf16.html) numbers.
+ /// Reinterprets a mutable slice of [`u16`] bits as a mutable slice of [`f16`] or [`bf16`]
+ /// numbers.
///
- /// `H` is the type to cast to, and must be either the [`f16`](../struct.f16.html) or
- /// [`bf16`](../struct.bf16.html) type.
+ /// `H` is the type to cast to, and must be either the [`f16`] or [`bf16`] type.
///
/// This is a zero-copy operation. The transmuted slice has the same lifetime as the original,
/// which prevents mutating `self` as long as the returned `&mut [f16]` is borrowed.
@@ -288,6 +282,7 @@ pub trait HalfBitsSliceExt: private::SealedHalfBitsSlice {
/// // The following is also valid in Rust.
/// let typed_buffer = int_buffer.reinterpret_cast_mut::<f16>();
/// ```
+ #[must_use]
fn reinterpret_cast_mut<H>(&mut self) -> &mut [H]
where
H: crate::private::SealedHalf;
@@ -316,7 +311,7 @@ impl HalfFloatSliceExt for [f16] {
#[inline]
fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
- let pointer = self.as_ptr() as *mut u16;
+ let pointer = self.as_mut_ptr().cast::<u16>();
let length = self.len();
// SAFETY: We are reconstructing full length of original slice, using its same lifetime,
// and the size of elements are identical
@@ -330,24 +325,7 @@ impl HalfFloatSliceExt for [f16] {
"destination and source slices have different lengths"
);
- let mut chunks = src.chunks_exact(4);
- let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
- for chunk in &mut chunks {
- let vec = convert::f32x4_to_f16x4(chunk);
- let dst_idx = chunk_count * 4;
- self[dst_idx..dst_idx + 4].copy_from_slice(vec.reinterpret_cast());
- chunk_count += 1;
- }
-
- // Process remainder
- if !chunks.remainder().is_empty() {
- let mut buf = [0f32; 4];
- buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder());
- let vec = convert::f32x4_to_f16x4(&buf);
- let dst_idx = chunk_count * 4;
- self[dst_idx..dst_idx + chunks.remainder().len()]
- .copy_from_slice(vec[..chunks.remainder().len()].reinterpret_cast());
- }
+ convert::f32_to_f16_slice(src, self.reinterpret_cast_mut())
}
fn convert_from_f64_slice(&mut self, src: &[f64]) {
@@ -357,24 +335,7 @@ impl HalfFloatSliceExt for [f16] {
"destination and source slices have different lengths"
);
- let mut chunks = src.chunks_exact(4);
- let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
- for chunk in &mut chunks {
- let vec = convert::f64x4_to_f16x4(chunk);
- let dst_idx = chunk_count * 4;
- self[dst_idx..dst_idx + 4].copy_from_slice(vec.reinterpret_cast());
- chunk_count += 1;
- }
-
- // Process remainder
- if !chunks.remainder().is_empty() {
- let mut buf = [0f64; 4];
- buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder());
- let vec = convert::f64x4_to_f16x4(&buf);
- let dst_idx = chunk_count * 4;
- self[dst_idx..dst_idx + chunks.remainder().len()]
- .copy_from_slice(vec[..chunks.remainder().len()].reinterpret_cast());
- }
+ convert::f64_to_f16_slice(src, self.reinterpret_cast_mut())
}
fn convert_to_f32_slice(&self, dst: &mut [f32]) {
@@ -384,24 +345,7 @@ impl HalfFloatSliceExt for [f16] {
"destination and source slices have different lengths"
);
- let mut chunks = self.chunks_exact(4);
- let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
- for chunk in &mut chunks {
- let vec = convert::f16x4_to_f32x4(chunk.reinterpret_cast());
- let dst_idx = chunk_count * 4;
- dst[dst_idx..dst_idx + 4].copy_from_slice(&vec);
- chunk_count += 1;
- }
-
- // Process remainder
- if !chunks.remainder().is_empty() {
- let mut buf = [0u16; 4];
- buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder().reinterpret_cast());
- let vec = convert::f16x4_to_f32x4(&buf);
- let dst_idx = chunk_count * 4;
- dst[dst_idx..dst_idx + chunks.remainder().len()]
- .copy_from_slice(&vec[..chunks.remainder().len()]);
- }
+ convert::f16_to_f32_slice(self.reinterpret_cast(), dst)
}
fn convert_to_f64_slice(&self, dst: &mut [f64]) {
@@ -411,28 +355,12 @@ impl HalfFloatSliceExt for [f16] {
"destination and source slices have different lengths"
);
- let mut chunks = self.chunks_exact(4);
- let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
- for chunk in &mut chunks {
- let vec = convert::f16x4_to_f64x4(chunk.reinterpret_cast());
- let dst_idx = chunk_count * 4;
- dst[dst_idx..dst_idx + 4].copy_from_slice(&vec);
- chunk_count += 1;
- }
-
- // Process remainder
- if !chunks.remainder().is_empty() {
- let mut buf = [0u16; 4];
- buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder().reinterpret_cast());
- let vec = convert::f16x4_to_f64x4(&buf);
- let dst_idx = chunk_count * 4;
- dst[dst_idx..dst_idx + chunks.remainder().len()]
- .copy_from_slice(&vec[..chunks.remainder().len()]);
- }
+ convert::f16_to_f64_slice(self.reinterpret_cast(), dst)
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[inline]
+ #[allow(clippy::uninit_vec)]
fn to_f32_vec(&self) -> Vec<f32> {
let mut vec = Vec::with_capacity(self.len());
// SAFETY: convert will initialize every value in the vector without reading them,
@@ -445,6 +373,7 @@ impl HalfFloatSliceExt for [f16] {
#[cfg(any(feature = "alloc", feature = "std"))]
#[inline]
+ #[allow(clippy::uninit_vec)]
fn to_f64_vec(&self) -> Vec<f64> {
let mut vec = Vec::with_capacity(self.len());
// SAFETY: convert will initialize every value in the vector without reading them,
@@ -468,7 +397,7 @@ impl HalfFloatSliceExt for [bf16] {
#[inline]
fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
- let pointer = self.as_ptr() as *mut u16;
+ let pointer = self.as_mut_ptr().cast::<u16>();
let length = self.len();
// SAFETY: We are reconstructing full length of original slice, using its same lifetime,
// and the size of elements are identical
@@ -529,6 +458,7 @@ impl HalfFloatSliceExt for [bf16] {
#[cfg(any(feature = "alloc", feature = "std"))]
#[inline]
+ #[allow(clippy::uninit_vec)]
fn to_f32_vec(&self) -> Vec<f32> {
let mut vec = Vec::with_capacity(self.len());
// SAFETY: convert will initialize every value in the vector without reading them,
@@ -541,6 +471,7 @@ impl HalfFloatSliceExt for [bf16] {
#[cfg(any(feature = "alloc", feature = "std"))]
#[inline]
+ #[allow(clippy::uninit_vec)]
fn to_f64_vec(&self) -> Vec<f64> {
let mut vec = Vec::with_capacity(self.len());
// SAFETY: convert will initialize every value in the vector without reading them,
@@ -579,58 +510,7 @@ impl HalfBitsSliceExt for [u16] {
}
}
-/// Reinterpret a mutable slice of `u16` bits as a mutable slice of [`f16`](../struct.f16.html)
-/// numbers.
-///
-/// The transmuted slice has the same life time as the original, which prevents mutating the borrowed
-/// `mut [u16]` argument as long as the returned `mut [f16]` is borrowed.
-#[deprecated(
- since = "1.4.0",
- note = "use [`HalfBitsSliceExt::reinterpret_cast_mut`](trait.HalfBitsSliceExt.html#tymethod.reinterpret_cast_mut) instead"
-)]
-#[inline]
-pub fn from_bits_mut(bits: &mut [u16]) -> &mut [f16] {
- bits.reinterpret_cast_mut()
-}
-
-/// Reinterpret a mutable slice of [`f16`](../struct.f16.html) numbers as a mutable slice of `u16`
-/// bits.
-///
-///The transmuted slice has the same life time as the original, which prevents mutating the
-/// borrowed `mut [f16]` argument as long as the returned `mut [u16]` is borrowed.
-#[deprecated(
- since = "1.4.0",
- note = "use [`HalfFloatSliceExt::reinterpret_cast_mut`](trait.HalfFloatSliceExt.html#tymethod.reinterpret_cast_mut) instead"
-)]
-#[inline]
-pub fn to_bits_mut(bits: &mut [f16]) -> &mut [u16] {
- bits.reinterpret_cast_mut()
-}
-
-/// Reinterpret a slice of `u16` bits as a slice of [`f16`](../struct.f16.html) numbers.
-///
-/// The transmuted slice has the same life time as the original.
-#[deprecated(
- since = "1.4.0",
- note = "use [`HalfBitsSliceExt::reinterpret_cast`](trait.HalfBitsSliceExt.html#tymethod.reinterpret_cast) instead"
-)]
-#[inline]
-pub fn from_bits(bits: &[u16]) -> &[f16] {
- bits.reinterpret_cast()
-}
-
-/// Reinterpret a slice of [`f16`](../struct.f16.html) numbers as a slice of `u16` bits.
-///
-/// The transmuted slice has the same life time as the original.
-#[deprecated(
- since = "1.4.0",
- note = "use [`HalfFloatSliceExt::reinterpret_cast`](trait.HalfFloatSliceExt.html#tymethod.reinterpret_cast) instead"
-)]
-#[inline]
-pub fn to_bits(bits: &[f16]) -> &[u16] {
- bits.reinterpret_cast()
-}
-
+#[allow(clippy::float_cmp)]
#[cfg(test)]
mod test {
use super::{HalfBitsSliceExt, HalfFloatSliceExt};
@@ -662,7 +542,6 @@ mod test {
{
// would not compile without these braces
- // TODO: add automated test to check that it does not compile without braces
let numbers = bits.reinterpret_cast_mut();
numbers[0] = f16::E;
}
@@ -699,7 +578,6 @@ mod test {
{
// would not compile without these braces
- // TODO: add automated test to check that it does not compile without braces
let numbers = bits.reinterpret_cast_mut();
numbers[0] = bf16::E;
}