safe_arch/x86_x64/
m128_.rs

1//! This module is for the `m128` 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 four `f32` lanes.
10///
11/// * This is _very similar to_ having `[f32; 4]`. 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 m128(pub __m128);
17
18#[cfg(feature = "bytemuck")]
19unsafe impl bytemuck::Zeroable for m128 {}
20#[cfg(feature = "bytemuck")]
21unsafe impl bytemuck::Pod for m128 {}
22#[cfg(feature = "bytemuck")]
23unsafe impl bytemuck::TransparentWrapper<__m128> for m128 {}
24
25impl m128 {
26  /// Transmutes the `m128` 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; 4] {
32    self.into()
33  }
34
35  /// Transmutes an array into `m128`.
36  ///
37  /// Same as `m128::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; 4]) -> Self {
42    f.into()
43  }
44
45  //
46
47  /// Converts into the bit patterns of these floats (`[u32;4]`).
48  ///
49  /// Like [`f32::to_bits`](f32::to_bits), but all four lanes at once.
50  #[must_use]
51  #[inline(always)]
52  pub fn to_bits(self) -> [u32; 4] {
53    unsafe { core::mem::transmute(self) }
54  }
55
56  /// Converts from the bit patterns of these floats (`[u32;4]`).
57  ///
58  /// Like [`f32::from_bits`](f32::from_bits), but all four lanes at once.
59  #[must_use]
60  #[inline(always)]
61  pub fn from_bits(bits: [u32; 4]) -> Self {
62    unsafe { core::mem::transmute(bits) }
63  }
64}
65
66impl Clone for m128 {
67  #[must_use]
68  #[inline(always)]
69  fn clone(&self) -> Self {
70    *self
71  }
72}
73impl Copy for m128 {}
74
75impl Default for m128 {
76  #[must_use]
77  #[inline(always)]
78  fn default() -> Self {
79    unsafe { core::mem::zeroed() }
80  }
81}
82
83impl From<[f32; 4]> for m128 {
84  #[must_use]
85  #[inline(always)]
86  fn from(arr: [f32; 4]) -> Self {
87    // Safety: because this semantically moves the value from the input position
88    // (align4) 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<m128> for [f32; 4] {
95  #[must_use]
96  #[inline(always)]
97  fn from(m: m128) -> 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 m128 {
108  /// Debug formats each float.
109  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
110    write!(f, "m128(")?;
111    for (i, float) in self.to_array().iter().enumerate() {
112      if i != 0 {
113        write!(f, ", ")?;
114      }
115      Debug::fmt(float, f)?;
116    }
117    write!(f, ")")
118  }
119}
120
121impl Display for m128 {
122  /// Display formats each float, and leaves the type name off of the font.
123  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
124    write!(f, "(")?;
125    for (i, float) in self.to_array().iter().enumerate() {
126      if i != 0 {
127        write!(f, ", ")?;
128      }
129      Display::fmt(float, f)?;
130    }
131    write!(f, ")")
132  }
133}
134
135impl Binary for m128 {
136  /// Binary formats each float's bit pattern (via [`f32::to_bits`]).
137  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
138    write!(f, "(")?;
139    for (i, float) in self.to_array().iter().enumerate() {
140      if i != 0 {
141        write!(f, ", ")?;
142      }
143      Binary::fmt(&float.to_bits(), f)?;
144    }
145    write!(f, ")")
146  }
147}
148
149impl LowerExp for m128 {
150  /// LowerExp formats each float.
151  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
152    write!(f, "(")?;
153    for (i, float) in self.to_array().iter().enumerate() {
154      if i != 0 {
155        write!(f, ", ")?;
156      }
157      LowerExp::fmt(float, f)?;
158    }
159    write!(f, ")")
160  }
161}
162
163impl UpperExp for m128 {
164  /// UpperExp formats each float.
165  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
166    write!(f, "(")?;
167    for (i, float) in self.to_array().iter().enumerate() {
168      if i != 0 {
169        write!(f, ", ")?;
170      }
171      UpperExp::fmt(float, f)?;
172    }
173    write!(f, ")")
174  }
175}
176
177impl LowerHex for m128 {
178  /// LowerHex formats each float's bit pattern (via [`f32::to_bits`]).
179  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
180    write!(f, "(")?;
181    for (i, float) in self.to_array().iter().enumerate() {
182      if i != 0 {
183        write!(f, ", ")?;
184      }
185      LowerHex::fmt(&float.to_bits(), f)?;
186    }
187    write!(f, ")")
188  }
189}
190
191impl UpperHex for m128 {
192  /// UpperHex formats each float's bit pattern (via [`f32::to_bits`]).
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      UpperHex::fmt(&float.to_bits(), f)?;
200    }
201    write!(f, ")")
202  }
203}
204
205impl Octal for m128 {
206  /// Octal formats each float's bit pattern (via [`f32::to_bits`]).
207  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
208    write!(f, "(")?;
209    for (i, float) in self.to_array().iter().enumerate() {
210      if i != 0 {
211        write!(f, ", ")?;
212      }
213      Octal::fmt(&float.to_bits(), f)?;
214    }
215    write!(f, ")")
216  }
217}