safe_arch/x86_x64/m512_.rs
1//! This module is for the `m512` wrapper type, its bonus methods, and all
2//! necessary trait impls.
3//!
4//! Intrinsics should _not_ be in this module! They should all be free-functions
5//! in the other modules, sorted by CPU target feature.
6
7use super::*;
8
9/// The data for a 512-bit AVX-512 register of sixteen `f32` lanes.
10///
11/// * This is _very similar to_ having `[f32; 16]`. The main difference is that
12/// it's aligned to 64 instead of just 4, and of course you can perform
13/// various intrinsic operations on it.
14#[repr(transparent)]
15#[allow(non_camel_case_types)]
16pub struct m512(pub __m512);
17
18#[cfg(feature = "bytemuck")]
19unsafe impl bytemuck::Zeroable for m512 {}
20#[cfg(feature = "bytemuck")]
21unsafe impl bytemuck::Pod for m512 {}
22#[cfg(feature = "bytemuck")]
23unsafe impl bytemuck::TransparentWrapper<__m512> for m512 {}
24
25impl m512 {
26 /// Transmutes the `m512` to an array.
27 ///
28 /// Same as `m.into()`, just lets you be more explicit about what's happening.
29 #[must_use]
30 #[inline(always)]
31 pub fn to_array(self) -> [f32; 16] {
32 self.into()
33 }
34
35 /// Transmutes an array into `m512`.
36 ///
37 /// Same as `m512::from(arr)`, it just lets you be more explicit about what's
38 /// happening.
39 #[must_use]
40 #[inline(always)]
41 pub fn from_array(f: [f32; 16]) -> Self {
42 f.into()
43 }
44
45 /// Converts into the bit patterns of these floats (`[u32;16]`).
46 ///
47 /// Like [`f32::to_bits`](f32::to_bits), but all sixteen lanes at once.
48 #[must_use]
49 #[inline(always)]
50 pub fn to_bits(self) -> [u32; 16] {
51 unsafe { core::mem::transmute(self) }
52 }
53
54 /// Converts from the bit patterns of these floats (`[u32;16]`).
55 ///
56 /// Like [`f32::from_bits`](f32::from_bits), but all sixteen lanes at once.
57 #[must_use]
58 #[inline(always)]
59 pub fn from_bits(bits: [u32; 16]) -> Self {
60 unsafe { core::mem::transmute(bits) }
61 }
62}
63
64impl Clone for m512 {
65 #[inline(always)]
66 fn clone(&self) -> Self {
67 *self
68 }
69}
70impl Copy for m512 {}
71
72impl Default for m512 {
73 #[inline(always)]
74 fn default() -> Self {
75 unsafe { core::mem::zeroed() }
76 }
77}
78
79impl From<[f32; 16]> for m512 {
80 #[inline(always)]
81 fn from(arr: [f32; 16]) -> Self {
82 // Safety: because this semantically moves the value from the input position
83 // (align4) to the output position (align64) it is fine to increase our
84 // required alignment without worry.
85 unsafe { core::mem::transmute(arr) }
86 }
87}
88
89impl From<m512> for [f32; 16] {
90 #[inline(always)]
91 fn from(m: m512) -> Self {
92 // We can of course transmute to a lower alignment
93 unsafe { core::mem::transmute(m) }
94 }
95}
96
97//
98// PLEASE KEEP ALL THE FORMAT IMPL JUNK AT THE END OF THE FILE
99//
100
101impl Debug for m512 {
102 /// Debug formats each float.
103 /// ```
104 /// # use safe_arch::*;
105 /// let f = format!("{:?}", m512::default());
106 /// assert_eq!(
107 /// &f,
108 /// "m512(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)"
109 /// );
110 /// ```
111 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
112 write!(f, "m512(")?;
113 for (i, float) in self.to_array().iter().enumerate() {
114 if i != 0 {
115 write!(f, ", ")?;
116 }
117 Debug::fmt(float, f)?;
118 }
119 write!(f, ")")
120 }
121}
122
123impl Display for m512 {
124 /// Display formats each float, and leaves the type name off of the font.
125 /// ```
126 /// # use safe_arch::*;
127 /// let f = format!("{}", m512::default());
128 /// assert_eq!(&f, "(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)");
129 /// ```
130 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
131 write!(f, "(")?;
132 for (i, float) in self.to_array().iter().enumerate() {
133 if i != 0 {
134 write!(f, ", ")?;
135 }
136 Display::fmt(float, f)?;
137 }
138 write!(f, ")")
139 }
140}
141
142impl Binary for m512 {
143 /// Binary formats each float's bit pattern (via [`f32::to_bits`]).
144 /// ```
145 /// # use safe_arch::*;
146 /// let f = format!("{:b}", m512::default());
147 /// assert_eq!(&f, "(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)");
148 /// ```
149 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
150 write!(f, "(")?;
151 for (i, float) in self.to_array().iter().enumerate() {
152 if i != 0 {
153 write!(f, ", ")?;
154 }
155 Binary::fmt(&float.to_bits(), f)?;
156 }
157 write!(f, ")")
158 }
159}
160
161impl LowerExp for m512 {
162 /// LowerExp formats each float.
163 /// ```
164 /// # use safe_arch::*;
165 /// let f = format!("{:e}", m512::default());
166 /// assert_eq!(
167 /// &f,
168 /// "(0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0, 0e0)"
169 /// );
170 /// ```
171 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
172 write!(f, "(")?;
173 for (i, float) in self.to_array().iter().enumerate() {
174 if i != 0 {
175 write!(f, ", ")?;
176 }
177 LowerExp::fmt(float, f)?;
178 }
179 write!(f, ")")
180 }
181}
182
183impl UpperExp for m512 {
184 /// UpperExp formats each float.
185 /// ```
186 /// # use safe_arch::*;
187 /// let f = format!("{:E}", m512::default());
188 /// assert_eq!(
189 /// &f,
190 /// "(0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0, 0E0)"
191 /// );
192 /// ```
193 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
194 write!(f, "(")?;
195 for (i, float) in self.to_array().iter().enumerate() {
196 if i != 0 {
197 write!(f, ", ")?;
198 }
199 UpperExp::fmt(float, f)?;
200 }
201 write!(f, ")")
202 }
203}
204
205impl LowerHex for m512 {
206 /// LowerHex formats each float's bit pattern (via [`f32::to_bits`]).
207 /// ```
208 /// # use safe_arch::*;
209 /// let f = format!("{:x}", m512::default());
210 /// assert_eq!(&f, "(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)");
211 /// ```
212 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
213 write!(f, "(")?;
214 for (i, float) in self.to_array().iter().enumerate() {
215 if i != 0 {
216 write!(f, ", ")?;
217 }
218 LowerHex::fmt(&float.to_bits(), f)?;
219 }
220 write!(f, ")")
221 }
222}
223
224impl UpperHex for m512 {
225 /// UpperHex formats each float's bit pattern (via [`f32::to_bits`]).
226 /// ```
227 /// # use safe_arch::*;
228 /// let f = format!("{:X}", m512::default());
229 /// assert_eq!(&f, "(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)");
230 /// ```
231 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
232 write!(f, "(")?;
233 for (i, float) in self.to_array().iter().enumerate() {
234 if i != 0 {
235 write!(f, ", ")?;
236 }
237 UpperHex::fmt(&float.to_bits(), f)?;
238 }
239 write!(f, ")")
240 }
241}
242
243impl Octal for m512 {
244 /// Octal formats each float's bit pattern (via [`f32::to_bits`]).
245 /// ```
246 /// # use safe_arch::*;
247 /// let f = format!("{:o}", m512::default());
248 /// assert_eq!(&f, "(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)");
249 /// ```
250 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
251 write!(f, "(")?;
252 for (i, float) in self.to_array().iter().enumerate() {
253 if i != 0 {
254 write!(f, ", ")?;
255 }
256 Octal::fmt(&float.to_bits(), f)?;
257 }
258 write!(f, ")")
259 }
260}