Coverage Report

Created: 2026-03-31 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/half-2.4.1/src/slice.rs
Line
Count
Source
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
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 core::slice;
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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`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 [`f16`] or [`bf16`] numbers.
230
    ///
231
    /// `H` is the type to cast to, and must be either the [`f16`] or [`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 [`f16`] or [`bf16`]
255
    /// numbers.
256
    ///
257
    /// `H` is the type to cast to, and must be either the [`f16`] or [`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
        let pointer = self.as_ptr() as *const u16;
305
0
        let length = self.len();
306
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
307
        // and the size of elements are identical
308
0
        unsafe { slice::from_raw_parts(pointer, length) }
309
0
    }
310
311
    #[inline]
312
0
    fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
313
0
        let pointer = self.as_mut_ptr().cast::<u16>();
314
0
        let length = self.len();
315
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
316
        // and the size of elements are identical
317
0
        unsafe { slice::from_raw_parts_mut(pointer, length) }
318
0
    }
319
320
    #[inline]
321
0
    fn convert_from_f32_slice(&mut self, src: &[f32]) {
322
0
        assert_eq!(
323
0
            self.len(),
324
0
            src.len(),
325
0
            "destination and source slices have different lengths"
326
        );
327
328
0
        arch::f32_to_f16_slice(src, self.reinterpret_cast_mut())
329
0
    }
330
331
    #[inline]
332
0
    fn convert_from_f64_slice(&mut self, src: &[f64]) {
333
0
        assert_eq!(
334
0
            self.len(),
335
0
            src.len(),
336
0
            "destination and source slices have different lengths"
337
        );
338
339
0
        arch::f64_to_f16_slice(src, self.reinterpret_cast_mut())
340
0
    }
341
342
    #[inline]
343
0
    fn convert_to_f32_slice(&self, dst: &mut [f32]) {
344
0
        assert_eq!(
345
0
            self.len(),
346
0
            dst.len(),
347
0
            "destination and source slices have different lengths"
348
        );
349
350
0
        arch::f16_to_f32_slice(self.reinterpret_cast(), dst)
351
0
    }
352
353
    #[inline]
354
0
    fn convert_to_f64_slice(&self, dst: &mut [f64]) {
355
0
        assert_eq!(
356
0
            self.len(),
357
0
            dst.len(),
358
0
            "destination and source slices have different lengths"
359
        );
360
361
0
        arch::f16_to_f64_slice(self.reinterpret_cast(), dst)
362
0
    }
363
364
    #[cfg(any(feature = "alloc", feature = "std"))]
365
    #[inline]
366
    #[allow(clippy::uninit_vec)]
367
    fn to_f32_vec(&self) -> Vec<f32> {
368
        let mut vec = vec![0f32; self.len()];
369
        self.convert_to_f32_slice(&mut vec);
370
        vec
371
    }
372
373
    #[cfg(any(feature = "alloc", feature = "std"))]
374
    #[inline]
375
    #[allow(clippy::uninit_vec)]
376
    fn to_f64_vec(&self) -> Vec<f64> {
377
        let mut vec = vec![0f64; self.len()];
378
        self.convert_to_f64_slice(&mut vec);
379
        vec
380
    }
