Coverage Report

Created: 2025-10-10 07:21

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