1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
use super::sealed::Sealed;
use crate::simd::{
intrinsics, LaneCount, Mask, Simd, SimdElement, SimdPartialEq, SimdPartialOrd,
SupportedLaneCount,
};
/// 对浮点数的 SIMD vectors 的操作。
pub trait SimdFloat: Copy + Sealed {
/// 用于操作此 SIMD vector 类型的掩码类型。
type Mask;
/// 此 SIMD vector 类型包含的标量类型。
type Scalar;
/// 此 SIMD vector 类型的位表示。
type Bits;
/// 原始转换为无符号整数 vector 类型,其大小和数量与 lanes 相同。
///
#[must_use = "method returns a new vector and does not mutate the original value"]
fn to_bits(self) -> Self::Bits;
/// 来自具有相同大小和数量的 lanes 的无符号整数 vector 类型的原始变换。
///
#[must_use = "method returns a new vector and does not mutate the original value"]
fn from_bits(bits: Self::Bits) -> Self;
/// 生成一个 vector,其中每个 lane 都具有 `self` 中等效索引 lane 的绝对值。
///
#[must_use = "method returns a new vector and does not mutate the original value"]
fn abs(self) -> Self;
/// 获取每个 lane 的倒数 (inverse),`1/x`。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn recip(self) -> Self;
/// 将每个 lane 从弧度转换为度数。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn to_degrees(self) -> Self;
/// 将每个 lane 从度数转换为弧度。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn to_radians(self) -> Self;
/// 如果每个 lane 具有正号,则为每个 lane 返回 true,包括 `+0.0`、具有正符号位的 `NaN` 和正无穷大。
///
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_sign_positive(self) -> Self::Mask;
/// 如果每个 lane 具有负号,则为每个 lane 返回 true,包括 `-0.0`、具有负符号位的 `NaN` 和负无穷大。
///
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_sign_negative(self) -> Self::Mask;
/// 如果每个 lane 的值为 `NaN`,则为每个 lane 返回 true。
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_nan(self) -> Self::Mask;
/// 如果每个 lane 的值是正无穷大或负无穷大,则为每个 lane 返回 true。
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_infinite(self) -> Self::Mask;
/// 如果每个 lane 的值既不是无穷大也不是 `NaN`,则为每个 lane 返回 true。
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_finite(self) -> Self::Mask;
/// 如果每个 lane 的值为 subnormal,则为每个 lane 返回 true。
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_subnormal(self) -> Self::Mask;
/// 如果 lane 的值既不是零、无限、subnormal 也不是 `NaN`,则为每个 lane 返回 true。
///
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_normal(self) -> Self::Mask;
/// 用代表其符号的数字替换每个 lane。
///
/// * `1.0` 如果数字是正数,`+0.0` 或 `INFINITY`
/// * `-1.0` 如果数字是负数,`-0.0` 或 `NEG_INFINITY`
/// * `NAN` 如果数字是 `NAN`
#[must_use = "method returns a new vector and does not mutate the original value"]
fn signum(self) -> Self;
/// 以 `self` 的大小和 `sign` 的符号返回每个 lane。
///
/// 对于任何包含 `NAN` 的 lane,将返回带有 `sign` 符号的 `NAN`。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn copysign(self, sign: Self) -> Self;
/// 返回每个 lane 的最小值。
///
/// 如果其中一个值为 `NAN`,则返回另一个值。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn simd_min(self, other: Self) -> Self;
/// 返回每个 lane 的最大值。
///
/// 如果其中一个值为 `NAN`,则返回另一个值。
#[must_use = "method returns a new vector and does not mutate the original value"]
fn simd_max(self, other: Self) -> Self;
/// 将每个 lane 限制在一定的区间内,除非它是 NaN。
///
/// 对于 `self` 中的每个 lane,如果 lane 大于 `max`,则返回 `max` 中对应的 lane,如果 lane 小于 `min`,则返回 `min` 中对应的 lane。
/// 否则返回 `self` 中的 lane。
///
#[must_use = "method returns a new vector and does not mutate the original value"]
fn simd_clamp(self, min: Self, max: Self) -> Self;
/// 返回 vector 的 lane 的总和。
///
/// # Examples
///
/// ```
/// # #![feature(portable_simd)]
/// # #[cfg(feature = "as_crate")] use core_simd::simd;
/// # #[cfg(not(feature = "as_crate"))] use core::simd;
/// # use simd::{f32x2, SimdFloat};
/// let v = f32x2::from_array([1., 2.]);
/// assert_eq!(v.reduce_sum(), 3.);
/// ```
fn reduce_sum(self) -> Self::Scalar;
/// 减少乘。返回 vector 的 lanes 的乘积。
///
/// # Examples
///
/// ```
/// # #![feature(portable_simd)]
/// # #[cfg(feature = "as_crate")] use core_simd::simd;
/// # #[cfg(not(feature = "as_crate"))] use core::simd;
/// # use simd::{f32x2, SimdFloat};
/// let v = f32x2::from_array([3., 4.]);
/// assert_eq!(v.reduce_product(), 12.);
/// ```
fn reduce_product(self) -> Self::Scalar;
/// 返回 vector 中的最大 lane。
///
/// 返回基于相等的值,因此包含 `0.` 和 `-0.` 的 vector 可以返回任意一个值。
///
///
/// 这个函数不会返回 `NaN`,除非所有的 lane 都是 `NaN`。
///
/// # Examples
///
/// ```
/// # #![feature(portable_simd)]
/// # #[cfg(feature = "as_crate")] use core_simd::simd;
/// # #[cfg(not(feature = "as_crate"))] use core::simd;
/// # use simd::{f32x2, SimdFloat};
/// let v = f32x2::from_array([1., 2.]);
/// assert_eq!(v.reduce_max(), 2.);
///
/// // 跳过 NaN 值...
/// let v = f32x2::from_array([1., f32::NAN]);
/// assert_eq!(v.reduce_max(), 1.);
///
/// // ...除非所有值都是 NaN
/// let v = f32x2::from_array([f32::NAN, f32::NAN]);
/// assert!(v.reduce_max().is_nan());
/// ```
fn reduce_max(self) -> Self::Scalar;
/// 返回 vector 中的最小 lane。
///
/// 返回基于相等的值,因此包含 `0.` 和 `-0.` 的 vector 可以返回任意一个值。
///
///
/// 这个函数不会返回 `NaN`,除非所有的 lane 都是 `NaN`。
///
/// # Examples
///
/// ```
/// # #![feature(portable_simd)]
/// # #[cfg(feature = "as_crate")] use core_simd::simd;
/// # #[cfg(not(feature = "as_crate"))] use core::simd;
/// # use simd::{f32x2, SimdFloat};
/// let v = f32x2::from_array([3., 7.]);
/// assert_eq!(v.reduce_min(), 3.);
///
/// // 跳过 NaN 值...
/// let v = f32x2::from_array([1., f32::NAN]);
/// assert_eq!(v.reduce_min(), 1.);
///
/// // ...除非所有值都是 NaN
/// let v = f32x2::from_array([f32::NAN, f32::NAN]);
/// assert!(v.reduce_min().is_nan());
/// ```
fn reduce_min(self) -> Self::Scalar;
}
macro_rules! impl_trait {
{ $($ty:ty { bits: $bits_ty:ty, mask: $mask_ty:ty }),* } => {
$(
impl<const LANES: usize> Sealed for Simd<$ty, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
}
impl<const LANES: usize> SimdFloat for Simd<$ty, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
type Mask = Mask<<$mask_ty as SimdElement>::Mask, LANES>;
type Scalar = $ty;
type Bits = Simd<$bits_ty, LANES>;
#[inline]
fn to_bits(self) -> Simd<$bits_ty, LANES> {
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
// 安全性: 在 vector 类型之间转换是安全的
unsafe { core::mem::transmute_copy(&self) }
}
#[inline]
fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self {
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
// 安全性: 在 vector 类型之间转换是安全的
unsafe { core::mem::transmute_copy(&bits) }
}
#[inline]
fn abs(self) -> Self {
// 安全性: `self` 是一个浮点数 vector
unsafe { intrinsics::simd_fabs(self) }
}
#[inline]
fn recip(self) -> Self {
Self::splat(1.0) / self
}
#[inline]
fn to_degrees(self) -> Self {
// to_degrees 使用一个特殊的常量来获得更好的精度,所以提取这个常量
self * Self::splat(Self::Scalar::to_degrees(1.))
}
#[inline]
fn to_radians(self) -> Self {
self * Self::splat(Self::Scalar::to_radians(1.))
}
#[inline]
fn is_sign_positive(self) -> Self::Mask {
!self.is_sign_negative()
}
#[inline]
fn is_sign_negative(self) -> Self::Mask {
let sign_bits = self.to_bits() & Simd::splat((!0 >> 1) + 1);
sign_bits.simd_gt(Simd::splat(0))
}
#[inline]
fn is_nan(self) -> Self::Mask {
self.simd_ne(self)
}
#[inline]
fn is_infinite(self) -> Self::Mask {
self.abs().simd_eq(Self::splat(Self::Scalar::INFINITY))
}
#[inline]
fn is_finite(self) -> Self::Mask {
self.abs().simd_lt(Self::splat(Self::Scalar::INFINITY))
}
#[inline]
fn is_subnormal(self) -> Self::Mask {
self.abs().simd_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(Self::Scalar::INFINITY).to_bits()).simd_eq(Simd::splat(0))
}
#[inline]
#[must_use = "method returns a new mask and does not mutate the original value"]
fn is_normal(self) -> Self::Mask {
!(self.abs().simd_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite())
}
#[inline]
fn signum(self) -> Self {
self.is_nan().select(Self::splat(Self::Scalar::NAN), Self::splat(1.0).copysign(self))
}
#[inline]
fn copysign(self, sign: Self) -> Self {
let sign_bit = sign.to_bits() & Self::splat(-0.).to_bits();
let magnitude = self.to_bits() & !Self::splat(-0.).to_bits();
Self::from_bits(sign_bit | magnitude)
}
#[inline]
fn simd_min(self, other: Self) -> Self {
// 安全性: `self` 和 `other` 是浮动 vectors
unsafe { intrinsics::simd_fmin(self, other) }
}
#[inline]
fn simd_max(self, other: Self) -> Self {
// 安全性: `self` 和 `other` 是浮点 vectors
unsafe { intrinsics::simd_fmax(self, other) }
}
#[inline]
fn simd_clamp(self, min: Self, max: Self) -> Self {
assert!(
min.simd_le(max).all(),
"each lane in `min` must be less than or equal to the corresponding lane in `max`",
);
let mut x = self;
x = x.simd_lt(min).select(min, x);
x = x.simd_gt(max).select(max, x);
x
}
#[inline]
fn reduce_sum(self) -> Self::Scalar {
// i586 上的 LLVM 总和不准确
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
self.as_array().iter().sum()
} else {
// 安全性: `self` 是一个浮点数 vector
unsafe { intrinsics::simd_reduce_add_ordered(self, 0.) }
}
}
#[inline]
fn reduce_product(self) -> Self::Scalar {
// LLVM 产品在 i586 上不准确
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
self.as_array().iter().product()
} else {
// 安全性: `self` 是一个浮点数 vector
unsafe { intrinsics::simd_reduce_mul_ordered(self, 1.) }
}
}
#[inline]
fn reduce_max(self) -> Self::Scalar {
// 安全性: `self` 是一个浮点数 vector
unsafe { intrinsics::simd_reduce_max(self) }
}
#[inline]
fn reduce_min(self) -> Self::Scalar {
// 安全性: `self` 是一个浮点数 vector
unsafe { intrinsics::simd_reduce_min(self) }
}
}
)*
}
}
impl_trait! { f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } }