Struct Subspace :: sus :: num :: f32

struct f32 final
{ ... };

A 32-bit floating point type.

This type can represent a wide range of decimal numbers, like 3.5, 27, -113.75, 0.0078125, 34359738368, 0, -1. So unlike integer types (such as i32), floating point types can represent non-integer numbers, too. Specifically, this type holds the same values as the float type specified by the C++ standard.

See the namespace level documentation for more.

Static Data Members

static const u32 DIGITS

Approximate number of significant digits in base 10.

static const f32 EPSILON

Machine epsilon value for f32.

This is the difference between 1.0 and the next larger representable number.

static const f32 INFINITY

Infinity.

Approximate number of significant digits in base 2.

static const f32 MAX

Largest finite f32.

static const i32 MAX_10_EXP

Maximum possible power of 10 exponent.

static const i32 MAX_EXP

Maximum possible power of 2 exponent.

static const float MAX_PRIMITIVE

Largest finite primitive value.

static const f32 MIN

Smallest finite f32.

static const i32 MIN_10_EXP

Minimum possible normal power of 10 exponent.

static const i32 MIN_EXP

One greater than the minimum possible normal power of 2 exponent.

static const f32 MIN_POSITIVE

Smallest positive normal f32 value.

static const float MIN_PRIMITIVE

Smallest finite primitive value.

static const f32 NAN

Not a Number (NaN).

Note that IEEE-745 doesn't define just a single NaN value; a plethora of bit patterns are considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern). This constant isn't guaranteed to equal to any specific NaN bitpattern, and the stability of its representation over Subspace versions and target platforms isn't guaranteed.

This value is not constexpr because the value can differ in a constexpr evaluation context from a runtime context, leading to bugs.

static const f32 NEG_INFINITY

Negative infinity.

static const u32 RADIX

The radix or base of the internal representation of f32.

Static Methods

template <class P>
f32(P v)
requires
sus::num::PrimitiveFloat<P>
::sus::mem::size_of<P>() <= ::sus::mem::size_of<_primitive>()

Construction from primitive types where no bits are lost.

template <class F>
f32(F v)
requires
sus::num::Float<F>
::sus::mem::size_of<F>() <= ::sus::mem::size_of<_primitive>()

Construction from floating point types where no bits are lost.

Default constructor, which sets the value to 0.

Satisfies the Default concept.

template <class F>
static auto from(F v) -> f32
requires
sus::num::Float<F>
::sus::mem::size_of<F>() <= ::sus::mem::size_of<_primitive>()

Construction from floating point types where no bits are lost.

template <class P>
static auto from(P v) -> f32
requires
sus::num::PrimitiveFloat<P>
::sus::mem::size_of<P>() <= ::sus::mem::size_of<_primitive>()

Construction from primitive floating point types where no bits are lost.

template <class I>
static auto from(I v) -> f32
requires
sus::num::Integer<I>
::sus::mem::size_of<I>() * 8 <=
           __private::num_mantissa_digits<_primitive>()

Construction from integer types where no bits are lost.

For f32 this includes integer types up to 16 bits. For f64 this includes integer types up to 32 bits.

template <class P>
static auto from(P v) -> f32
requires
sus::num::PrimitiveInteger<P>
::sus::mem::size_of<P>() * 8 <=
           __private::num_mantissa_digits<_primitive>()

Construction from integer types where no bits are lost.

For f32 this includes integer types up to 16 bits. For f64 this includes integer types up to 32 bits.

static auto from_be_bytes(const Array<u8, ::sus::mem::size_of<_primitive>()>& bytes) -> f32

Create a floating point value from its representation as a byte array in big endian.

See from_bits for why this function is not constexpr.

static auto from_bits(u32 v) -> f32

Raw transmutation from ##_unsigned##.

This is identical to std::bit_cast<f32, u32>, or std::bit_cast<f64, u64>. It turns out this is incredibly portable, for two reasons:

  • Floats and Ints have the same endianness on all modern platforms.
  • IEEE 754 very precisely specifies the bit layout of floats.

