1 //! Contains utility functions and traits to convert between slices of `u16` bits and `f16` or
2 //! `bf16` numbers.
3 //!
4 //! The utility [`HalfBitsSliceExt`] sealed extension trait is implemented for `[u16]` slices,
5 //! while the utility [`HalfFloatSliceExt`] sealed extension trait is implemented for both `[f16]`
6 //! and `[bf16]` slices. 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 //! [`HalfBitsSliceExt`]: trait.HalfBitsSliceExt.html
11 //! [`HalfFloatSliceExt`]: trait.HalfFloatSliceExt.html
12 //! [`prelude`]: ../prelude/index.html
13 
14 use crate::{bf16, binary16::convert, f16};
15 use core::slice;
16 
17 #[cfg(all(feature = "alloc", not(feature = "std")))]
18 use alloc::vec::Vec;
19 
20 /// Extensions to `[f16]` and `[bf16]` slices to support conversion and reinterpret operations.
21 ///
22 /// This trait is sealed and cannot be implemented outside of this crate.
23 pub trait HalfFloatSliceExt: private::SealedHalfFloatSlice {
24     /// Reinterpret a slice of [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
25     /// numbers as a slice of `u16` bits.
26     ///
27     /// This is a zero-copy operation. The reinterpreted slice has the same lifetime and memory
28     /// location as `self`.
29     ///
30     /// # Examples
31     ///
32     /// ```rust
33     /// # use half::prelude::*;
34     /// let float_buffer = [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)];
35     /// let int_buffer = float_buffer.reinterpret_cast();
36     ///
37     /// assert_eq!(int_buffer, [float_buffer[0].to_bits(), float_buffer[1].to_bits(), float_buffer[2].to_bits()]);
38     /// ```
reinterpret_cast(&self) -> &[u16]39     fn reinterpret_cast(&self) -> &[u16];
40 
41     /// Reinterpret a mutable slice of [`f16`](../struct.f16.html) or
42     /// [`bf16`](../struct.bf16.html) numbers as a mutable slice of `u16` bits.
43     ///
44     /// This is a zero-copy operation. The transmuted slice has the same lifetime as the original,
45     /// which prevents mutating `self` as long as the returned `&mut [u16]` is borrowed.
46     ///
47     /// # Examples
48     ///
49     /// ```rust
50     /// # use half::prelude::*;
51     /// let mut float_buffer = [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)];
52     ///
53     /// {
54     ///     let int_buffer = float_buffer.reinterpret_cast_mut();
55     ///
56     ///     assert_eq!(int_buffer, [f16::from_f32(1.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()]);
57     ///
58     ///     // Mutating the u16 slice will mutating the original
59     ///     int_buffer[0] = 0;
60     /// }
61     ///
62     /// // Note that we need to drop int_buffer before using float_buffer again or we will get a borrow error.
63     /// assert_eq!(float_buffer, [f16::from_f32(0.), f16::from_f32(2.), f16::from_f32(3.)]);
64     /// ```
reinterpret_cast_mut(&mut self) -> &mut [u16]65     fn reinterpret_cast_mut(&mut self) -> &mut [u16];
66 
67     /// Convert all of the elements of a `[f32]` slice into [`f16`](../struct.f16.html) or
68     /// [`bf16`](../struct.bf16.html) values in `self`.
69     ///
70     /// The length of `src` must be the same as `self`.
71     ///
72     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
73     /// efficient than converting individual elements on some hardware that supports SIMD
74     /// conversions. See [crate documentation](../index.html) for more information on hardware
75     /// conversion support.
76     ///
77     /// # Panics
78     ///
79     /// This function will panic if the two slices have different lengths.
80     ///
81     /// # Examples
82     /// ```rust
83     /// # use half::prelude::*;
84     /// // Initialize an empty buffer
85     /// let mut buffer = [0u16; 4];
86     /// let buffer = buffer.reinterpret_cast_mut::<f16>();
87     ///
88     /// let float_values = [1., 2., 3., 4.];
89     ///
90     /// // Now convert
91     /// buffer.convert_from_f32_slice(&float_values);
92     ///
93     /// assert_eq!(buffer, [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.), f16::from_f32(4.)]);
94     /// ```
convert_from_f32_slice(&mut self, src: &[f32])95     fn convert_from_f32_slice(&mut self, src: &[f32]);
96 
97     /// Convert all of the elements of a `[f64]` slice into [`f16`](../struct.f16.html) or
98     /// [`bf16`](../struct.bf16.html) values in `self`.
99     ///
100     /// The length of `src` must be the same as `self`.
101     ///
102     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
103     /// efficient than converting individual elements on some hardware that supports SIMD
104     /// conversions. See [crate documentation](../index.html) for more information on hardware
105     /// conversion support.
106     ///
107     /// # Panics
108     ///
109     /// This function will panic if the two slices have different lengths.
110     ///
111     /// # Examples
112     /// ```rust
113     /// # use half::prelude::*;
114     /// // Initialize an empty buffer
115     /// let mut buffer = [0u16; 4];
116     /// let buffer = buffer.reinterpret_cast_mut::<f16>();
117     ///
118     /// let float_values = [1., 2., 3., 4.];
119     ///
120     /// // Now convert
121     /// buffer.convert_from_f64_slice(&float_values);
122     ///
123     /// assert_eq!(buffer, [f16::from_f64(1.), f16::from_f64(2.), f16::from_f64(3.), f16::from_f64(4.)]);
124     /// ```
convert_from_f64_slice(&mut self, src: &[f64])125     fn convert_from_f64_slice(&mut self, src: &[f64]);
126 
127     /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
128     /// elements of `self` into `f32` values in `dst`.
129     ///
130     /// The length of `src` must be the same as `self`.
131     ///
132     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
133     /// efficient than converting individual elements on some hardware that supports SIMD
134     /// conversions. See [crate documentation](../index.html) for more information on hardware
135     /// conversion support.
136     ///
137     /// # Panics
138     ///
139     /// This function will panic if the two slices have different lengths.
140     ///
141     /// # Examples
142     /// ```rust
143     /// # use half::prelude::*;
144     /// // Initialize an empty buffer
145     /// let mut buffer = [0f32; 4];
146     ///
147     /// let half_values = [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.), f16::from_f32(4.)];
148     ///
149     /// // Now convert
150     /// half_values.convert_to_f32_slice(&mut buffer);
151     ///
152     /// assert_eq!(buffer, [1., 2., 3., 4.]);
153     /// ```
convert_to_f32_slice(&self, dst: &mut [f32])154     fn convert_to_f32_slice(&self, dst: &mut [f32]);
155 
156     /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
157     /// elements of `self` into `f64` values in `dst`.
158     ///
159     /// The length of `src` must be the same as `self`.
160     ///
161     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
162     /// efficient than converting individual elements on some hardware that supports SIMD
163     /// conversions. See [crate documentation](../index.html) for more information on hardware
164     /// conversion support.
165     ///
166     /// # Panics
167     ///
168     /// This function will panic if the two slices have different lengths.
169     ///
170     /// # Examples
171     /// ```rust
172     /// # use half::prelude::*;
173     /// // Initialize an empty buffer
174     /// let mut buffer = [0f64; 4];
175     ///
176     /// let half_values = [f16::from_f64(1.), f16::from_f64(2.), f16::from_f64(3.), f16::from_f64(4.)];
177     ///
178     /// // Now convert
179     /// half_values.convert_to_f64_slice(&mut buffer);
180     ///
181     /// assert_eq!(buffer, [1., 2., 3., 4.]);
182     /// ```
convert_to_f64_slice(&self, dst: &mut [f64])183     fn convert_to_f64_slice(&self, dst: &mut [f64]);
184 
185     // Because trait is sealed, we can get away with different interfaces between features
186 
187     #[cfg(any(feature = "alloc", feature = "std"))]
188     /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
189     /// elements of `self` into `f32` values in a new vector.
190     ///
191     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
192     /// efficient than converting individual elements on some hardware that supports SIMD
193     /// conversions. See [crate documentation](../index.html) for more information on hardware
194     /// conversion support.
195     ///
196     /// This method is only available with the `std` or `alloc` feature.
197     ///
198     /// # Examples
199     /// ```rust
200     /// # use half::prelude::*;
201     /// let half_values = [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.), f16::from_f32(4.)];
202     /// let vec = half_values.to_f32_vec();
203     ///
204     /// assert_eq!(vec, vec![1., 2., 3., 4.]);
205     /// ```
to_f32_vec(&self) -> Vec<f32>206     fn to_f32_vec(&self) -> Vec<f32>;
207 
208     /// Convert all of the [`f16`](../struct.f16.html) or [`bf16`](../struct.bf16.html)
209     /// elements of `self` into `f64` values in a new vector.
210     ///
211     /// The conversion operation is vectorized over the slice, meaning the conversion may be more
212     /// efficient than converting individual elements on some hardware that supports SIMD
213     /// conversions. See [crate documentation](../index.html) for more information on hardware
214     /// conversion support.
215     ///
216     /// This method is only available with the `std` or `alloc` feature.
217     ///
218     /// # Examples
219     /// ```rust
220     /// # use half::prelude::*;
221     /// let half_values = [f16::from_f64(1.), f16::from_f64(2.), f16::from_f64(3.), f16::from_f64(4.)];
222     /// let vec = half_values.to_f64_vec();
223     ///
224     /// assert_eq!(vec, vec![1., 2., 3., 4.]);
225     /// ```
226     #[cfg(any(feature = "alloc", feature = "std"))]
to_f64_vec(&self) -> Vec<f64>227     fn to_f64_vec(&self) -> Vec<f64>;
228 }
229 
230 /// Extensions to `[u16]` slices to support reinterpret operations.
231 ///
232 /// This trait is sealed and cannot be implemented outside of this crate.
233 pub trait HalfBitsSliceExt: private::SealedHalfBitsSlice {
234     /// Reinterpret a slice of `u16` bits as a slice of [`f16`](../struct.f16.html) or
235     /// [`bf16`](../struct.bf16.html) numbers.
236     ///
237     /// `H` is the type to cast to, and must be either the [`f16`](../struct.f16.html) or
238     /// [`bf16`](../struct.bf16.html) type.
239     ///
240     /// This is a zero-copy operation. The reinterpreted slice has the same lifetime and memory
241     /// location as `self`.
242     ///
243     /// # Examples
244     ///
245     /// ```rust
246     /// # use half::prelude::*;
247     /// let int_buffer = [f16::from_f32(1.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()];
248     /// let float_buffer: &[f16] = int_buffer.reinterpret_cast();
249     ///
250     /// assert_eq!(float_buffer, [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)]);
251     ///
252     /// // You may have to specify the cast type directly if the compiler can't infer the type.
253     /// // The following is also valid in Rust.
254     /// let typed_buffer = int_buffer.reinterpret_cast::<f16>();
255     /// ```
reinterpret_cast<H>(&self) -> &[H] where H: crate::private::SealedHalf256     fn reinterpret_cast<H>(&self) -> &[H]
257     where
258         H: crate::private::SealedHalf;
259 
260     /// Reinterpret a mutable slice of `u16` bits as a mutable slice of [`f16`](../struct.f16.html)
261     /// or [`bf16`](../struct.bf16.html)  numbers.
262     ///
263     /// `H` is the type to cast to, and must be either the [`f16`](../struct.f16.html) or
264     /// [`bf16`](../struct.bf16.html) type.
265     ///
266     /// This is a zero-copy operation. The transmuted slice has the same lifetime as the original,
267     /// which prevents mutating `self` as long as the returned `&mut [f16]` is borrowed.
268     ///
269     /// # Examples
270     ///
271     /// ```rust
272     /// # use half::prelude::*;
273     /// let mut int_buffer = [f16::from_f32(1.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()];
274     ///
275     /// {
276     ///     let float_buffer: &mut [f16] = int_buffer.reinterpret_cast_mut();
277     ///
278     ///     assert_eq!(float_buffer, [f16::from_f32(1.), f16::from_f32(2.), f16::from_f32(3.)]);
279     ///
280     ///     // Mutating the f16 slice will mutating the original
281     ///     float_buffer[0] = f16::from_f32(0.);
282     /// }
283     ///
284     /// // Note that we need to drop float_buffer before using int_buffer again or we will get a borrow error.
285     /// assert_eq!(int_buffer, [f16::from_f32(0.).to_bits(), f16::from_f32(2.).to_bits(), f16::from_f32(3.).to_bits()]);
286     ///
287     /// // You may have to specify the cast type directly if the compiler can't infer the type.
288     /// // The following is also valid in Rust.
289     /// let typed_buffer = int_buffer.reinterpret_cast_mut::<f16>();
290     /// ```
reinterpret_cast_mut<H>(&mut self) -> &mut [H] where H: crate::private::SealedHalf291     fn reinterpret_cast_mut<H>(&mut self) -> &mut [H]
292     where
293         H: crate::private::SealedHalf;
294 }
295 
296 mod private {
297     use crate::{bf16, f16};
298 
299     pub trait SealedHalfFloatSlice {}
300     impl SealedHalfFloatSlice for [f16] {}
301     impl SealedHalfFloatSlice for [bf16] {}
302 
303     pub trait SealedHalfBitsSlice {}
304     impl SealedHalfBitsSlice for [u16] {}
305 }
306 
307 impl HalfFloatSliceExt for [f16] {
308     #[inline]
reinterpret_cast(&self) -> &[u16]309     fn reinterpret_cast(&self) -> &[u16] {
310         let pointer = self.as_ptr() as *const u16;
311         let length = self.len();
312         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
313         // and the size of elements are identical
314         unsafe { slice::from_raw_parts(pointer, length) }
315     }
316 
317     #[inline]
reinterpret_cast_mut(&mut self) -> &mut [u16]318     fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
319         let pointer = self.as_ptr() as *mut u16;
320         let length = self.len();
321         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
322         // and the size of elements are identical
323         unsafe { slice::from_raw_parts_mut(pointer, length) }
324     }
325 
convert_from_f32_slice(&mut self, src: &[f32])326     fn convert_from_f32_slice(&mut self, src: &[f32]) {
327         assert_eq!(
328             self.len(),
329             src.len(),
330             "destination and source slices have different lengths"
331         );
332 
333         let mut chunks = src.chunks_exact(4);
334         let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
335         for chunk in &mut chunks {
336             let vec = convert::f32x4_to_f16x4(chunk);
337             let dst_idx = chunk_count * 4;
338             self[dst_idx..dst_idx + 4].copy_from_slice(vec.reinterpret_cast());
339             chunk_count += 1;
340         }
341 
342         // Process remainder
343         if !chunks.remainder().is_empty() {
344             let mut buf = [0f32; 4];
345             buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder());
346             let vec = convert::f32x4_to_f16x4(&buf);
347             let dst_idx = chunk_count * 4;
348             self[dst_idx..dst_idx + chunks.remainder().len()]
349                 .copy_from_slice(vec[..chunks.remainder().len()].reinterpret_cast());
350         }
351     }
352 
convert_from_f64_slice(&mut self, src: &[f64])353     fn convert_from_f64_slice(&mut self, src: &[f64]) {
354         assert_eq!(
355             self.len(),
356             src.len(),
357             "destination and source slices have different lengths"
358         );
359 
360         let mut chunks = src.chunks_exact(4);
361         let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
362         for chunk in &mut chunks {
363             let vec = convert::f64x4_to_f16x4(chunk);
364             let dst_idx = chunk_count * 4;
365             self[dst_idx..dst_idx + 4].copy_from_slice(vec.reinterpret_cast());
366             chunk_count += 1;
367         }
368 
369         // Process remainder
370         if !chunks.remainder().is_empty() {
371             let mut buf = [0f64; 4];
372             buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder());
373             let vec = convert::f64x4_to_f16x4(&buf);
374             let dst_idx = chunk_count * 4;
375             self[dst_idx..dst_idx + chunks.remainder().len()]
376                 .copy_from_slice(vec[..chunks.remainder().len()].reinterpret_cast());
377         }
378     }
379 
convert_to_f32_slice(&self, dst: &mut [f32])380     fn convert_to_f32_slice(&self, dst: &mut [f32]) {
381         assert_eq!(
382             self.len(),
383             dst.len(),
384             "destination and source slices have different lengths"
385         );
386 
387         let mut chunks = self.chunks_exact(4);
388         let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
389         for chunk in &mut chunks {
390             let vec = convert::f16x4_to_f32x4(chunk.reinterpret_cast());
391             let dst_idx = chunk_count * 4;
392             dst[dst_idx..dst_idx + 4].copy_from_slice(&vec);
393             chunk_count += 1;
394         }
395 
396         // Process remainder
397         if !chunks.remainder().is_empty() {
398             let mut buf = [0u16; 4];
399             buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder().reinterpret_cast());
400             let vec = convert::f16x4_to_f32x4(&buf);
401             let dst_idx = chunk_count * 4;
402             dst[dst_idx..dst_idx + chunks.remainder().len()]
403                 .copy_from_slice(&vec[..chunks.remainder().len()]);
404         }
405     }
406 
convert_to_f64_slice(&self, dst: &mut [f64])407     fn convert_to_f64_slice(&self, dst: &mut [f64]) {
408         assert_eq!(
409             self.len(),
410             dst.len(),
411             "destination and source slices have different lengths"
412         );
413 
414         let mut chunks = self.chunks_exact(4);
415         let mut chunk_count = 0usize; // Not using .enumerate() because we need this value for remainder
416         for chunk in &mut chunks {
417             let vec = convert::f16x4_to_f64x4(chunk.reinterpret_cast());
418             let dst_idx = chunk_count * 4;
419             dst[dst_idx..dst_idx + 4].copy_from_slice(&vec);
420             chunk_count += 1;
421         }
422 
423         // Process remainder
424         if !chunks.remainder().is_empty() {
425             let mut buf = [0u16; 4];
426             buf[..chunks.remainder().len()].copy_from_slice(chunks.remainder().reinterpret_cast());
427             let vec = convert::f16x4_to_f64x4(&buf);
428             let dst_idx = chunk_count * 4;
429             dst[dst_idx..dst_idx + chunks.remainder().len()]
430                 .copy_from_slice(&vec[..chunks.remainder().len()]);
431         }
432     }
433 
434     #[cfg(any(feature = "alloc", feature = "std"))]
435     #[inline]
to_f32_vec(&self) -> Vec<f32>436     fn to_f32_vec(&self) -> Vec<f32> {
437         let mut vec = Vec::with_capacity(self.len());
438         // SAFETY: convert will initialize every value in the vector without reading them,
439         // so this is safe to do instead of double initialize from resize, and we're setting it to
440         // same value as capacity.
441         unsafe { vec.set_len(self.len()) };
442         self.convert_to_f32_slice(&mut vec);
443         vec
444     }
445 
446     #[cfg(any(feature = "alloc", feature = "std"))]
447     #[inline]
to_f64_vec(&self) -> Vec<f64>448     fn to_f64_vec(&self) -> Vec<f64> {
449         let mut vec = Vec::with_capacity(self.len());
450         // SAFETY: convert will initialize every value in the vector without reading them,
451         // so this is safe to do instead of double initialize from resize, and we're setting it to
452         // same value as capacity.
453         unsafe { vec.set_len(self.len()) };
454         self.convert_to_f64_slice(&mut vec);
455         vec
456     }
457 }
458 
459 impl HalfFloatSliceExt for [bf16] {
460     #[inline]
reinterpret_cast(&self) -> &[u16]461     fn reinterpret_cast(&self) -> &[u16] {
462         let pointer = self.as_ptr() as *const u16;
463         let length = self.len();
464         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
465         // and the size of elements are identical
466         unsafe { slice::from_raw_parts(pointer, length) }
467     }
468 
469     #[inline]
reinterpret_cast_mut(&mut self) -> &mut [u16]470     fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
471         let pointer = self.as_ptr() as *mut u16;
472         let length = self.len();
473         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
474         // and the size of elements are identical
475         unsafe { slice::from_raw_parts_mut(pointer, length) }
476     }
477 
convert_from_f32_slice(&mut self, src: &[f32])478     fn convert_from_f32_slice(&mut self, src: &[f32]) {
479         assert_eq!(
480             self.len(),
481             src.len(),
482             "destination and source slices have different lengths"
483         );
484 
485         // Just use regular loop here until there's any bf16 SIMD support.
486         for (i, f) in src.iter().enumerate() {
487             self[i] = bf16::from_f32(*f);
488         }
489     }
490 
convert_from_f64_slice(&mut self, src: &[f64])491     fn convert_from_f64_slice(&mut self, src: &[f64]) {
492         assert_eq!(
493             self.len(),
494             src.len(),
495             "destination and source slices have different lengths"
496         );
497 
498         // Just use regular loop here until there's any bf16 SIMD support.
499         for (i, f) in src.iter().enumerate() {
500             self[i] = bf16::from_f64(*f);
501         }
502     }
503 
convert_to_f32_slice(&self, dst: &mut [f32])504     fn convert_to_f32_slice(&self, dst: &mut [f32]) {
505         assert_eq!(
506             self.len(),
507             dst.len(),
508             "destination and source slices have different lengths"
509         );
510 
511         // Just use regular loop here until there's any bf16 SIMD support.
512         for (i, f) in self.iter().enumerate() {
513             dst[i] = f.to_f32();
514         }
515     }
516 
convert_to_f64_slice(&self, dst: &mut [f64])517     fn convert_to_f64_slice(&self, dst: &mut [f64]) {
518         assert_eq!(
519             self.len(),
520             dst.len(),
521             "destination and source slices have different lengths"
522         );
523 
524         // Just use regular loop here until there's any bf16 SIMD support.
525         for (i, f) in self.iter().enumerate() {
526             dst[i] = f.to_f64();
527         }
528     }
529 
530     #[cfg(any(feature = "alloc", feature = "std"))]
531     #[inline]
to_f32_vec(&self) -> Vec<f32>532     fn to_f32_vec(&self) -> Vec<f32> {
533         let mut vec = Vec::with_capacity(self.len());
534         // SAFETY: convert will initialize every value in the vector without reading them,
535         // so this is safe to do instead of double initialize from resize, and we're setting it to
536         // same value as capacity.
537         unsafe { vec.set_len(self.len()) };
538         self.convert_to_f32_slice(&mut vec);
539         vec
540     }
541 
542     #[cfg(any(feature = "alloc", feature = "std"))]
543     #[inline]
to_f64_vec(&self) -> Vec<f64>544     fn to_f64_vec(&self) -> Vec<f64> {
545         let mut vec = Vec::with_capacity(self.len());
546         // SAFETY: convert will initialize every value in the vector without reading them,
547         // so this is safe to do instead of double initialize from resize, and we're setting it to
548         // same value as capacity.
549         unsafe { vec.set_len(self.len()) };
550         self.convert_to_f64_slice(&mut vec);
551         vec
552     }
553 }
554 
555 impl HalfBitsSliceExt for [u16] {
556     // Since we sealed all the traits involved, these are safe.
557     #[inline]
reinterpret_cast<H>(&self) -> &[H] where H: crate::private::SealedHalf,558     fn reinterpret_cast<H>(&self) -> &[H]
559     where
560         H: crate::private::SealedHalf,
561     {
562         let pointer = self.as_ptr() as *const H;
563         let length = self.len();
564         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
565         // and the size of elements are identical
566         unsafe { slice::from_raw_parts(pointer, length) }
567     }
568 
569     #[inline]
reinterpret_cast_mut<H>(&mut self) -> &mut [H] where H: crate::private::SealedHalf,570     fn reinterpret_cast_mut<H>(&mut self) -> &mut [H]
571     where
572         H: crate::private::SealedHalf,
573     {
574         let pointer = self.as_mut_ptr() as *mut H;
575         let length = self.len();
576         // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
577         // and the size of elements are identical
578         unsafe { slice::from_raw_parts_mut(pointer, length) }
579     }
580 }
581 
582 /// Reinterpret a mutable slice of `u16` bits as a mutable slice of [`f16`](../struct.f16.html)
583 /// numbers.
584 ///
585 /// The transmuted slice has the same life time as the original, which prevents mutating the borrowed
586 /// `mut [u16]` argument as long as the returned `mut [f16]` is borrowed.
587 #[deprecated(
588     since = "1.4.0",
589     note = "use [`HalfBitsSliceExt::reinterpret_cast_mut`](trait.HalfBitsSliceExt.html#tymethod.reinterpret_cast_mut) instead"
590 )]
591 #[inline]
from_bits_mut(bits: &mut [u16]) -> &mut [f16]592 pub fn from_bits_mut(bits: &mut [u16]) -> &mut [f16] {
593     bits.reinterpret_cast_mut()
594 }
595 
596 /// Reinterpret a mutable slice of [`f16`](../struct.f16.html) numbers as a mutable slice of `u16`
597 /// bits.
598 ///
599 ///The transmuted slice has the same life time as the original, which prevents mutating the
600 /// borrowed `mut [f16]` argument as long as the returned `mut [u16]` is borrowed.
601 #[deprecated(
602     since = "1.4.0",
603     note = "use [`HalfFloatSliceExt::reinterpret_cast_mut`](trait.HalfFloatSliceExt.html#tymethod.reinterpret_cast_mut) instead"
604 )]
605 #[inline]
to_bits_mut(bits: &mut [f16]) -> &mut [u16]606 pub fn to_bits_mut(bits: &mut [f16]) -> &mut [u16] {
607     bits.reinterpret_cast_mut()
608 }
609 
610 /// Reinterpret a slice of `u16` bits as a slice of [`f16`](../struct.f16.html) numbers.
611 ///
612 /// The transmuted slice has the same life time as the original.
613 #[deprecated(
614     since = "1.4.0",
615     note = "use [`HalfBitsSliceExt::reinterpret_cast`](trait.HalfBitsSliceExt.html#tymethod.reinterpret_cast) instead"
616 )]
617 #[inline]
from_bits(bits: &[u16]) -> &[f16]618 pub fn from_bits(bits: &[u16]) -> &[f16] {
619     bits.reinterpret_cast()
620 }
621 
622 /// Reinterpret a slice of [`f16`](../struct.f16.html) numbers as a slice of `u16` bits.
623 ///
624 /// The transmuted slice has the same life time as the original.
625 #[deprecated(
626     since = "1.4.0",
627     note = "use [`HalfFloatSliceExt::reinterpret_cast`](trait.HalfFloatSliceExt.html#tymethod.reinterpret_cast) instead"
628 )]
629 #[inline]
to_bits(bits: &[f16]) -> &[u16]630 pub fn to_bits(bits: &[f16]) -> &[u16] {
631     bits.reinterpret_cast()
632 }
633 
634 #[cfg(test)]
635 mod test {
636     use super::{HalfBitsSliceExt, HalfFloatSliceExt};
637     use crate::{bf16, f16};
638 
639     #[test]
test_slice_conversions_f16()640     fn test_slice_conversions_f16() {
641         let bits = &[
642             f16::E.to_bits(),
643             f16::PI.to_bits(),
644             f16::EPSILON.to_bits(),
645             f16::FRAC_1_SQRT_2.to_bits(),
646         ];
647         let numbers = &[f16::E, f16::PI, f16::EPSILON, f16::FRAC_1_SQRT_2];
648 
649         // Convert from bits to numbers
650         let from_bits = bits.reinterpret_cast::<f16>();
651         assert_eq!(from_bits, numbers);
652 
653         // Convert from numbers back to bits
654         let to_bits = from_bits.reinterpret_cast();
655         assert_eq!(to_bits, bits);
656     }
657 
658     #[test]
test_mutablility_f16()659     fn test_mutablility_f16() {
660         let mut bits_array = [f16::PI.to_bits()];
661         let bits = &mut bits_array[..];
662 
663         {
664             // would not compile without these braces
665             // TODO: add automated test to check that it does not compile without braces
666             let numbers = bits.reinterpret_cast_mut();
667             numbers[0] = f16::E;
668         }
669 
670         assert_eq!(bits, &[f16::E.to_bits()]);
671 
672         bits[0] = f16::LN_2.to_bits();
673         assert_eq!(bits, &[f16::LN_2.to_bits()]);
674     }
675 
676     #[test]
test_slice_conversions_bf16()677     fn test_slice_conversions_bf16() {
678         let bits = &[
679             bf16::E.to_bits(),
680             bf16::PI.to_bits(),
681             bf16::EPSILON.to_bits(),
682             bf16::FRAC_1_SQRT_2.to_bits(),
683         ];
684         let numbers = &[bf16::E, bf16::PI, bf16::EPSILON, bf16::FRAC_1_SQRT_2];
685 
686         // Convert from bits to numbers
687         let from_bits = bits.reinterpret_cast::<bf16>();
688         assert_eq!(from_bits, numbers);
689 
690         // Convert from numbers back to bits
691         let to_bits = from_bits.reinterpret_cast();
692         assert_eq!(to_bits, bits);
693     }
694 
695     #[test]
test_mutablility_bf16()696     fn test_mutablility_bf16() {
697         let mut bits_array = [bf16::PI.to_bits()];
698         let bits = &mut bits_array[..];
699 
700         {
701             // would not compile without these braces
702             // TODO: add automated test to check that it does not compile without braces
703             let numbers = bits.reinterpret_cast_mut();
704             numbers[0] = bf16::E;
705         }
706 
707         assert_eq!(bits, &[bf16::E.to_bits()]);
708 
709         bits[0] = bf16::LN_2.to_bits();
710         assert_eq!(bits, &[bf16::LN_2.to_bits()]);
711     }
712 
713     #[test]
slice_convert_f16_f32()714     fn slice_convert_f16_f32() {
715         // Exact chunks
716         let vf32 = [1., 2., 3., 4., 5., 6., 7., 8.];
717         let vf16 = [
718             f16::from_f32(1.),
719             f16::from_f32(2.),
720             f16::from_f32(3.),
721             f16::from_f32(4.),
722             f16::from_f32(5.),
723             f16::from_f32(6.),
724             f16::from_f32(7.),
725             f16::from_f32(8.),
726         ];
727         let mut buf32 = vf32;
728         let mut buf16 = vf16;
729 
730         vf16.convert_to_f32_slice(&mut buf32);
731         assert_eq!(&vf32, &buf32);
732 
733         buf16.convert_from_f32_slice(&vf32);
734         assert_eq!(&vf16, &buf16);
735 
736         // Partial with chunks
737         let vf32 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
738         let vf16 = [
739             f16::from_f32(1.),
740             f16::from_f32(2.),
741             f16::from_f32(3.),
742             f16::from_f32(4.),
743             f16::from_f32(5.),
744             f16::from_f32(6.),
745             f16::from_f32(7.),
746             f16::from_f32(8.),
747             f16::from_f32(9.),
748         ];
749         let mut buf32 = vf32;
750         let mut buf16 = vf16;
751 
752         vf16.convert_to_f32_slice(&mut buf32);
753         assert_eq!(&vf32, &buf32);
754 
755         buf16.convert_from_f32_slice(&vf32);
756         assert_eq!(&vf16, &buf16);
757 
758         // Partial with chunks
759         let vf32 = [1., 2.];
760         let vf16 = [f16::from_f32(1.), f16::from_f32(2.)];
761         let mut buf32 = vf32;
762         let mut buf16 = vf16;
763 
764         vf16.convert_to_f32_slice(&mut buf32);
765         assert_eq!(&vf32, &buf32);
766 
767         buf16.convert_from_f32_slice(&vf32);
768         assert_eq!(&vf16, &buf16);
769     }
770 
771     #[test]
slice_convert_bf16_f32()772     fn slice_convert_bf16_f32() {
773         // Exact chunks
774         let vf32 = [1., 2., 3., 4., 5., 6., 7., 8.];
775         let vf16 = [
776             bf16::from_f32(1.),
777             bf16::from_f32(2.),
778             bf16::from_f32(3.),
779             bf16::from_f32(4.),
780             bf16::from_f32(5.),
781             bf16::from_f32(6.),
782             bf16::from_f32(7.),
783             bf16::from_f32(8.),
784         ];
785         let mut buf32 = vf32;
786         let mut buf16 = vf16;
787 
788         vf16.convert_to_f32_slice(&mut buf32);
789         assert_eq!(&vf32, &buf32);
790 
791         buf16.convert_from_f32_slice(&vf32);
792         assert_eq!(&vf16, &buf16);
793 
794         // Partial with chunks
795         let vf32 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
796         let vf16 = [
797             bf16::from_f32(1.),
798             bf16::from_f32(2.),
799             bf16::from_f32(3.),
800             bf16::from_f32(4.),
801             bf16::from_f32(5.),
802             bf16::from_f32(6.),
803             bf16::from_f32(7.),
804             bf16::from_f32(8.),
805             bf16::from_f32(9.),
806         ];
807         let mut buf32 = vf32;
808         let mut buf16 = vf16;
809 
810         vf16.convert_to_f32_slice(&mut buf32);
811         assert_eq!(&vf32, &buf32);
812 
813         buf16.convert_from_f32_slice(&vf32);
814         assert_eq!(&vf16, &buf16);
815 
816         // Partial with chunks
817         let vf32 = [1., 2.];
818         let vf16 = [bf16::from_f32(1.), bf16::from_f32(2.)];
819         let mut buf32 = vf32;
820         let mut buf16 = vf16;
821 
822         vf16.convert_to_f32_slice(&mut buf32);
823         assert_eq!(&vf32, &buf32);
824 
825         buf16.convert_from_f32_slice(&vf32);
826         assert_eq!(&vf16, &buf16);
827     }
828 
829     #[test]
slice_convert_f16_f64()830     fn slice_convert_f16_f64() {
831         // Exact chunks
832         let vf64 = [1., 2., 3., 4., 5., 6., 7., 8.];
833         let vf16 = [
834             f16::from_f64(1.),
835             f16::from_f64(2.),
836             f16::from_f64(3.),
837             f16::from_f64(4.),
838             f16::from_f64(5.),
839             f16::from_f64(6.),
840             f16::from_f64(7.),
841             f16::from_f64(8.),
842         ];
843         let mut buf64 = vf64;
844         let mut buf16 = vf16;
845 
846         vf16.convert_to_f64_slice(&mut buf64);
847         assert_eq!(&vf64, &buf64);
848 
849         buf16.convert_from_f64_slice(&vf64);
850         assert_eq!(&vf16, &buf16);
851 
852         // Partial with chunks
853         let vf64 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
854         let vf16 = [
855             f16::from_f64(1.),
856             f16::from_f64(2.),
857             f16::from_f64(3.),
858             f16::from_f64(4.),
859             f16::from_f64(5.),
860             f16::from_f64(6.),
861             f16::from_f64(7.),
862             f16::from_f64(8.),
863             f16::from_f64(9.),
864         ];
865         let mut buf64 = vf64;
866         let mut buf16 = vf16;
867 
868         vf16.convert_to_f64_slice(&mut buf64);
869         assert_eq!(&vf64, &buf64);
870 
871         buf16.convert_from_f64_slice(&vf64);
872         assert_eq!(&vf16, &buf16);
873 
874         // Partial with chunks
875         let vf64 = [1., 2.];
876         let vf16 = [f16::from_f64(1.), f16::from_f64(2.)];
877         let mut buf64 = vf64;
878         let mut buf16 = vf16;
879 
880         vf16.convert_to_f64_slice(&mut buf64);
881         assert_eq!(&vf64, &buf64);
882 
883         buf16.convert_from_f64_slice(&vf64);
884         assert_eq!(&vf16, &buf16);
885     }
886 
887     #[test]
slice_convert_bf16_f64()888     fn slice_convert_bf16_f64() {
889         // Exact chunks
890         let vf64 = [1., 2., 3., 4., 5., 6., 7., 8.];
891         let vf16 = [
892             bf16::from_f64(1.),
893             bf16::from_f64(2.),
894             bf16::from_f64(3.),
895             bf16::from_f64(4.),
896             bf16::from_f64(5.),
897             bf16::from_f64(6.),
898             bf16::from_f64(7.),
899             bf16::from_f64(8.),
900         ];
901         let mut buf64 = vf64;
902         let mut buf16 = vf16;
903 
904         vf16.convert_to_f64_slice(&mut buf64);
905         assert_eq!(&vf64, &buf64);
906 
907         buf16.convert_from_f64_slice(&vf64);
908         assert_eq!(&vf16, &buf16);
909 
910         // Partial with chunks
911         let vf64 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
912         let vf16 = [
913             bf16::from_f64(1.),
914             bf16::from_f64(2.),
915             bf16::from_f64(3.),
916             bf16::from_f64(4.),
917             bf16::from_f64(5.),
918             bf16::from_f64(6.),
919             bf16::from_f64(7.),
920             bf16::from_f64(8.),
921             bf16::from_f64(9.),
922         ];
923         let mut buf64 = vf64;
924         let mut buf16 = vf16;
925 
926         vf16.convert_to_f64_slice(&mut buf64);
927         assert_eq!(&vf64, &buf64);
928 
929         buf16.convert_from_f64_slice(&vf64);
930         assert_eq!(&vf16, &buf16);
931 
932         // Partial with chunks
933         let vf64 = [1., 2.];
934         let vf16 = [bf16::from_f64(1.), bf16::from_f64(2.)];
935         let mut buf64 = vf64;
936         let mut buf16 = vf16;
937 
938         vf16.convert_to_f64_slice(&mut buf64);
939         assert_eq!(&vf64, &buf64);
940 
941         buf16.convert_from_f64_slice(&vf64);
942         assert_eq!(&vf16, &buf16);
943     }
944 
945     #[test]
946     #[should_panic]
convert_from_f32_slice_len_mismatch_panics()947     fn convert_from_f32_slice_len_mismatch_panics() {
948         let mut slice1 = [f16::ZERO; 3];
949         let slice2 = [0f32; 4];
950         slice1.convert_from_f32_slice(&slice2);
951     }
952 
953     #[test]
954     #[should_panic]
convert_from_f64_slice_len_mismatch_panics()955     fn convert_from_f64_slice_len_mismatch_panics() {
956         let mut slice1 = [f16::ZERO; 3];
957         let slice2 = [0f64; 4];
958         slice1.convert_from_f64_slice(&slice2);
959     }
960 
961     #[test]
962     #[should_panic]
convert_to_f32_slice_len_mismatch_panics()963     fn convert_to_f32_slice_len_mismatch_panics() {
964         let slice1 = [f16::ZERO; 3];
965         let mut slice2 = [0f32; 4];
966         slice1.convert_to_f32_slice(&mut slice2);
967     }
968 
969     #[test]
970     #[should_panic]
convert_to_f64_slice_len_mismatch_panics()971     fn convert_to_f64_slice_len_mismatch_panics() {
972         let slice1 = [f16::ZERO; 3];
973         let mut slice2 = [0f64; 4];
974         slice1.convert_to_f64_slice(&mut slice2);
975     }
976 }
977