1use crate::{Flat, HardwareField};
19use core::fmt;
20use core::fmt::{Debug, Formatter};
21use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
22
23pub trait PackableField: Sized + Copy + Clone + Default {
26 type Packed: Add<Output = Self::Packed>
28 + Sub<Output = Self::Packed>
29 + Mul<Output = Self::Packed>
30 + Mul<Self, Output = Self::Packed>
31 + AddAssign
32 + SubAssign
33 + MulAssign
34 + Copy
35 + Clone
36 + Default
37 + Send;
38
39 const WIDTH: usize;
41
42 fn pack(chunk: &[Self]) -> Self::Packed;
45
46 fn unpack(packed: Self::Packed, output: &mut [Self]);
48}
49
50impl<F: HardwareField> PackableField for Flat<F> {
51 type Packed = PackedFlat<F>;
52
53 const WIDTH: usize = F::WIDTH;
54
55 #[inline(always)]
56 fn pack(chunk: &[Self]) -> Self::Packed {
57 PackedFlat::from_raw(F::pack(flat_slice_as_raw(chunk)))
58 }
59
60 #[inline(always)]
61 fn unpack(packed: Self::Packed, output: &mut [Self]) {
62 F::unpack(packed.into_raw(), flat_slice_as_raw_mut(output));
63 }
64}
65
66#[repr(transparent)]
69pub struct PackedFlat<F: PackableField>(<F as PackableField>::Packed);
70
71impl<F> PackedFlat<F>
72where
73 F: PackableField,
74{
75 #[inline(always)]
76 pub fn from_raw(raw: F::Packed) -> Self {
77 Self(raw)
78 }
79
80 #[inline(always)]
81 pub fn into_raw(self) -> F::Packed {
82 self.0
83 }
84
85 #[inline(always)]
86 pub fn as_raw(&self) -> &F::Packed {
87 &self.0
88 }
89}
90
91impl<F> Copy for PackedFlat<F>
92where
93 F: PackableField,
94 F::Packed: Copy,
95{
96}
97
98impl<F> Clone for PackedFlat<F>
99where
100 F: PackableField,
101 F::Packed: Copy,
102{
103 #[inline(always)]
104 fn clone(&self) -> Self {
105 *self
106 }
107}
108
109impl<F> Default for PackedFlat<F>
110where
111 F: PackableField,
112 F::Packed: Default,
113{
114 #[inline(always)]
115 fn default() -> Self {
116 Self(F::Packed::default())
117 }
118}
119
120impl<F> PartialEq for PackedFlat<F>
121where
122 F: PackableField,
123 F::Packed: PartialEq,
124{
125 #[inline(always)]
126 fn eq(&self, other: &Self) -> bool {
127 self.0 == other.0
128 }
129}
130
131impl<F> Eq for PackedFlat<F>
132where
133 F: PackableField,
134 F::Packed: Eq,
135{
136}
137
138impl<F> Debug for PackedFlat<F>
139where
140 F: PackableField,
141 F::Packed: Debug,
142{
143 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
144 f.debug_tuple("PackedFlat").field(&self.0).finish()
145 }
146}
147
148impl<F: HardwareField> Add for PackedFlat<F> {
149 type Output = Self;
150
151 #[inline(always)]
152 fn add(self, rhs: Self) -> Self::Output {
153 F::add_hardware_packed(self, rhs)
154 }
155}
156
157impl<F: HardwareField> AddAssign for PackedFlat<F> {
158 #[inline(always)]
159 fn add_assign(&mut self, rhs: Self) {
160 *self = *self + rhs;
161 }
162}
163
164impl<F: HardwareField> Sub for PackedFlat<F> {
165 type Output = Self;
166
167 #[inline(always)]
168 fn sub(self, rhs: Self) -> Self::Output {
169 F::add_hardware_packed(self, rhs)
170 }
171}
172
173impl<F: HardwareField> SubAssign for PackedFlat<F> {
174 #[inline(always)]
175 fn sub_assign(&mut self, rhs: Self) {
176 *self = *self - rhs;
177 }
178}
179
180impl<F: HardwareField> Mul for PackedFlat<F> {
181 type Output = Self;
182
183 #[inline(always)]
184 fn mul(self, rhs: Self) -> Self::Output {
185 F::mul_hardware_packed(self, rhs)
186 }
187}
188
189impl<F: HardwareField> MulAssign for PackedFlat<F> {
190 #[inline(always)]
191 fn mul_assign(&mut self, rhs: Self) {
192 *self = *self * rhs;
193 }
194}
195
196impl<F: HardwareField> Mul<Flat<F>> for PackedFlat<F> {
197 type Output = Self;
198
199 #[inline(always)]
200 fn mul(self, rhs: Flat<F>) -> Self::Output {
201 F::mul_hardware_scalar_packed(self, rhs)
202 }
203}
204
205#[inline(always)]
206fn flat_slice_as_raw<F>(slice: &[Flat<F>]) -> &[F] {
207 unsafe { core::slice::from_raw_parts(slice.as_ptr().cast::<F>(), slice.len()) }
208}
209
210#[inline(always)]
211fn flat_slice_as_raw_mut<F>(slice: &mut [Flat<F>]) -> &mut [F] {
212 unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast::<F>(), slice.len()) }
213}