However there is one caveat: prior to the 2008 version of IEEE 754, how to interpret the NaN signaling bit wasn’t actually specified. Most platforms (notably x86 and ARM) picked the interpretation that was ultimately standardized in 2008, but some didn’t (notably MIPS). As a result, all signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.

Rather than trying to preserve signaling-ness cross-platform, this implementation favors preserving the exact bits. This means that any payloads encoded in NaNs will be preserved even if the result of this method is sent over the network from an x86 machine to a MIPS one.

If the results of this method are only manipulated by the same architecture that produced them, then there is no portability concern.

If the input isn’t NaN, then there is no portability concern.

If you don’t care about signalingness (very likely), then there is no portability concern.

Note that this function is distinct from Cast casting, which attempts to preserve the numeric value, and not the bitwise value.

Examples

auto v = f32::from_bits(0x41480000);
sus::check!(v, 12.5);

This function is not constexpr, as converting a NaN does not preserve the exact bits in a constexpr context.

static auto from_le_bytes(const Array<u8, ::sus::mem::size_of<_primitive>()>& bytes) -> f32

Create a floating point value from its representation as a byte array in big endian.

See from_bits for why this function is not constexpr.

static auto from_ne_bytes(const Array<u8, ::sus::mem::size_of<_primitive>()>& bytes) -> f32

Create a floating point value from its representation as a byte array in native endian.

As the target platform's native endianness is used, portable code likely wants to use from_be_bytes or from_le_bytes, as appropriate instead.

See from_bits for why this function is not constexpr.

static auto from_product(Iterator<f32> auto&& it) -> f32
requires
sus::mem::IsMoveRef<decltype(it)>

Constructs a f32 from an Iterator by computing the product of all elements in the iterator.

This method should rarely be called directly, as it is used to satisfy the Product concept so that Iterator::product() can be called for iterators over f32 .

static auto from_sum(Iterator<f32> auto&& it) -> f32
requires
sus::mem::IsMoveRef<decltype(it)>

Constructs a f32 from an Iterator by computing the sum of all elements in the iterator.

This method should rarely be called directly, as it is used to satisfy the Sum concept so that Iterator::sum() can be called for iterators over f32 .

Methods

auto abs() const& -> f32
auto acos() const& -> f32

Computes the arccosine of a number. Return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1].

auto acosh() const& -> f32

Inverse hyperbolic cosine function, or NaN if the number is less than -1.

auto as_mut_ptr() & -> float*

Returns a mutable pointer to the underlying C++ primitive value type.

This allows Subspace numerics be used with APIs that expect a pointer to a C++ primitive type.

auto as_ptr() const& -> const float*
auto as_ptr() && -> const float*
deleted

Returns a const pointer to the underlying C++ primitive value type.

This allows Subspace numerics be used with APIs that expect a pointer to a C++ primitive type.

auto asin() const& -> f32

Computes the arcsine of a number. Return value is in radians in the range [-pi/2, pi/2] or NaN if the number is outside the range [-1, 1].

auto asinh() const& -> f32

Inverse hyperbolic sine function.

auto atan() const& -> f32

Computes the arctangent of a number. Return value is in radians in the range [-pi/2, pi/2];

auto atan2(f32 other) const& -> f32

Computes the four quadrant arctangent of self (y) and other (x) in radians.

  • x = 0, y = 0: 0
  • x >= 0: arctan(y/x) -> [-pi/2, pi/2]
  • y >= 0: arctan(y/x) + pi -> (pi/2, pi]
  • y < 0: arctan(y/x) - pi -> (-pi, -pi/2)

Returns NaN if both self and other are 0.

auto atanh() const& -> f32

Inverse hyperbolic tangent function.

auto cbrt() const& -> f32

Returns the cube root of a number.

auto ceil() const& -> f32

Returns the smallest integer greater than or equal to self.

auto clamp(f32 min, f32 max) const& -> f32

Restrict a value to a certain interval unless it is NaN.

Returns max if self is greater than max, and min if self is less than min. Otherwise this returns self.

Note that this function returns NaN if the initial value was NaN as well.

Panics

Panics if min > max, min is NaN, or max is NaN.

auto classify() const& -> sus::num::FpCategory

Returns the floating point category of the number.