381
}
382
383
impl HalfFloatSliceExt for [bf16] {
384
    #[inline]
385
0
    fn reinterpret_cast(&self) -> &[u16] {
386
0
        let pointer = self.as_ptr() as *const u16;
387
0
        let length = self.len();
388
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
389
        // and the size of elements are identical
390
0
        unsafe { slice::from_raw_parts(pointer, length) }
391
0
    }
392
393
    #[inline]
394
0
    fn reinterpret_cast_mut(&mut self) -> &mut [u16] {
395
0
        let pointer = self.as_mut_ptr().cast::<u16>();
396
0
        let length = self.len();
397
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
398
        // and the size of elements are identical
399
0
        unsafe { slice::from_raw_parts_mut(pointer, length) }
400
0
    }
401
402
    #[inline]
403
0
    fn convert_from_f32_slice(&mut self, src: &[f32]) {
404
0
        assert_eq!(
405
0
            self.len(),
406
0
            src.len(),
407
0
            "destination and source slices have different lengths"
408
        );
409
410
        // Just use regular loop here until there's any bf16 SIMD support.
411
0
        for (i, f) in src.iter().enumerate() {
412
0
            self[i] = bf16::from_f32(*f);
413
0
        }
414
0
    }
415
416
    #[inline]
417
0
    fn convert_from_f64_slice(&mut self, src: &[f64]) {
418
0
        assert_eq!(
419
0
            self.len(),
420
0
            src.len(),
421
0
            "destination and source slices have different lengths"
422
        );
423
424
        // Just use regular loop here until there's any bf16 SIMD support.
425
0
        for (i, f) in src.iter().enumerate() {
426
0
            self[i] = bf16::from_f64(*f);
427
0
        }
428
0
    }
429
430
    #[inline]
431
0
    fn convert_to_f32_slice(&self, dst: &mut [f32]) {
432
0
        assert_eq!(
433
0
            self.len(),
434
0
            dst.len(),
435
0
            "destination and source slices have different lengths"
436
        );
437
438
        // Just use regular loop here until there's any bf16 SIMD support.
439
0
        for (i, f) in self.iter().enumerate() {
440
0
            dst[i] = f.to_f32();
441
0
        }
442
0
    }
443
444
    #[inline]
445
0
    fn convert_to_f64_slice(&self, dst: &mut [f64]) {
446
0
        assert_eq!(
447
0
            self.len(),
448
0
            dst.len(),
449
0
            "destination and source slices have different lengths"
450
        );
451
452
        // Just use regular loop here until there's any bf16 SIMD support.
453
0
        for (i, f) in self.iter().enumerate() {
454
0
            dst[i] = f.to_f64();
455
0
        }
456
0
    }
457
458
    #[cfg(any(feature = "alloc", feature = "std"))]
459
    #[inline]
460
    #[allow(clippy::uninit_vec)]
461
    fn to_f32_vec(&self) -> Vec<f32> {
462
        let mut vec = vec![0f32; self.len()];
463
        self.convert_to_f32_slice(&mut vec);
464
        vec
465
    }
466
467
    #[cfg(any(feature = "alloc", feature = "std"))]
468
    #[inline]
469
    #[allow(clippy::uninit_vec)]
470
    fn to_f64_vec(&self) -> Vec<f64> {
471
        let mut vec = vec![0f64; self.len()];
472
        self.convert_to_f64_slice(&mut vec);
473
        vec
474
    }
475
}
476
477
impl HalfBitsSliceExt for [u16] {
478
    // Since we sealed all the traits involved, these are safe.
479
    #[inline]
480
0
    fn reinterpret_cast<H>(&self) -> &[H]
481
0
    where
482
0
        H: crate::private::SealedHalf,
483
    {
484
0
        let pointer = self.as_ptr() as *const H;
485
0
        let length = self.len();
486
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
487
        // and the size of elements are identical
488
0
        unsafe { slice::from_raw_parts(pointer, length) }
489
0
    }
490
491
    #[inline]
492
0
    fn reinterpret_cast_mut<H>(&mut self) -> &mut [H]
493
0
    where
494
0
        H: crate::private::SealedHalf,
495
    {
496
0
        let pointer = self.as_mut_ptr() as *mut H;
497
0
        let length = self.len();
498
        // SAFETY: We are reconstructing full length of original slice, using its same lifetime,
499
        // and the size of elements are identical
500
0
        unsafe { slice::from_raw_parts_mut(pointer, length) }
501
0
    }
502
}
503
504
#[allow(clippy::float_cmp)]
505
#[cfg(test)]
506
mod test {
507
    use super::{HalfBitsSliceExt, HalfFloatSliceExt};
508
    use crate::{bf16, f16};
509
510
    #[test]
511
    fn test_slice_conversions_f16() {
512
        let bits = &[
513
            f16::E.to_bits(),
514
            f16::PI.to_bits(),
515
            f16::EPSILON.to_bits(),
516
            f16::FRAC_1_SQRT_2.to_bits(),
517
        ];
518
        let numbers = &[f16::E, f16::PI, f16::EPSILON, f16::FRAC_1_SQRT_2];
519
520
        // Convert from bits to numbers
521
        let from_bits = bits.reinterpret_cast::<f16>();
522
        assert_eq!(from_bits, numbers);
523
524
        // Convert from numbers back to bits
525
        let to_bits = from_bits.reinterpret_cast();
526
        assert_eq!(to_bits, bits);
527
    }
528
529
    #[test]
530
    fn test_mutablility_f16() {
531
        let mut bits_array = [f16::PI.to_bits()];
532
        let bits = &mut bits_array[..];
533
534
        {
535
            // would not compile without these braces
536
            let numbers = bits.reinterpret_cast_mut();
537
            numbers[0] = f16::E;
538
        }
539
540
        assert_eq!(bits, &[f16::E.to_bits()]);
541
542
        bits[0] = f16::LN_2.to_bits();
543
        assert_eq!(bits, &[f16::LN_2.to_bits()]);
544
    }
545
546
    #[test]
547
    fn test_slice_conversions_bf16() {
548
        let bits = &[
549
            bf16::E.to_bits(),
550
            bf16::PI.to_bits(),
551
            bf16::EPSILON.to_bits(),
552
            bf16::FRAC_1_SQRT_2.to_bits(),
553
        ];
554
        let numbers = &[bf16::E, bf16::PI, bf16::EPSILON, bf16::FRAC_1_SQRT_2];
555
556
        // Convert from bits to numbers
557
        let from_bits = bits.reinterpret_cast::<bf16>();
558
        assert_eq!(from_bits, numbers);
559
560
        // Convert from numbers back to bits
561
        let to_bits = from_bits.reinterpret_cast();
562
        assert_eq!(to_bits, bits);
563
    }
564
565
    #[test]
566
    fn test_mutablility_bf16() {
567
        let mut bits_array = [bf16::PI.to_bits()];
568
        let bits = &mut bits_array[..];
569
570
        {
571
            // would not compile without these braces
572
            let numbers = bits.reinterpret_cast_mut();
573
            numbers[0] = bf16::E;
574
        }
575
576
        assert_eq!(bits, &[bf16::E.to_bits()]);
577
578
        bits[0] = bf16::LN_2.to_bits();
579
        assert_eq!(bits, &[bf16::LN_2.to_bits()]);
580
    }
581
582
    #[test]
583
    fn slice_convert_f16_f32() {
584
        // Exact chunks
585
        let vf32 = [1., 2., 3., 4., 5., 6., 7., 8.];
586
        let vf16 = [
587
            f16::from_f32(1.),
588
            f16::from_f32(2.),
589
            f16::from_f32(3.),
590
            f16::from_f32(4.),
591
            f16::from_f32(5.),
592
            f16::from_f32(6.),
593
            f16::from_f32(7.),
594
            f16::from_f32(8.),
595
        ];
596
        let mut buf32 = vf32;
597
        let mut buf16 = vf16;
598
599
        vf16.convert_to_f32_slice(&mut buf32);
600
        assert_eq!(&vf32, &buf32);
601
602
        buf16.convert_from_f32_slice(&vf32);
603
        assert_eq!(&vf16, &buf16);
604
605
        // Partial with chunks
606
        let vf32 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
607
        let vf16 = [
608
            f16::from_f32(1.),
609
            f16::from_f32(2.),
610
            f16::from_f32(3.),
611
            f16::from_f32(4.),
612
            f16::from_f32(5.),
613
            f16::from_f32(6.),
614
            f16::from_f32(7.),
615
            f16::from_f32(8.),
616
            f16::from_f32(9.),
617
        ];
618
        let mut buf32 = vf32;
619
        let mut buf16 = vf16;
620
621
        vf16.convert_to_f32_slice(&mut buf32);
622
        assert_eq!(&vf32, &buf32);
623
624
        buf16.convert_from_f32_slice(&vf32);
625
        assert_eq!(&vf16, &buf16);
626
627
        // Partial with chunks
628
        let vf32 = [1., 2.];
629
        let vf16 = [f16::from_f32(1.), f16::from_f32(2.)];
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
640
    #[test]
641
    fn slice_convert_bf16_f32() {
642
        // Exact chunks
643
        let vf32 = [1., 2., 3., 4., 5., 6., 7., 8.];
644
        let vf16 = [
645
            bf16::from_f32(1.),
646
            bf16::from_f32(2.),
647
            bf16::from_f32(3.),
648
            bf16::from_f32(4.),
649
            bf16::from_f32(5.),
650
            bf16::from_f32(6.),
651
            bf16::from_f32(7.),
652
            bf16::from_f32(8.),
653
        ];
654
        let mut buf32 = vf32;
655
        let mut buf16 = vf16;
656
657
        vf16.convert_to_f32_slice(&mut buf32);
658
        assert_eq!(&vf32, &buf32);
659
660
        buf16.convert_from_f32_slice(&vf32);
661
        assert_eq!(&vf16, &buf16);
662
663
        // Partial with chunks
664
        let vf32 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
665
        let vf16 = [
666
            bf16::from_f32(1.),
667
            bf16::from_f32(2.),
668
            bf16::from_f32(3.),
669
            bf16::from_f32(4.),
670
            bf16::from_f32(5.),
671
            bf16::from_f32(6.),
672
            bf16::from_f32(7.),
673
            bf16::from_f32(8.),
674
            bf16::from_f32(9.),
675
        ];
676
        let mut buf32 = vf32;
677
        let mut buf16 = vf16;
678
679
        vf16.convert_to_f32_slice(&mut buf32);
680
        assert_eq!(&vf32, &buf32);
681
682
        buf16.convert_from_f32_slice(&vf32);
683
        assert_eq!(&vf16, &buf16);
684
685
        // Partial with chunks
686
        let vf32 = [1., 2.];
687
        let vf16 = [bf16::from_f32(1.), bf16::from_f32(2.)];
688
        let mut buf32 = vf32;
689
        let mut buf16 = vf16;
690
691
        vf16.convert_to_f32_slice(&mut buf32);
692
        assert_eq!(&vf32, &buf32);
693
694
        buf16.convert_from_f32_slice(&vf32);
695
        assert_eq!(&vf16, &buf16);
696
    }
697
698
    #[test]
699
    fn slice_convert_f16_f64() {
700
        // Exact chunks
701
        let vf64 = [1., 2., 3., 4., 5., 6., 7., 8.];
702
        let vf16 = [
703
            f16::from_f64(1.),
704
            f16::from_f64(2.),
705
            f16::from_f64(3.),
706
            f16::from_f64(4.),
707
            f16::from_f64(5.),
708
            f16::from_f64(6.),
709
            f16::from_f64(7.),
710
            f16::from_f64(8.),
711
        ];
712
        let mut buf64 = vf64;
713
        let mut buf16 = vf16;
714
715
        vf16.convert_to_f64_slice(&mut buf64);
716
        assert_eq!(&vf64, &buf64);
717
718
        buf16.convert_from_f64_slice(&vf64);
719
        assert_eq!(&vf16, &buf16);
720
721
        // Partial with chunks
722
        let vf64 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
723
        let vf16 = [
724
            f16::from_f64(1.),
725
            f16::from_f64(2.),
726
            f16::from_f64(3.),
727
            f16::from_f64(4.),
728
            f16::from_f64(5.),
729
            f16::from_f64(6.),
730
            f16::from_f64(7.),
731
            f16::from_f64(8.),
732
            f16::from_f64(9.),
733
        ];
734
        let mut buf64 = vf64;
735
        let mut buf16 = vf16;
736
737
        vf16.convert_to_f64_slice(&mut buf64);
738
        assert_eq!(&vf64, &buf64);
739
740
        buf16.convert_from_f64_slice(&vf64);
741
        assert_eq!(&vf16, &buf16);
742
743
        // Partial with chunks
744
        let vf64 = [1., 2.];
745
        let vf16 = [f16::from_f64(1.), f16::from_f64(2.)];
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
756
    #[test]
757
    fn slice_convert_bf16_f64() {
758
        // Exact chunks
759
        let vf64 = [1., 2., 3., 4., 5., 6., 7., 8.];
760
        let vf16 = [
761
            bf16::from_f64(1.),
762
            bf16::from_f64(2.),
763
            bf16::from_f64(3.),
764
            bf16::from_f64(4.),
765
            bf16::from_f64(5.),
766
            bf16::from_f64(6.),
767
            bf16::from_f64(7.),
768
            bf16::from_f64(8.),
769
        ];
770
        let mut buf64 = vf64;
771
        let mut buf16 = vf16;
772
773
        vf16.convert_to_f64_slice(&mut buf64);
774
        assert_eq!(&vf64, &buf64);
775
776
        buf16.convert_from_f64_slice(&vf64);
777
        assert_eq!(&vf16, &buf16);
778
779
        // Partial with chunks
780
        let vf64 = [1., 2., 3., 4., 5., 6., 7., 8., 9.];
781
        let vf16 = [
782
            bf16::from_f64(1.),
783
            bf16::from_f64(2.),
784
            bf16::from_f64(3.),
785
            bf16::from_f64(4.),
786
            bf16::from_f64(5.),
787
            bf16::from_f64(6.),
788
            bf16::from_f64(7.),
789
            bf16::from_f64(8.),
790
            bf16::from_f64(9.),
791
        ];
792
        let mut buf64 = vf64;
793
        let mut buf16 = vf16;
794
795
        vf16.convert_to_f64_slice(&mut buf64);
796
        assert_eq!(&vf64, &buf64);
797
798
        buf16.convert_from_f64_slice(&vf64);
799
        assert_eq!(&vf16, &buf16);
800
801
        // Partial with chunks
802
        let vf64 = [1., 2.];
803
        let vf16 = [bf16::from_f64(1.), bf16::from_f64(2.)];
804
        let mut buf64 = vf64;
805
        let mut buf16 = vf16;
806
807
        vf16.convert_to_f64_slice(&mut buf64);
808
        assert_eq!(&vf64, &buf64);
809
810
        buf16.convert_from_f64_slice(&vf64);
811
        assert_eq!(&vf16, &buf16);
812
    }
813
814
    #[test]
815
    #[should_panic]
816
    fn convert_from_f32_slice_len_mismatch_panics() {
817
        let mut slice1 = [f16::ZERO; 3];
818
        let slice2 = [0f32; 4];
819
        slice1.convert_from_f32_slice(&slice2);
820
    }
821
822
    #[test]
823
    #[should_panic]
824
    fn convert_from_f64_slice_len_mismatch_panics() {
825
        let mut slice1 = [f16::ZERO; 3];
826
        let slice2 = [0f64; 4];
827
        slice1.convert_from_f64_slice(&slice2);
828
    }
829
830
    #[test]
831
    #[should_panic]
832
    fn convert_to_f32_slice_len_mismatch_panics() {
833
        let slice1 = [f16::ZERO; 3];
834
        let mut slice2 = [0f32; 4];
835
        slice1.convert_to_f32_slice(&mut slice2);
836
    }
837
838
    #[test]
839
    #[should_panic]
840
    fn convert_to_f64_slice_len_mismatch_panics() {
841
        let slice1 = [f16::ZERO; 3];
842
        let mut slice2 = [0f64; 4];
843
        slice1.convert_to_f64_slice(&mut slice2);
844
    }
845
}