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