If only one property is going to be tested, it is generally faster to use the specific predicate instead.

auto copysign(f32 sign) const& -> f32

Returns a number composed of the magnitude of self and the sign of sign.

Equal to self if the sign of self and sign are the same, otherwise equal to -self. If self is a NaN, then a NaN with the sign bit of sign is returned. Note, however, that conserving the sign bit on NaN across arithmetical operations is not generally guaranteed.

auto cos() const& -> f32

Computes the cosine of a number (in radians).

auto cosh() const& -> f32

Hyperbolic cosine function.

auto div_euclid(f32 rhs) const& -> f32

Calculates Euclidean division, the matching method for rem_euclid.

This computes the integer n such that self = n * rhs + self.rem_euclid(rhs). In other words, the result is self / rhs rounded to the integer n such that self >= n * rhs.

auto exp() const& -> f32

Returns e^(self), (the exponential function).

auto exp2() const& -> f32

Returns 2^(self).

auto exp_m1() const& -> f32

Returns e^(self) - 1 in a way that is accurate even if the number is close to zero.

auto floor() const& -> f32

Returns the largest integer less than or equal to self.

auto fract() const& -> f32
auto hypot(f32 other) const& -> f32

Calculates the length of the hypotenuse of a right-angle triangle given legs of length x and y.

auto is_finite() const& -> bool

Returns true if this number is neither infinite nor NaN.

auto is_infinite() const& -> bool

Returns true if this value is positive infinity or negative infinity, and false otherwise.

auto is_nan() const& -> bool

Returns true if this value is NaN.

auto is_normal() const& -> bool

Returns true if the number is neither zero, infinite, subnormal, or NaN.

auto is_sign_negative() const& -> bool

Returns true if self has a negative sign, including -0.0, NaNs with negative sign bit and negative infinity.

Note that IEEE-745 doesn't assign any meaning to the sign bit in case of a NaN

auto is_sign_positive() const& -> bool

Returns true if self has a positive sign, including +0.0, NaNs with positive sign bit and positive infinity.

Note that IEEE-745 doesn't assign any meaning to the sign bit in case of a NaN.

auto is_subnormal() const& -> bool

Returns true if the number is subnormal.

auto ln() const& -> f32

Returns the natural logarithm of the number.

auto ln_1p() const& -> f32

Returns ln(1+n) (natural logarithm) more accurately than if the operations were performed separately.

auto log(f32 base) const& -> f32

Returns the logarithm of the number with respect to an arbitrary base.

The result might not be correctly rounded owing to implementation details; self.log2() can produce more accurate results for base 2, and self.log10() can produce more accurate results for base 10.

auto log10() const& -> f32

Returns the base 10 logarithm of the number.

auto log2() const& -> f32

Returns the base 2 logarithm of the number.

auto max(f32 other) const& -> f32

Returns the maximum of the two numbers, ignoring NaN.

If one of the arguments is NaN, then the other argument is returned.

auto min(f32 other) const& -> f32

Returns the minimum of the two numbers, ignoring NaN.

If one of the arguments is NaN, then the other argument is returned.

auto mul_add(f32 a, f32 b) const& -> f32

Fused multiply-add. Computes (self * a) + b with only one rounding error, yielding a more accurate result than an unfused multiply-add.

Using mul_add may be more performant than an unfused multiply-add if the target architecture has a dedicated fma CPU instruction. However, this is not always true, and will be heavily dependent on designing algorithms with specific target hardware in mind.

auto next_toward(f32 toward) const& -> f32

Returns the next representable value of the float type after self in the direction of toward. If self == toward, toward is returned. If either self or toward is NAN, NAN is returned.

This is implemented by the cmath library, see the documentation for details on errors.

auto powf(f32 n) const& -> f32

Raises a number to a floating point power.

auto powi(i32 n) const& -> f32

Raises a number to an integer point power.

Using this function may be faster than using powf. It might have a different sequence of rounding operations than powf, so the results are not guaranteed to agree.

auto recip() const& -> f32

Takes the reciprocal (inverse) of a number, 1/x.

auto rem_euclid(f32 rhs) const& -> f32

Calculates the least nonnegative remainder of self (mod rhs).

