1
- use crate :: simd:: SimdElement ;
1
+ use crate :: simd:: { intrinsics , LaneCount , Simd , SimdElement , SupportedLaneCount } ;
2
2
3
3
/// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly.
4
- pub trait SimdCast < Target : SimdElement > : SimdElement { }
4
+ pub trait SimdCast < Target : SimdElement > : SimdElement {
5
+ #[ doc( hidden) ]
6
+ fn cast < const LANES : usize > ( x : Simd < Self , LANES > ) -> Simd < Target , LANES >
7
+ where
8
+ LaneCount < LANES > : SupportedLaneCount ;
9
+ }
5
10
6
11
macro_rules! into_number {
12
+ { $from: ty, $to: ty } => {
13
+ impl SimdCast <$to> for $from {
14
+ fn cast<const LANES : usize >( x: Simd <Self , LANES >) -> Simd <$to, LANES >
15
+ where
16
+ LaneCount <LANES >: SupportedLaneCount ,
17
+ {
18
+ // Safety: simd_as can handle numeric conversions
19
+ unsafe { intrinsics:: simd_as( x) }
20
+ }
21
+ }
22
+ } ;
7
23
{ $( $type: ty) ,* } => {
8
24
$(
9
- impl SimdCast < i8 > for $type { }
10
- impl SimdCast < i16 > for $type { }
11
- impl SimdCast < i32 > for $type { }
12
- impl SimdCast < i64 > for $type { }
13
- impl SimdCast < isize > for $type { }
14
-
15
- impl SimdCast < u8 > for $type { }
16
- impl SimdCast < u16 > for $type { }
17
- impl SimdCast < u32 > for $type { }
18
- impl SimdCast < u64 > for $type { }
19
- impl SimdCast < usize > for $type { }
20
-
21
- impl SimdCast < f32 > for $type { }
22
- impl SimdCast < f64 > for $type { }
25
+ into_number! { $type, i8 }
26
+ into_number! { $type, i16 }
27
+ into_number! { $type, i32 }
28
+ into_number! { $type, i64 }
29
+ into_number! { $type, isize }
30
+
31
+ into_number! { $type, u8 }
32
+ into_number! { $type, u16 }
33
+ into_number! { $type, u32 }
34
+ into_number! { $type, u64 }
35
+ into_number! { $type, usize }
36
+
37
+ into_number! { $type, f32 }
38
+ into_number! { $type, f64 }
23
39
) *
24
40
}
25
41
}
@@ -29,17 +45,85 @@ into_number! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64 }
29
45
macro_rules! into_pointer {
30
46
{ $( $type: ty) ,* } => {
31
47
$(
32
- impl <T > SimdCast <$type> for * const T { }
33
- impl <T > SimdCast <$type> for * mut T { }
34
- impl <T > SimdCast <* const T > for $type { }
35
- impl <T > SimdCast <* mut T > for $type { }
48
+ impl <T > SimdCast <$type> for * const T {
49
+ fn cast<const LANES : usize >( x: Simd <Self , LANES >) -> Simd <$type, LANES >
50
+ where
51
+ LaneCount <LANES >: SupportedLaneCount ,
52
+ {
53
+ // Safety: transmuting isize to pointers is safe
54
+ let x: Simd <isize , LANES > = unsafe { core:: mem:: transmute_copy( & x) } ;
55
+ x. cast( )
56
+ }
57
+ }
58
+ impl <T > SimdCast <$type> for * mut T {
59
+ fn cast<const LANES : usize >( x: Simd <Self , LANES >) -> Simd <$type, LANES >
60
+ where
61
+ LaneCount <LANES >: SupportedLaneCount ,
62
+ {
63
+ // Safety: transmuting isize to pointers is safe
64
+ let x: Simd <isize , LANES > = unsafe { core:: mem:: transmute_copy( & x) } ;
65
+ x. cast( )
66
+ }
67
+ }
68
+ impl <T > SimdCast <* const T > for $type {
69
+ fn cast<const LANES : usize >( x: Simd <$type, LANES >) -> Simd <* const T , LANES >
70
+ where
71
+ LaneCount <LANES >: SupportedLaneCount ,
72
+ {
73
+ let x: Simd <isize , LANES > = x. cast( ) ;
74
+ // Safety: transmuting isize to pointers is safe
75
+ unsafe { core:: mem:: transmute_copy( & x) }
76
+ }
77
+ }
78
+ impl <T > SimdCast <* mut T > for $type {
79
+ fn cast<const LANES : usize >( x: Simd <$type, LANES >) -> Simd <* mut T , LANES >
80
+ where
81
+ LaneCount <LANES >: SupportedLaneCount ,
82
+ {
83
+ let x: Simd <isize , LANES > = x. cast( ) ;
84
+ // Safety: transmuting isize to pointers is safe
85
+ unsafe { core:: mem:: transmute_copy( & x) }
86
+ }
87
+ }
36
88
) *
37
89
}
38
90
}
39
91
40
92
into_pointer ! { i8 , i16 , i32 , i64 , isize , u8 , u16 , u32 , u64 , usize }
41
93
42
- impl < T , U > SimdCast < * const T > for * const U { }
43
- impl < T , U > SimdCast < * const T > for * mut U { }
44
- impl < T , U > SimdCast < * mut T > for * const U { }
45
- impl < T , U > SimdCast < * mut T > for * mut U { }
94
+ impl < T , U > SimdCast < * const T > for * const U {
95
+ fn cast < const LANES : usize > ( x : Simd < * const U , LANES > ) -> Simd < * const T , LANES >
96
+ where
97
+ LaneCount < LANES > : SupportedLaneCount ,
98
+ {
99
+ // Safety: transmuting pointers is safe
100
+ unsafe { core:: mem:: transmute_copy ( & x) }
101
+ }
102
+ }
103
+ impl < T , U > SimdCast < * const T > for * mut U {
104
+ fn cast < const LANES : usize > ( x : Simd < * mut U , LANES > ) -> Simd < * const T , LANES >
105
+ where
106
+ LaneCount < LANES > : SupportedLaneCount ,
107
+ {
108
+ // Safety: transmuting pointers is safe
109
+ unsafe { core:: mem:: transmute_copy ( & x) }
110
+ }
111
+ }
112
+ impl < T , U > SimdCast < * mut T > for * const U {
113
+ fn cast < const LANES : usize > ( x : Simd < * const U , LANES > ) -> Simd < * mut T , LANES >
114
+ where
115
+ LaneCount < LANES > : SupportedLaneCount ,
116
+ {
117
+ // Safety: transmuting pointers is safe
118
+ unsafe { core:: mem:: transmute_copy ( & x) }
119
+ }
120
+ }
121
+ impl < T , U > SimdCast < * mut T > for * mut U {
122
+ fn cast < const LANES : usize > ( x : Simd < * mut U , LANES > ) -> Simd < * mut T , LANES >
123
+ where
124
+ LaneCount < LANES > : SupportedLaneCount ,
125
+ {
126
+ // Safety: transmuting pointers is safe
127
+ unsafe { core:: mem:: transmute_copy ( & x) }
128
+ }
129
+ }
0 commit comments