Skip to main content

safe_arch/x86_x64/
m512d_.rs

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