ppv_lite86/
types.rs

1#![allow(non_camel_case_types)]
2use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign, Not};
3
4pub trait AndNot {
5    type Output;
6    fn andnot(self, rhs: Self) -> Self::Output;
7}
8pub trait BSwap {
9    fn bswap(self) -> Self;
10}
11/// Ops that depend on word size
12pub trait ArithOps: Add<Output = Self> + AddAssign + Sized + Copy + Clone + BSwap {}
13/// Ops that are independent of word size and endian
14pub trait BitOps0:
15    BitAnd<Output = Self>
16    + BitOr<Output = Self>
17    + BitXor<Output = Self>
18    + BitXorAssign
19    + Not<Output = Self>
20    + AndNot<Output = Self>
21    + Sized
22    + Copy
23    + Clone
24{
25}
26
27pub trait BitOps32: BitOps0 + RotateEachWord32 {}
28pub trait BitOps64: BitOps32 + RotateEachWord64 {}
29pub trait BitOps128: BitOps64 + RotateEachWord128 {}
30
31pub trait RotateEachWord32 {
32    fn rotate_each_word_right7(self) -> Self;
33    fn rotate_each_word_right8(self) -> Self;
34    fn rotate_each_word_right11(self) -> Self;
35    fn rotate_each_word_right12(self) -> Self;
36    fn rotate_each_word_right16(self) -> Self;
37    fn rotate_each_word_right20(self) -> Self;
38    fn rotate_each_word_right24(self) -> Self;
39    fn rotate_each_word_right25(self) -> Self;
40}
41
42pub trait RotateEachWord64 {
43    fn rotate_each_word_right32(self) -> Self;
44}
45
46pub trait RotateEachWord128 {}
47
48// Vector type naming scheme:
49// uN[xP]xL
50// Unsigned; N-bit words * P bits per lane * L lanes
51//
52// A lane is always 128-bits, chosen because common SIMD architectures treat 128-bit units of
53// wide vectors specially (supporting e.g. intra-lane shuffles), and tend to have limited and
54// slow inter-lane operations.
55
56use crate::arch::{vec128_storage, vec256_storage, vec512_storage};
57
58#[allow(clippy::missing_safety_doc)]
59pub trait UnsafeFrom<T> {
60    unsafe fn unsafe_from(t: T) -> Self;
61}
62
63/// A vector composed of two elements, which may be words or themselves vectors.
64pub trait Vec2<W> {
65    fn extract(self, i: u32) -> W;
66    fn insert(self, w: W, i: u32) -> Self;
67}
68
69/// A vector composed of four elements, which may be words or themselves vectors.
70pub trait Vec4<W> {
71    fn extract(self, i: u32) -> W;
72    fn insert(self, w: W, i: u32) -> Self;
73}
74
75// TODO: multiples of 4 should inherit this
76/// A vector composed of four words; depending on their size, operations may cross lanes.
77pub trait Words4 {
78    fn shuffle1230(self) -> Self;
79    fn shuffle2301(self) -> Self;
80    fn shuffle3012(self) -> Self;
81}
82
83/// A vector composed one or more lanes each composed of four words.
84pub trait LaneWords4 {
85    fn shuffle_lane_words1230(self) -> Self;
86    fn shuffle_lane_words2301(self) -> Self;
87    fn shuffle_lane_words3012(self) -> Self;
88}
89
90// TODO: make this a part of BitOps
91/// Exchange neigboring ranges of bits of the specified size
92pub trait Swap64 {
93    fn swap1(self) -> Self;
94    fn swap2(self) -> Self;
95    fn swap4(self) -> Self;
96    fn swap8(self) -> Self;
97    fn swap16(self) -> Self;
98    fn swap32(self) -> Self;
99    fn swap64(self) -> Self;
100}
101
102pub trait u32x4<M: Machine>:
103    BitOps32
104    + Store<vec128_storage>
105    + ArithOps
106    + Vec4<u32>
107    + Words4
108    + LaneWords4
109    + StoreBytes
110    + MultiLane<[u32; 4]>
111    + Into<vec128_storage>
112{
113}
114pub trait u64x2<M: Machine>:
115    BitOps64
116    + Store<vec128_storage>
117    + ArithOps
118    + Vec2<u64>
119    + MultiLane<[u64; 2]>
120    + Into<vec128_storage>
121{
122}
123pub trait u128x1<M: Machine>:
124    BitOps128 + Store<vec128_storage> + Swap64 + MultiLane<[u128; 1]> + Into<vec128_storage>
125{
126}
127
128pub trait u32x4x2<M: Machine>:
129    BitOps32
130    + Store<vec256_storage>
131    + Vec2<M::u32x4>
132    + MultiLane<[M::u32x4; 2]>
133    + ArithOps
134    + Into<vec256_storage>
135{
136}
137pub trait u64x2x2<M: Machine>:
138    BitOps64
139    + Store<vec256_storage>
140    + Vec2<M::u64x2>
141    + MultiLane<[M::u64x2; 2]>
142    + ArithOps
143    + StoreBytes
144    + Into<vec256_storage>
145{
146}
147pub trait u64x4<M: Machine>:
148    BitOps64
149    + Store<vec256_storage>
150    + Vec4<u64>
151    + MultiLane<[u64; 4]>
152    + ArithOps
153    + Words4
154    + StoreBytes
155    + Into<vec256_storage>
156{
157}
158pub trait u128x2<M: Machine>:
159    BitOps128
160    + Store<vec256_storage>
161    + Vec2<M::u128x1>
162    + MultiLane<[M::u128x1; 2]>
163    + Swap64
164    + Into<vec256_storage>
165{
166}
167
168pub trait u32x4x4<M: Machine>:
169    BitOps32
170    + Store<vec512_storage>
171    + Vec4<M::u32x4>
172    + MultiLane<[M::u32x4; 4]>
173    + ArithOps
174    + LaneWords4
175    + Into<vec512_storage>
176{
177}
178pub trait u64x2x4<M: Machine>:
179    BitOps64
180    + Store<vec512_storage>
181    + Vec4<M::u64x2>
182    + MultiLane<[M::u64x2; 4]>
183    + ArithOps
184    + Into<vec512_storage>
185{
186}
187// TODO: Words4
188pub trait u128x4<M: Machine>:
189    BitOps128
190    + Store<vec512_storage>
191    + Vec4<M::u128x1>
192    + MultiLane<[M::u128x1; 4]>
193    + Swap64
194    + Into<vec512_storage>
195{
196}
197
198/// A vector composed of multiple 128-bit lanes.
199pub trait MultiLane<Lanes> {
200    /// Split a multi-lane vector into single-lane vectors.
201    fn to_lanes(self) -> Lanes;
202    /// Build a multi-lane vector from individual lanes.
203    fn from_lanes(lanes: Lanes) -> Self;
204}
205
206/// Combine single vectors into a multi-lane vector.
207pub trait VZip<V> {
208    fn vzip(self) -> V;
209}
210
211impl<V, T> VZip<V> for T
212where
213    V: MultiLane<T>,
214{
215    #[inline(always)]
216    fn vzip(self) -> V {
217        V::from_lanes(self)
218    }
219}
220
221pub trait Machine: Sized + Copy {
222    type u32x4: u32x4<Self>;
223    type u64x2: u64x2<Self>;
224    type u128x1: u128x1<Self>;
225
226    type u32x4x2: u32x4x2<Self>;
227    type u64x2x2: u64x2x2<Self>;
228    type u64x4: u64x4<Self>;
229    type u128x2: u128x2<Self>;
230
231    type u32x4x4: u32x4x4<Self>;
232    type u64x2x4: u64x2x4<Self>;
233    type u128x4: u128x4<Self>;
234
235    #[inline(always)]
236    fn unpack<S, V: Store<S>>(self, s: S) -> V {
237        unsafe { V::unpack(s) }
238    }
239
240    #[inline(always)]
241    fn vec<V, A>(self, a: A) -> V
242    where
243        V: MultiLane<A>,
244    {
245        V::from_lanes(a)
246    }
247
248    #[inline(always)]
249    fn read_le<V>(self, input: &[u8]) -> V
250    where
251        V: StoreBytes,
252    {
253        unsafe { V::unsafe_read_le(input) }
254    }
255
256    #[inline(always)]
257    fn read_be<V>(self, input: &[u8]) -> V
258    where
259        V: StoreBytes,
260    {
261        unsafe { V::unsafe_read_be(input) }
262    }
263
264    /// # Safety
265    /// Caller must ensure the type of Self is appropriate for the hardware of the execution
266    /// environment.
267    unsafe fn instance() -> Self;
268}
269
270pub trait Store<S> {
271    /// # Safety
272    /// Caller must ensure the type of Self is appropriate for the hardware of the execution
273    /// environment.
274    unsafe fn unpack(p: S) -> Self;
275}
276
277pub trait StoreBytes {
278    /// # Safety
279    /// Caller must ensure the type of Self is appropriate for the hardware of the execution
280    /// environment.
281    unsafe fn unsafe_read_le(input: &[u8]) -> Self;
282    /// # Safety
283    /// Caller must ensure the type of Self is appropriate for the hardware of the execution
284    /// environment.
285    unsafe fn unsafe_read_be(input: &[u8]) -> Self;
286    fn write_le(self, out: &mut [u8]);
287    fn write_be(self, out: &mut [u8]);
288}