@@ -4,6 +4,9 @@ use super::MaskElement;
44use crate :: simd:: intrinsics;
55use crate :: simd:: { LaneCount , Simd , SupportedLaneCount , ToBitMask } ;
66
7+ #[ cfg( feature = "generic_const_exprs" ) ]
8+ use crate :: simd:: ToBitMaskArray ;
9+
710#[ repr( transparent) ]
811pub struct Mask < T , const LANES : usize > ( Simd < T , LANES > )
912where
@@ -139,6 +142,68 @@ where
139142 unsafe { Mask ( intrinsics:: simd_cast ( self . 0 ) ) }
140143 }
141144
145+ #[ cfg( feature = "generic_const_exprs" ) ]
146+ #[ inline]
147+ #[ must_use = "method returns a new array and does not mutate the original value" ]
148+ pub fn to_bitmask_array < const N : usize > ( self ) -> [ u8 ; N ]
149+ where
150+ super :: Mask < T , LANES > : ToBitMaskArray ,
151+ [ ( ) ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] : Sized ,
152+ {
153+ assert_eq ! ( <super :: Mask <T , LANES > as ToBitMaskArray >:: BYTES , N ) ;
154+
155+ // Safety: N is the correct bitmask size
156+ unsafe {
157+ // Compute the bitmask
158+ let bitmask: [ u8 ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] =
159+ intrinsics:: simd_bitmask ( self . 0 ) ;
160+
161+ // Transmute to the return type, previously asserted to be the same size
162+ let mut bitmask: [ u8 ; N ] = core:: mem:: transmute_copy ( & bitmask) ;
163+
164+ // LLVM assumes bit order should match endianness
165+ if cfg ! ( target_endian = "big" ) {
166+ for x in bitmask. as_mut ( ) {
167+ * x = x. reverse_bits ( ) ;
168+ }
169+ } ;
170+
171+ bitmask
172+ }
173+ }
174+
175+ #[ cfg( feature = "generic_const_exprs" ) ]
176+ #[ inline]
177+ #[ must_use = "method returns a new mask and does not mutate the original value" ]
178+ pub fn from_bitmask_array < const N : usize > ( mut bitmask : [ u8 ; N ] ) -> Self
179+ where
180+ super :: Mask < T , LANES > : ToBitMaskArray ,
181+ [ ( ) ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] : Sized ,
182+ {
183+ assert_eq ! ( <super :: Mask <T , LANES > as ToBitMaskArray >:: BYTES , N ) ;
184+
185+ // Safety: N is the correct bitmask size
186+ unsafe {
187+ // LLVM assumes bit order should match endianness
188+ if cfg ! ( target_endian = "big" ) {
189+ for x in bitmask. as_mut ( ) {
190+ * x = x. reverse_bits ( ) ;
191+ }
192+ }
193+
194+ // Transmute to the bitmask type, previously asserted to be the same size
195+ let bitmask: [ u8 ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] =
196+ core:: mem:: transmute_copy ( & bitmask) ;
197+
198+ // Compute the regular mask
199+ Self :: from_int_unchecked ( intrinsics:: simd_select_bitmask (
200+ bitmask,
201+ Self :: splat ( true ) . to_int ( ) ,
202+ Self :: splat ( false ) . to_int ( ) ,
203+ ) )
204+ }
205+ }
206+
142207 #[ inline]
143208 pub ( crate ) fn to_bitmask_integer < U : ReverseBits > ( self ) -> U
144209 where
0 commit comments