Skip to main content

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}