In particular, the return value r satisfies 0.0 <= r < rhs.abs() in most cases. However, due to a floating point round-off error it can result in r == rhs.abs(), violating the mathematical definition, if self is much smaller than rhs.abs() in magnitude and self < 0.0. This result is not an element of the function's codomain, but it is the closest floating point number in the real numbers and thus fulfills the property self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs) approximately.

auto round() const& -> f32

Returns the nearest integer to self. If a value is half-way between two integers, round away from 0.0.

This rounding behaviour matches the behaviour of the std::round standard library function, but is much slower and less conformant than round_ties which often makes the latter a better choice.

If self is a NaN, infinity, or zero, the same will be returned, though a different NaN may be returned.

As in Rust's round, this method preserves the sign bit when the result is -0.0, but this is unlike std::round.

auto round_ties() const& -> f32

Returns the nearest integer to self. If a value is half-way between two integers, respects the current rounding mode. The default mode will round ties to the nearest even number.

This rounding operation is faster and more standard conformant than round, making it generally preferable. However it breaks with the legacy behaviour of std::round.

If self is a NaN, infinity, or zero, the same will be returned, though a different NaN may be returned.

Rust has the unstable round_ties_even method that always uses the FE_TONEAREST rounding mode. In C++ the rounding mode can be controlled by the user with std::fesetround.

As in Rust's round and with std::nearbyint, this method preserves the sign bit when the result is -0.0.

auto round_to_i16() const& -> i16

Returns the nearest i16 representable by self.

This is equivalent to sus::cast<i16>(self.round_ties()) but it may require fewer instructions on some platforms.

Like round_ties, but unlike round, the current rounding mode will be respected to break ties. The default mode will round ties to the nearest even number.

A NaN input will return 0.

auto round_to_i32() const& -> i32

Returns the nearest i32 representable by self.

This is equivalent to sus::cast<i32>(self.round_ties()) but it may require fewer instructions on some platforms.

Like round_ties, but unlike round, the current rounding mode will be respected to break ties. The default mode will round ties to the nearest even number.

A NaN input will return 0.

auto round_to_i64() const& -> i64

Returns the nearest i64 representable by self.

This is equivalent to sus::cast<i64>(self.round_ties()) but it may require fewer instructions on some platforms.

Like round_ties, but unlike round, the current rounding mode will be respected to break ties. The default mode will round ties to the nearest even number.

A NaN input will return 0.

auto round_to_i8() const& -> i8

Returns the nearest i8 representable by self.

This is equivalent to sus::cast<i8>(self.round_ties()) but it may require fewer instructions on some platforms.

Like round_ties, but unlike round, the current rounding mode will be respected to break ties. The default mode will round ties to the nearest even number.

A NaN input will return 0.

auto round_to_isize() const& -> isize

Returns the nearest isize representable by self.

This is equivalent to sus::cast<isize>(self.round_ties()) but it may require fewer instructions on some platforms.

Like round_ties, but unlike round, the current rounding mode will be respected to break ties. The default mode will round ties to the nearest even number.

A NaN input will return 0.

auto signum() const& -> f32

Returns a number that represents the sign of self.

  • 1.0 if the number is positive, +0.0 or INFINITY.
  • -1.0 if the number is negative, -0.0 or NEG_INFINITY.
  • NaN if the number is NaN. The input value is returned exactly, preserving signaling NaNs.
auto sin() const& -> f32

Computes the sine of a number (in radians).

auto sinh() const& -> f32

Hyperbolic sine function.

auto sqrt() const& -> f32

Returns the square root of a number.

Returns NaN if self is a negative number other than -0.0.

auto tan() const& -> f32

Computes the tangent of a number (in radians).

auto tanh() const& -> f32

Hyperbolic tangent function.

auto to_be_bytes() const& -> Array<u8, ::sus::mem::size_of<_primitive>()>

Return the memory representation of this floating point number as a byte array in big-endian (network) byte order.

auto to_bits() const& -> u32

Raw transmutation to ##UnsignedT##.

This is identical to std::bit_cast<u32, f32>, or std::bit_cast<u64, f64>.

See from_bits() for some discussion of the portability of this operation (there are almost no issues).

