safe_arch/x86_x64/
m128d_.rs

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