Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 64 additions & 5 deletions library/core/src/intrinsics/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,68 @@ impl<T: PointeeSized, U: PointeeSized> ChangePointee<U> for *const T {
///
/// # Safety
/// Must actually *be* such a type.
pub unsafe trait FloatPrimitive: Sized + Copy {}
#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
pub const unsafe trait FloatPrimitive: Sized + Copy {
type UInt: const core::ops::BitOr<Output = Self::UInt>
+ const core::ops::BitAnd<Output = Self::UInt>
+ const core::ops::Not<Output = Self::UInt>;
const SIGN_MASK: Self::UInt;
fn to_bits(self) -> Self::UInt;
fn from_bits(bits: Self::UInt) -> Self;
}

#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
const unsafe impl FloatPrimitive for f16 {
type UInt = u16;
const SIGN_MASK: Self::UInt = f16::SIGN_MASK;
#[inline]
fn to_bits(self) -> Self::UInt {
f16::to_bits(self)
}
#[inline]
fn from_bits(bits: Self::UInt) -> Self {
f16::from_bits(bits)
}
}
Comment on lines +57 to +69

@N1ark N1ark Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be macro'd if you'd rather i have no strong opinions on that

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's hold off on using macros, this seems manageable now and a macro won't work for fallbacks that need a per-type implementation (e.g. sin or fma)


#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
const unsafe impl FloatPrimitive for f32 {
type UInt = u32;
const SIGN_MASK: Self::UInt = f32::SIGN_MASK;
#[inline]
fn to_bits(self) -> Self::UInt {
f32::to_bits(self)
}
#[inline]
fn from_bits(bits: Self::UInt) -> Self {
f32::from_bits(bits)
}
}

#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
const unsafe impl FloatPrimitive for f64 {
type UInt = u64;
const SIGN_MASK: Self::UInt = f64::SIGN_MASK;
#[inline]
fn to_bits(self) -> Self::UInt {
f64::to_bits(self)
}
#[inline]
fn from_bits(bits: Self::UInt) -> Self {
f64::from_bits(bits)
}
}

unsafe impl FloatPrimitive for f16 {}
unsafe impl FloatPrimitive for f32 {}
unsafe impl FloatPrimitive for f64 {}
unsafe impl FloatPrimitive for f128 {}
#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
const unsafe impl FloatPrimitive for f128 {
type UInt = u128;
const SIGN_MASK: Self::UInt = f128::SIGN_MASK;
#[inline]
fn to_bits(self) -> Self::UInt {
f128::to_bits(self)
}
#[inline]
fn from_bits(bits: Self::UInt) -> Self {
f128::from_bits(bits)
}
}
6 changes: 5 additions & 1 deletion library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3628,9 +3628,13 @@ pub const fn maximumf128(x: f128, y: f128) -> f128 {
/// The stabilized versions of this intrinsic are available on the float
/// primitives via the `abs` method. For example, [`f32::abs`].
#[rustc_nounwind]
#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
pub const fn fabs<T: bounds::FloatPrimitive>(x: T) -> T;
#[miri::intrinsic_fallback_is_spec]
pub const fn fabs<T: const bounds::FloatPrimitive>(x: T) -> T {
T::from_bits(x.to_bits() & !T::SIGN_MASK)
}
Comment on lines +3634 to +3637

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RalfJung does this spark joy? I'd much rather have the one-liner duplicated 4 times than the (trivial, but still) unsafety and const trait stuff that is required.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is whether it sparks more or less joy than copy-paste. The status quo is definitely not joyful. ;)

But yeah I agree needing unsafe is pretty bad.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it spark joy now ? ^-^

pub const fn fabs<T: const bounds::FloatPrimitive>(x: T) -> T {
    T::from_bits(x.to_bits() & !T::SIGN_MASK)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that seems exactly as readable as the per-type version, just less duplicated :)


/// Copies the sign from `y` to `x` for `f16` values.
///
Expand Down
Loading