Note that this function is distinct from Cast casting, which attempts to preserve the numeric value, and not the bitwise value.

auto to_degrees() const& -> f32

Converts radians to degrees.

template <class Int>
auto to_int_unchecked(UnsafeFnMarker) const& -> Int
requires
sus::num::Integer<Int>

Rounds toward zero and converts to any safe integer type assuming that the value is finite and fits in that type.

Safety

To avoid Undefined Behaviour, the value must:

  • Not be NaN.
  • Not be infinite.
  • Be representable in the return type Int, after truncating off its fractional part.
auto to_le_bytes() const& -> Array<u8, ::sus::mem::size_of<_primitive>()>

Return the memory representation of this floating point number as a byte array in little-endian byte order.

auto to_ne_bytes() const& -> Array<u8, ::sus::mem::size_of<_primitive>()>

Return the memory representation of this floating point number as a byte array in native byte order.

As the target platform's native endianness is used, portable code should use to_be_bytes or to_le_bytes, as appropriate, instead.

auto to_radians() const& -> f32

Converts degrees to radians.

auto total_cmp(f32 other) const& -> std::weak_ordering

Return the ordering between *this and other.

Unlike the standard partial comparison between floating point numbers, this comparison always produces an ordering in accordance to the totalOrder predicate as defined in the IEEE 754 (2008 revision) floating point standard. The values are ordered in the following sequence:

negative quiet NaN negative signaling NaN negative infinity negative numbers negative subnormal numbers negative zero positive zero positive subnormal numbers positive numbers positive infinity positive signaling NaN positive quiet NaN.

The ordering established by this function does not always agree with the PartialOrd and Eq implementations of f32. For example, they consider negative and positive zero equal, while total_cmp doesn't.

The interpretation of the signaling NaN bit follows the definition in the IEEE 754 standard, which may not match the interpretation by some of the older, non-conformant (e.g. MIPS) hardware implementations.

Why does this method satisfy Ord and not StrongOrd?

This method returns std::weak_ordering which can be used in situations that require Ord because different NaNs will be ordered equivalently.

auto trunc() const& -> f32

Returns the integer part of self. This means that non-integer numbers are always truncated towards zero.

Conversions

template <class U>
operator U() const
requires
sus::num::PrimitiveFloat<U>
::sus::mem::size_of<U>() >= ::sus::mem::size_of<_primitive>()

Conversion from the numeric type to a C++ primitive type.

This converts to floating point primitives which are at least as large as the f32.

auto d = double{3_f64};  // Compiles.
auto e = double(3_f64);  // Compiles.
double f = 3_f64;  // Compiles.

auto d = float{3_f64};  // Does not compile.
auto e = float(3_f64);  // Does not compile.
float f = 3_f64;  // Does not compile.

Potentially-lossy type conversions can be forced through the Cast concept, such as sus::cast<float>(3_f64) or sus::cast<f32>(3_f64).

Operators

auto operator%=(f32 r) & -> void

Satisfies the RemAssign<f32> concept.

Assigns the remainder from the division of two floats.

The remainder has the same sign as the dividend and is computed as: l - (l / r).trunc() * r.

auto operator*=(f32 r) & -> void

Satisfies the MulAssign<f32> concept.

auto operator+=(f32 r) & -> void

Satisfies the AddAssign<f32> concept.

auto operator-() const -> f32

Satisfies the Neg<f32> concept.

auto operator-=(f32 r) & -> void

Satisfies the SubAssign<f32> concept.

auto operator/=(f32 r) & -> void

Satisfies the DivAssign<f32> concept.

template <class F>
auto operator=(F v) -> f32&
requires
sus::num::Float<F>
::sus::mem::size_of<F>() <= ::sus::mem::size_of<_primitive>()

Assignment from floating point types where no bits are lost.

template <class P>
auto operator=(P v) -> f32&
requires
sus::num::PrimitiveFloat<P>
::sus::mem::size_of<P>() <= ::sus::mem::size_of<_primitive>()

Assignment from primitive types where no bits are lost.

Data Members

The inner primitive value. Prefer to cast to the desired primitive type, such as with float{n} for a numeric value n.