Coverage Report

Created: 2025-07-18 06:49

/rust/registry/src/index.crates.io-6f17d22bba15001f/half-2.6.0/src/vec.rs
Line
Count
Source (jump to first uncovered line)
1
//! Contains utility functions and traits to convert between vectors of [`u16`] bits and [`struct@f16`] or
2
//! [`bf16`] vectors.
3
//!
4
//! The utility [`HalfBitsVecExt`] sealed extension trait is implemented for [`Vec<u16>`] vectors,
5
//! while the utility [`HalfFloatVecExt`] sealed extension trait is implemented for both
6
//! [`Vec<f16>`] and [`Vec<bf16>`] vectors. These traits provide efficient conversions and
7
//! reinterpret casting of larger buffers of floating point values, and are automatically included
8
//! in the [`prelude`][crate::prelude] module.
9
//!
10
//! This module is only available with the `std` or `alloc` feature.
11
12
use super::{bf16, f16, slice::HalfFloatSliceExt};
13
#[cfg(feature = "alloc")]
14
#[allow(unused_imports)]
15
use alloc::{vec, vec::Vec};
16
use core::mem;
17
18
/// Extensions to [`Vec<f16>`] and [`Vec<bf16>`] to support reinterpret operations.
19
///
20
/// This trait is sealed and cannot be implemented outside of this crate.
21
pub trait HalfFloatVecExt: private::SealedHalfFloatVec {
22
    /// Reinterprets a vector of [`struct@f16`]or [`bf16`] numbers as a vector of [`u16`] bits.
23
    ///
24
    /// This is a zero-copy operation. The reinterpreted vector has the same memory location as
25
    /// `self`.
26
    ///
27
    /// # Examples
28
    ///
29
    /// ```rust
30
    /// # use half::prelude::*;
31
    /// let float_buffer = vec![f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)];
32
    /// let int_buffer = float_buffer.reinterpret_into();
33
    ///
34
    /// assert_eq!(int_buffer, [f16::from_f32(1.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()]);
35
    /// ```
36
    #[must_use]
37
    fn reinterpret_into(self) -> Vec<u16>;
38
39
    /// Converts all of the elements of a `[f32]` slice into a new [`struct@f16`] or [`bf16`] vector.
40
    ///
41
    /// The conversion operation is vectorized over the slice, meaning the conversion may be more
42
    /// efficient than converting individual elements on some hardware that supports SIMD
43
    /// conversions. See [crate documentation][crate] for more information on hardware conversion
44
    /// support.
45
    ///
46
    /// # Examples
47
    /// ```rust
48
    /// # use half::prelude::*;
49
    /// let float_values = [1., 2., 3., 4.];
50
    /// let vec: Vec<f16> = Vec::from_f32_slice(&float_values);
51
    ///
52
    /// assert_eq!(vec, vec![f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.), f16::from_f32(4.)]);
53
    /// ```
54
    #[must_use]
55
    fn from_f32_slice(slice: &[f32]) -> Self;
56
57
    /// Converts all of the elements of a `[f64]` slice into a new [`struct@f16`] or [`bf16`] vector.
58
    ///
59
    /// The conversion operation is vectorized over the slice, meaning the conversion may be more
60
    /// efficient than converting individual elements on some hardware that supports SIMD
61
    /// conversions. See [crate documentation][crate] for more information on hardware conversion
62
    /// support.
63
    ///
64
    /// # Examples
65
    /// ```rust
66
    /// # use half::prelude::*;
67
    /// let float_values = [1., 2., 3., 4.];
68
    /// let vec: Vec<f16> = Vec::from_f64_slice(&float_values);
69
    ///
70
    /// assert_eq!(vec, vec![f16::from_f64(1.), f16::from_f64(2.), f16::from_f64(3.), f16::from_f64(4.)]);
71
    /// ```
72
    #[must_use]
73
    fn from_f64_slice(slice: &[f64]) -> Self;
74
}
75
76
/// Extensions to [`Vec<u16>`] to support reinterpret operations.
77
///
78
/// This trait is sealed and cannot be implemented outside of this crate.
79
pub trait HalfBitsVecExt: private::SealedHalfBitsVec {
80
    /// Reinterprets a vector of [`u16`] bits as a vector of [`struct@f16`] or [`bf16`] numbers.
81
    ///
82
    /// `H` is the type to cast to, and must be either the [`struct@f16`] or [`bf16`] type.
83
    ///
84
    /// This is a zero-copy operation. The reinterpreted vector has the same memory location as
85
    /// `self`.
86
    ///
87
    /// # Examples
88
    ///
89
    /// ```rust
90
    /// # use half::prelude::*;
91
    /// let int_buffer = vec![f16::from_f32(1.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()];
92
    /// let float_buffer = int_buffer.reinterpret_into::<f16>();
93
    ///
94
    /// assert_eq!(float_buffer, [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)]);
95
    /// ```
96
    #[must_use]
97
    fn reinterpret_into<H>(self) -> Vec<H>
98
    where
99
        H: crate::private::SealedHalf;
100
}
101
102
mod private {
103
    use crate::{bf16, f16};
104
    #[cfg(feature = "alloc")]
105
    #[allow(unused_imports)]
106
    use alloc::vec::Vec;
107
108
    pub trait SealedHalfFloatVec {}
109
    impl SealedHalfFloatVec for Vec<f16> {}
110
    impl SealedHalfFloatVec for Vec<bf16> {}
111
112
    pub trait SealedHalfBitsVec {}
113
    impl SealedHalfBitsVec for Vec<u16> {}
114
}
115
116
impl HalfFloatVecExt for Vec<f16> {
117
    #[inline]
118
0
    fn reinterpret_into(mut self) -> Vec<u16> {
119
0
        // An f16 array has same length and capacity as u16 array
120
0
        let length = self.len();
121
0
        let capacity = self.capacity();
122
0
123
0
        // Actually reinterpret the contents of the Vec<f16> as u16,
124
0
        // knowing that structs are represented as only their members in memory,
125
0
        // which is the u16 part of `f16(u16)`
126
0
        let pointer = self.as_mut_ptr() as *mut u16;
127
0
128
0
        // Prevent running a destructor on the old Vec<u16>, so the pointer won't be deleted
129
0
        mem::forget(self);
130
0
131
0
        // Finally construct a new Vec<f16> from the raw pointer
132
0
        // SAFETY: We are reconstructing full length and capacity of original vector,
133
0
        // using its original pointer, and the size of elements are identical.
134
0
        unsafe { Vec::from_raw_parts(pointer, length, capacity) }
135
0
    }
136
137
    #[allow(clippy::uninit_vec)]
138
0
    fn from_f32_slice(slice: &[f32]) -> Self {
139
0
        let mut vec = vec![f16::from_bits(0); slice.len()];
140
0
        vec.convert_from_f32_slice(slice);
141
0
        vec
142
0
    }
143
144
    #[allow(clippy::uninit_vec)]
145
0
    fn from_f64_slice(slice: &[f64]) -> Self {
146
0
        let mut vec = vec![f16::from_bits(0); slice.len()];
147
0
        vec.convert_from_f64_slice(slice);
148
0
        vec
149
0
    }
150
}
151
152
impl HalfFloatVecExt for Vec<bf16> {
153
    #[inline]
154
0
    fn reinterpret_into(mut self) -> Vec<u16> {
155
0
        // An f16 array has same length and capacity as u16 array
156
0
        let length = self.len();
157
0
        let capacity = self.capacity();
158
0
159
0
        // Actually reinterpret the contents of the Vec<f16> as u16,
160
0
        // knowing that structs are represented as only their members in memory,
161
0
        // which is the u16 part of `f16(u16)`
162
0
        let pointer = self.as_mut_ptr() as *mut u16;
163
0
164
0
        // Prevent running a destructor on the old Vec<u16>, so the pointer won't be deleted
165
0
        mem::forget(self);
166
0
167
0
        // Finally construct a new Vec<f16> from the raw pointer
168
0
        // SAFETY: We are reconstructing full length and capacity of original vector,
169
0
        // using its original pointer, and the size of elements are identical.
170
0
        unsafe { Vec::from_raw_parts(pointer, length, capacity) }
171
0
    }
172
173
    #[allow(clippy::uninit_vec)]
174
0
    fn from_f32_slice(slice: &[f32]) -> Self {
175
0
        let mut vec = vec![bf16::from_bits(0); slice.len()];
176
0
        vec.convert_from_f32_slice(slice);
177
0
        vec
178
0
    }
179
180
    #[allow(clippy::uninit_vec)]
181
0
    fn from_f64_slice(slice: &[f64]) -> Self {
182
0
        let mut vec = vec![bf16::from_bits(0); slice.len()];
183
0
        vec.convert_from_f64_slice(slice);
184
0
        vec
185
0
    }
186
}
187
188
impl HalfBitsVecExt for Vec<u16> {
189
    // This is safe because all traits are sealed
190
    #[inline]
191
0
    fn reinterpret_into<H>(mut self) -> Vec<H>
192
0
    where
193
0
        H: crate::private::SealedHalf,
194
0
    {
195
0
        // An f16 array has same length and capacity as u16 array
196
0
        let length = self.len();
197
0
        let capacity = self.capacity();
198
0
199
0
        // Actually reinterpret the contents of the Vec<u16> as f16,
200
0
        // knowing that structs are represented as only their members in memory,
201
0
        // which is the u16 part of `f16(u16)`
202
0
        let pointer = self.as_mut_ptr() as *mut H;
203
0
204
0
        // Prevent running a destructor on the old Vec<u16>, so the pointer won't be deleted
205
0
        mem::forget(self);
206
0
207
0
        // Finally construct a new Vec<f16> from the raw pointer
208
0
        // SAFETY: We are reconstructing full length and capacity of original vector,
209
0
        // using its original pointer, and the size of elements are identical.
210
0
        unsafe { Vec::from_raw_parts(pointer, length, capacity) }
211
0
    }
212
}
213
214
#[cfg(test)]
215
mod test {
216
    use super::{HalfBitsVecExt, HalfFloatVecExt};
217
    use crate::{bf16, f16};
218
    #[cfg(all(feature = "alloc", not(feature = "std")))]
219
    use alloc::vec;
220
221
    #[test]
222
    fn test_vec_conversions_f16() {
223
        let numbers = vec![f16::E, f16::PI, f16::EPSILON, f16::FRAC_1_SQRT_2];
224
        let bits = vec![
225
            f16::E.to_bits(),
226
            f16::PI.to_bits(),
227
            f16::EPSILON.to_bits(),
228
            f16::FRAC_1_SQRT_2.to_bits(),
229
        ];
230
        let bits_cloned = bits.clone();
231
232
        // Convert from bits to numbers
233
        let from_bits = bits.reinterpret_into::<f16>();
234
        assert_eq!(&from_bits[..], &numbers[..]);
235
236
        // Convert from numbers back to bits
237
        let to_bits = from_bits.reinterpret_into();
238
        assert_eq!(&to_bits[..], &bits_cloned[..]);
239
    }
240
241
    #[test]
242
    fn test_vec_conversions_bf16() {
243
        let numbers = vec![bf16::E, bf16::PI, bf16::EPSILON, bf16::FRAC_1_SQRT_2];
244
        let bits = vec![
245
            bf16::E.to_bits(),
246
            bf16::PI.to_bits(),
247
            bf16::EPSILON.to_bits(),
248
            bf16::FRAC_1_SQRT_2.to_bits(),
249
        ];
250
        let bits_cloned = bits.clone();
251
252
        // Convert from bits to numbers
253
        let from_bits = bits.reinterpret_into::<bf16>();
254
        assert_eq!(&from_bits[..], &numbers[..]);
255
256
        // Convert from numbers back to bits
257
        let to_bits = from_bits.reinterpret_into();
258
        assert_eq!(&to_bits[..], &bits_cloned[..]);
259
    }
260
}