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