Skip to main content

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  #[inline(always)]
68  fn clone(&self) -> Self {
69    *self
70  }
71}
72impl Copy for m128 {}
73
74impl Default for m128 {
75  #[inline(always)]
76  fn default() -> Self {
77    unsafe { core::mem::zeroed() }
78  }
79}
80
81impl From<[f32; 4]> for m128 {
82  #[inline(always)]
83  fn from(arr: [f32; 4]) -> Self {
84    // Safety: because this semantically moves the value from the input position
85    // (align4) to the output position (align16) it is fine to increase our
86    // required alignment without worry.
87    unsafe { core::mem::transmute(arr) }
88  }
89}
90
91impl From<m128> for [f32; 4] {
92  #[inline(always)]
93  fn from(m: m128) -> 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 m128 {
104  /// Debug formats each float.
105  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
106    write!(f, "m128(")?;
107    for (i, float) in self.to_array().iter().enumerate() {
108      if i != 0 {
109        write!(f, ", ")?;
110      }
111      Debug::fmt(float, f)?;
112    }
113    write!(f, ")")
114  }
115}
116
117impl Display for m128 {
118  /// Display formats each float, and leaves the type name off of the font.
119  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
120    write!(f, "(")?;
121    for (i, float) in self.to_array().iter().enumerate() {
122      if i != 0 {
123        write!(f, ", ")?;
124      }
125      Display::fmt(float, f)?;
126    }
127    write!(f, ")")
128  }
129}
130
131impl Binary for m128 {
132  /// Binary formats each float's bit pattern (via [`f32::to_bits`]).
133  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
134    write!(f, "(")?;
135    for (i, float) in self.to_array().iter().enumerate() {
136      if i != 0 {
137        write!(f, ", ")?;
138      }
139      Binary::fmt(&float.to_bits(), f)?;
140    }
141    write!(f, ")")
142  }
143}
144
145impl LowerExp for m128 {
146  /// LowerExp formats each float.
147  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
148    write!(f, "(")?;
149    for (i, float) in self.to_array().iter().enumerate() {
150      if i != 0 {
151        write!(f, ", ")?;
152      }
153      LowerExp::fmt(float, f)?;
154    }
155    write!(f, ")")
156  }
157}
158
159impl UpperExp for m128 {
160  /// UpperExp formats each float.
161  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
162    write!(f, "(")?;
163    for (i, float) in self.to_array().iter().enumerate() {
164      if i != 0 {
165        write!(f, ", ")?;
166      }
167      UpperExp::fmt(float, f)?;
168    }
169    write!(f, ")")
170  }
171}
172
173impl LowerHex for m128 {
174  /// LowerHex formats each float's bit pattern (via [`f32::to_bits`]).
175  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
176    write!(f, "(")?;
177    for (i, float) in self.to_array().iter().enumerate() {
178      if i != 0 {
179        write!(f, ", ")?;
180      }
181      LowerHex::fmt(&float.to_bits(), f)?;
182    }
183    write!(f, ")")
184  }
185}
186
187impl UpperHex for m128 {
188  /// UpperHex formats each float's bit pattern (via [`f32::to_bits`]).
189  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
190    write!(f, "(")?;
191    for (i, float) in self.to_array().iter().enumerate() {
192      if i != 0 {
193        write!(f, ", ")?;
194      }
195      UpperHex::fmt(&float.to_bits(), f)?;
196    }
197    write!(f, ")")
198  }
199}
200
201impl Octal for m128 {
202  /// Octal formats each float's bit pattern (via [`f32::to_bits`]).
203  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
204    write!(f, "(")?;
205    for (i, float) in self.to_array().iter().enumerate() {
206      if i != 0 {
207        write!(f, ", ")?;
208      }
209      Octal::fmt(&float.to_bits(), f)?;
210    }
211    write!(f, ")")
212  }
213}