Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
rust source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
mrustc (master)
rustc 1.0.0
rustc 1.1.0
rustc 1.10.0
rustc 1.11.0
rustc 1.12.0
rustc 1.13.0
rustc 1.14.0
rustc 1.15.1
rustc 1.16.0
rustc 1.17.0
rustc 1.18.0
rustc 1.19.0
rustc 1.2.0
rustc 1.20.0
rustc 1.21.0
rustc 1.22.0
rustc 1.23.0
rustc 1.24.0
rustc 1.25.0
rustc 1.26.0
rustc 1.27.0
rustc 1.27.1
rustc 1.28.0
rustc 1.29.0
rustc 1.3.0
rustc 1.30.0
rustc 1.31.0
rustc 1.32.0
rustc 1.33.0
rustc 1.34.0
rustc 1.35.0
rustc 1.36.0
rustc 1.37.0
rustc 1.38.0
rustc 1.39.0
rustc 1.4.0
rustc 1.40.0
rustc 1.41.0
rustc 1.42.0
rustc 1.43.0
rustc 1.44.0
rustc 1.45.0
rustc 1.45.2
rustc 1.46.0
rustc 1.47.0
rustc 1.48.0
rustc 1.49.0
rustc 1.5.0
rustc 1.50.0
rustc 1.51.0
rustc 1.52.0
rustc 1.53.0
rustc 1.54.0
rustc 1.55.0
rustc 1.56.0
rustc 1.57.0
rustc 1.58.0
rustc 1.59.0
rustc 1.6.0
rustc 1.60.0
rustc 1.61.0
rustc 1.62.0
rustc 1.63.0
rustc 1.64.0
rustc 1.65.0
rustc 1.66.0
rustc 1.67.0
rustc 1.68.0
rustc 1.69.0
rustc 1.7.0
rustc 1.70.0
rustc 1.71.0
rustc 1.72.0
rustc 1.73.0
rustc 1.74.0
rustc 1.75.0
rustc 1.76.0
rustc 1.77.0
rustc 1.78.0
rustc 1.79.0
rustc 1.8.0
rustc 1.80.0
rustc 1.81.0
rustc 1.9.0
rustc beta
rustc nightly
rustc-cg-gcc (master)
x86-64 GCCRS (GCC master)
x86-64 GCCRS (GCCRS master)
x86-64 GCCRS 14.1 (GCC)
x86-64 GCCRS 14.2 (GCC)
Options
Source code
pub fn f64tof32(a: f64) -> f32 { trunc(a) } fn trunc<F: Float, R: Float>(a: F) -> R where F::Int: CastInto<u64>, F::Int: CastInto<u32>, u64: CastInto<F::Int>, u32: CastInto<F::Int>, R::Int: CastInto<u32>, u32: CastInto<R::Int>, F::Int: CastInto<R::Int>, { let src_zero = F::Int::ZERO; let src_one = F::Int::ONE; let src_bits = F::BITS; let src_exp_bias = F::EXPONENT_BIAS; let src_min_normal = F::IMPLICIT_BIT; let src_significand_mask = F::SIGNIFICAND_MASK; let src_infinity = F::EXPONENT_MASK; let src_sign_mask = F::SIGN_MASK; let src_abs_mask = src_sign_mask - src_one; let round_mask = (src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)) - src_one; let halfway = src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS - 1); let src_qnan = src_one << (F::SIGNIFICAND_BITS - 1); let src_nan_code = src_qnan - src_one; let dst_zero = R::Int::ZERO; let dst_one = R::Int::ONE; let dst_bits = R::BITS; let dst_inf_exp = R::EXPONENT_MAX; let dst_exp_bias = R::EXPONENT_BIAS; let underflow_exponent: F::Int = (src_exp_bias + 1 - dst_exp_bias).cast(); let overflow_exponent: F::Int = (src_exp_bias + dst_inf_exp - dst_exp_bias).cast(); let underflow: F::Int = underflow_exponent << F::SIGNIFICAND_BITS; let overflow: F::Int = overflow_exponent << F::SIGNIFICAND_BITS; let dst_qnan = R::Int::ONE << (R::SIGNIFICAND_BITS - 1); let dst_nan_code = dst_qnan - dst_one; let sign_bits_delta = F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS; // Break a into a sign and representation of the absolute value. let a_abs = a.repr() & src_abs_mask; let sign = a.repr() & src_sign_mask; let mut abs_result: R::Int; if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) { // The exponent of a is within the range of normal numbers in the // destination format. We can convert by simply right-shifting with // rounding and adjusting the exponent. abs_result = (a_abs >> sign_bits_delta).cast(); let tmp = src_exp_bias.wrapping_sub(dst_exp_bias) << R::SIGNIFICAND_BITS; abs_result = abs_result.wrapping_sub(tmp.cast()); let round_bits = a_abs & round_mask; if round_bits > halfway { // Round to nearest. abs_result += dst_one; } else if round_bits == halfway { // Tie to even. abs_result += abs_result & dst_one; }; } else if a_abs > src_infinity { // a is NaN. // Conjure the result by beginning with infinity, setting the qNaN // bit and inserting the (truncated) trailing NaN field. abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast(); abs_result |= dst_qnan; abs_result |= dst_nan_code & ((a_abs & src_nan_code) >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast(); } else if a_abs >= overflow { // a overflows to infinity. abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast(); } else { // a underflows on conversion to the destination type or is an exact // zero. The result may be a denormal or zero. Extract the exponent // to get the shift amount for the denormalization. let a_exp: u32 = (a_abs >> F::SIGNIFICAND_BITS).cast(); let shift = src_exp_bias - dst_exp_bias - a_exp + 1; let significand = (a.repr() & src_significand_mask) | src_min_normal; // Right shift by the denormalization amount with sticky. if shift > F::SIGNIFICAND_BITS { abs_result = dst_zero; } else { let sticky = if (significand << (src_bits - shift)) != src_zero { src_one } else { src_zero }; let denormalized_significand: F::Int = significand >> shift | sticky; abs_result = (denormalized_significand >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast(); let round_bits = denormalized_significand & round_mask; // Round to nearest if round_bits > halfway { abs_result += dst_one; } // Ties to even else if round_bits == halfway { abs_result += abs_result & dst_one; }; } } // Apply the signbit to the absolute value. R::from_repr(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast()) } use std::ops; pub(crate) trait Float: Copy + core::fmt::Debug + PartialEq + PartialOrd + ops::AddAssign + ops::MulAssign + ops::Add<Output = Self> + ops::Sub<Output = Self> + ops::Div<Output = Self> + ops::Rem<Output = Self> { /// A uint of the same width as the float type Int: Int; /// A int of the same width as the float type SignedInt: Int; /// An int capable of containing the exponent bits plus a sign bit. This is signed. type ExpInt: Int; const ZERO: Self; const ONE: Self; /// The bitwidth of the float type const BITS: u32; /// The bitwidth of the significand const SIGNIFICAND_BITS: u32; /// The bitwidth of the exponent const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1; /// The maximum value of the exponent const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1; /// The exponent bias value const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1; /// A mask for the sign bit const SIGN_MASK: Self::Int; /// A mask for the significand const SIGNIFICAND_MASK: Self::Int; const IMPLICIT_BIT: Self::Int; /// A mask for the exponent const EXPONENT_MASK: Self::Int; /// Returns `self` transmuted to `Self::Int` fn repr(self) -> Self::Int; /// Returns `self` transmuted to `Self::SignedInt` fn signed_repr(self) -> Self::SignedInt; /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be /// represented in multiple different ways. This method returns `true` if two NaNs are /// compared. fn eq_repr(self, rhs: Self) -> bool; /// Returns the sign bit fn sign(self) -> bool; /// Returns the exponent with bias fn exp(self) -> Self::ExpInt; /// Returns the significand with no implicit bit (or the "fractional" part) fn frac(self) -> Self::Int; /// Returns the significand with implicit bit fn imp_frac(self) -> Self::Int; /// Returns a `Self::Int` transmuted back to `Self` fn from_repr(a: Self::Int) -> Self; /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position. fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self; /// Returns (normalized exponent, normalized significand) fn normalize(significand: Self::Int) -> (i32, Self::Int); /// Returns if `self` is subnormal fn is_subnormal(self) -> bool; } impl Float for f32 { type Int = u32; type SignedInt = i32; type ExpInt = i16; const ZERO: Self = 0.0; const ONE: Self = 1.0; const BITS: u32 = 32; const SIGNIFICAND_BITS: u32 = 23; const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1; const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS; const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK); #[inline] fn repr(self) -> Self::Int { self.to_bits() } #[inline] fn signed_repr(self) -> Self::SignedInt { self.to_bits() as Self::SignedInt } fn eq_repr(self, rhs: Self) -> bool { if self.is_nan() && rhs.is_nan() { true } else { self.repr() == rhs.repr() } } #[inline] fn sign(self) -> bool { self.signed_repr() < Self::SignedInt::ZERO } #[inline] fn exp(self) -> Self::ExpInt { ((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as Self::ExpInt } #[inline] fn frac(self) -> Self::Int { self.to_bits() & Self::SIGNIFICAND_MASK } #[inline] fn imp_frac(self) -> Self::Int { self.frac() | Self::IMPLICIT_BIT } #[inline] fn from_repr(a: Self::Int) -> Self { Self::from_bits(a) } #[inline] fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { Self::from_repr( ((sign as Self::Int) << (Self::BITS - 1)) | ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) | (significand & Self::SIGNIFICAND_MASK), ) } fn normalize(significand: Self::Int) -> (i32, Self::Int) { let shift = significand .leading_zeros() .wrapping_sub( (Self::Int::ONE << Self::SIGNIFICAND_BITS).leading_zeros(), ); (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) } #[inline] fn is_subnormal(self) -> bool { (self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO } } impl Float for f64 { type Int = u64; type SignedInt = i64; type ExpInt = i16; const ZERO: Self = 0.0; const ONE: Self = 1.0; const BITS: u32 = 64; const SIGNIFICAND_BITS: u32 = 52; const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1; const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS; const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK); #[inline] fn repr(self) -> Self::Int { self.to_bits() } #[inline] fn signed_repr(self) -> Self::SignedInt { self.to_bits() as Self::SignedInt } fn eq_repr(self, rhs: Self) -> bool { if self.is_nan() && rhs.is_nan() { true } else { self.repr() == rhs.repr() } } #[inline] fn sign(self) -> bool { self.signed_repr() < Self::SignedInt::ZERO } #[inline] fn exp(self) -> Self::ExpInt { ((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as Self::ExpInt } #[inline] fn frac(self) -> Self::Int { self.to_bits() & Self::SIGNIFICAND_MASK } #[inline] fn imp_frac(self) -> Self::Int { self.frac() | Self::IMPLICIT_BIT } #[inline] fn from_repr(a: Self::Int) -> Self { Self::from_bits(a) } #[inline] fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { Self::from_repr( ((sign as Self::Int) << (Self::BITS - 1)) | ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) | (significand & Self::SIGNIFICAND_MASK), ) } fn normalize(significand: Self::Int) -> (i32, Self::Int) { let shift = significand .leading_zeros() .wrapping_sub( (Self::Int::ONE << Self::SIGNIFICAND_BITS).leading_zeros(), ); (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) } #[inline] fn is_subnormal(self) -> bool { (self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO } } pub(crate) trait CastInto<T: Copy>: Copy { fn cast(self) -> T; } impl CastInto<u64> for u32 { fn cast(self) -> u64 { self as _ } } impl CastInto<u32> for u32 { fn cast(self) -> u32 { self as _ } } impl CastInto<u64> for u64 { fn cast(self) -> u64 { self as _ } } impl CastInto<u32> for u64 { fn cast(self) -> u32 { self as _ } } trait Int: Copy + core::fmt::Debug + PartialEq + PartialOrd + ops::AddAssign + ops::SubAssign + ops::BitAndAssign + ops::BitOrAssign + ops::BitXorAssign + ops::ShlAssign<i32> + ops::ShrAssign<u32> + ops::Add<Output = Self> + ops::Sub<Output = Self> + ops::Div<Output = Self> + ops::Shl<u32, Output = Self> + ops::Shr<u32, Output = Self> + ops::BitOr<Output = Self> + ops::BitXor<Output = Self> + ops::BitAnd<Output = Self> + ops::Not<Output = Self> { const ZERO: Self; const ONE: Self; fn wrapping_sub(self, other: Self) -> Self; fn wrapping_shr(self, other: u32) -> Self; } impl Int for i32 { const ZERO: Self = 0; const ONE: Self = 1; fn wrapping_sub(self, other: Self) -> Self { <Self>::wrapping_sub(self, other) } fn wrapping_shr(self, other: u32) -> Self { <Self>::wrapping_shr(self, other) } } impl Int for i16 { const ZERO: Self = 0; const ONE: Self = 1; fn wrapping_sub(self, other: Self) -> Self { <Self>::wrapping_sub(self, other) } fn wrapping_shr(self, other: u32) -> Self { <Self>::wrapping_shr(self, other) } } impl Int for i64 { const ZERO: Self = 0; const ONE: Self = 1; fn wrapping_sub(self, other: Self) -> Self { <Self>::wrapping_sub(self, other) } fn wrapping_shr(self, other: u32) -> Self { <Self>::wrapping_shr(self, other) } } impl Int for u32 { const ZERO: Self = 0; const ONE: Self = 1; fn wrapping_sub(self, other: Self) -> Self { <Self>::wrapping_sub(self, other) } fn wrapping_shr(self, other: u32) -> Self { <Self>::wrapping_shr(self, other) } } impl Int for u64 { const ZERO: Self = 0; const ONE: Self = 1; fn wrapping_sub(self, other: Self) -> Self { <Self>::wrapping_sub(self, other) } fn wrapping_shr(self, other: u32) -> Self { <Self>::wrapping_shr(self, other) } }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree