std::softfloat
IEEE 754 arithmetic on the bits of floats, with integer instructions only, rounding to nearest with ties to even like the hardware: what a CPU without a floating-point unit uses (std/bare.volt hands these to LLVM under the names it calls, __adddf3 and the rest). The f64 code follows compiler-rt's generic soft-float; the f32 operations go through f64 and round once more, which gives the exact f32 result for +, -, * and / (53 bits is more than twice 24, plus two). The f128 operations are the f64 ones on u128 bits; on aarch64 macOS, whose C runtime has no quad routines, and on os=none, which has no C runtime, they're exported under compiler-rt's names (namespace quad_rt, at the end).
Source: std/softfloat.volt
Functions
std::softfloat::clz64
fn clz64(x: u64) -> i32the number of leading zero bits of x (64 for 0)
std::softfloat::shift_sticky
fn shift_sticky(x: u64, by: i32) -> u64x >> by, with a 1 in the lowest bit when anything nonzero was shifted out ("sticky")
std::softfloat::pack64
fn pack64(sign: u64, exp0: i32, sig0: u64) -> u64the result from its sign, biased exponent and significand: the significand's leading 1 at bit 55 (for exp >= 1), its low three bits the guard, round and sticky bits. Below the smallest normal the significand shifts right (a subnormal, or zero); past the largest it's infinity
std::softfloat::pack32
fn pack32(sign: u32, exp0: i32, sig0: u64) -> u32the same for an f32: the significand's leading 1 at bit 26, three rounding bits below it
std::softfloat::is_nan
fn is_nan(a: u64) -> boolstd::softfloat::unpack
fn unpack(a: u64, sig: u64&, exp: i32&) -> voida finite nonzero |a|'s significand (leading 1 at bit 52) and exponent, subnormals normalized (their exponent goes to 0 or below)
std::softfloat::add64
fn add64(a: u64, b: u64) -> u64std::softfloat::sub64
fn sub64(a: u64, b: u64) -> u64std::softfloat::mul_wide
fn mul_wide(a: u64, b: u64, hi: u64&, lo: u64&) -> voidthe 128-bit product of a and b, from 32-bit pieces (32-bit cores have no 64-bit multiply high)
std::softfloat::mul64
fn mul64(a: u64, b: u64) -> u64std::softfloat::div64
fn div64(a: u64, b: u64) -> u64std::softfloat::cmp64
fn cmp64(a: u64, b: u64) -> i32-1, 0 or 1 as a is less than, equal to or greater than b; 2 when either is NaN. -0 equals 0
std::softfloat::f32_to_f64
fn f32_to_f64(a: u32) -> u64std::softfloat::f64_to_f32
fn f64_to_f32(a: u64) -> u32std::softfloat::u64_to_f64
fn u64_to_f64(neg: bool, v: u64) -> u64an integer's magnitude, and whether it's negative, as an f64 or f32 (rounded once)
std::softfloat::u64_to_f32
fn u64_to_f32(neg: bool, v: u64) -> u32std::softfloat::i64_to_f64
fn i64_to_f64(v: i64) -> u64std::softfloat::i64_to_f32
fn i64_to_f32(v: i64) -> u32std::softfloat::f64_to_magnitude
fn f64_to_magnitude(a: u64, bits: i32) -> u64a's integer part (toward zero) as an unsigned magnitude no wider than bits, saturating past it; NaN gives the largest
std::softfloat::f64_to_i64
fn f64_to_i64(a: u64) -> i64std::softfloat::f64_to_u64
fn f64_to_u64(a: u64) -> u64std::softfloat::f64_to_i32
fn f64_to_i32(a: u64) -> i32std::softfloat::f64_to_u32
fn f64_to_u32(a: u64) -> u32std::softfloat::add32
fn add32(a: u32, b: u32) -> u32std::softfloat::sub32
fn sub32(a: u32, b: u32) -> u32std::softfloat::mul32
fn mul32(a: u32, b: u32) -> u32std::softfloat::div32
fn div32(a: u32, b: u32) -> u32std::softfloat::cmp32
fn cmp32(a: u32, b: u32) -> i32std::softfloat::clz128
fn clz128(x: u128) -> i32std::softfloat::shift_sticky128
fn shift_sticky128(x: u128, by: i32) -> u128std::softfloat::pack128
fn pack128(sign: u128, exp0: i32, sig0: u128) -> u128pack64's f128 twin: the significand's leading 1 at bit 115, three rounding bits below it
std::softfloat::is_nan128
fn is_nan128(a: u128) -> boolstd::softfloat::unpack128
fn unpack128(a: u128, sig: u128&, exp: i32&) -> voida finite nonzero |a|'s significand (leading 1 at bit 112) and exponent, subnormals normalized
std::softfloat::add128
fn add128(a: u128, b: u128) -> u128std::softfloat::sub128
fn sub128(a: u128, b: u128) -> u128std::softfloat::mul_wide64
fn mul_wide64(a: u64, b: u64) -> u128the 64-bit halves' product as a u128 (from mul_wide: no 128-bit multiply needed)
std::softfloat::mul128
fn mul128(a: u128, b: u128) -> u128std::softfloat::div128
fn div128(a: u128, b: u128) -> u128std::softfloat::cmp128
fn cmp128(a: u128, b: u128) -> i32-1, 0 or 1 as a is less than, equal to or greater than b; 2 when either is NaN
std::softfloat::widen128
fn widen128(a: u64, fbits: i32, ebits: i32) -> u128a narrower float's bits (f16, f32 or f64: fbits fraction bits under ebits exponent bits) as an f128, exactly; a NaN keeps its payload, quieted
std::softfloat::narrow128
fn narrow128(a: u128, fbits: i32, ebits: i32) -> u64an f128 rounded to a narrower float (widen128's parameters), its bits in the low end of a u64
std::softfloat::f16_to_f128
fn f16_to_f128(a: u16) -> u128std::softfloat::f32_to_f128
fn f32_to_f128(a: u32) -> u128std::softfloat::f64_to_f128
fn f64_to_f128(a: u64) -> u128std::softfloat::f128_to_f16
fn f128_to_f16(a: u128) -> u16std::softfloat::f128_to_f32
fn f128_to_f32(a: u128) -> u32std::softfloat::f128_to_f64
fn f128_to_f64(a: u128) -> u64std::softfloat::u128_to_f128
fn u128_to_f128(neg: bool, v: u128) -> u128an integer's magnitude, and whether it's negative, as an f128 (exact up to 113 bits)
std::softfloat::i128_to_f128
fn i128_to_f128(v: i128) -> u128std::softfloat::f128_to_magnitude
fn f128_to_magnitude(a: u128, bits: i32) -> u128a's integer part (toward zero) as an unsigned magnitude no wider than bits, saturating past it; NaN gives the largest
std::softfloat::f128_to_signed
fn f128_to_signed(a: u128, bits: i32) -> i128to a signed integer of bits bits (32, 64 or 128), saturating by the sign bit as compiler-rt does: a NaN gives the largest, or the smallest when its sign bit is set
std::softfloat::f128_to_unsigned
fn f128_to_unsigned(a: u128, bits: i32) -> u128std::softfloat::rem128
fn rem128(a: u128, b: u128) -> u128the remainder of a / b with a's sign, exact (C's fmod, which can't round: the remainder is a binary128 itself): the significands reduced a bit of the exponent gap at a time by shifting and subtracting (no 128-bit division, which bare metal doesn't have), stopping early at a zero remainder; at most about 32900 steps for the widest gap
std::softfloat::volt_f128_rem
export fn volt_f128_rem(x: f128, y: f128) -> f128f128 % for both backends (voltc calls it for every f128 remainder, on every target)
std::softfloat::parse128
fn parse128(text: str) -> u128the binary128 nearest the unsigned decimal number text spells (digits, _ between them, an optional fraction and e/E exponent), ties to even: num / den exactly, its quotient taken to 116 or 117 bits by long division, the remainder sticky, and pack128 rounding (subnormals, inf)
std::softfloat::quad_rt::b
fn b(v: f128) -> u128std::softfloat::quad_rt::q
fn q(v: u128) -> f128std::softfloat::quad_rt::le
fn le(x: f128, y: f128) -> i32as libgcc's: <0, 0 or >0 like x - y; a NaN gives 1 to eq/ne/lt/le, -1 to ge/gt
std::softfloat::quad_rt::ge
fn ge(x: f128, y: f128) -> i32std::softfloat::quad_rt::unord
fn unord(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__addtf3
export fn __addtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::apple::__subtf3
export fn __subtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::apple::__multf3
export fn __multf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::apple::__divtf3
export fn __divtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::apple::__negtf2
export fn __negtf2(x: f128) -> f128std::softfloat::quad_rt::apple::__eqtf2
export fn __eqtf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__netf2
export fn __netf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__lttf2
export fn __lttf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__letf2
export fn __letf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__getf2
export fn __getf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__gttf2
export fn __gttf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__unordtf2
export fn __unordtf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::apple::__extendhftf2
export fn __extendhftf2(x: f16) -> f128std::softfloat::quad_rt::apple::__extendsftf2
export fn __extendsftf2(x: f32) -> f128std::softfloat::quad_rt::apple::__extenddftf2
export fn __extenddftf2(x: f64) -> f128std::softfloat::quad_rt::apple::__trunctfhf2
export fn __trunctfhf2(x: f128) -> f16std::softfloat::quad_rt::apple::__trunctfsf2
export fn __trunctfsf2(x: f128) -> f32std::softfloat::quad_rt::apple::__trunctfdf2
export fn __trunctfdf2(x: f128) -> f64std::softfloat::quad_rt::apple::__fixtfsi
export fn __fixtfsi(x: f128) -> i32std::softfloat::quad_rt::apple::__fixtfdi
export fn __fixtfdi(x: f128) -> i64std::softfloat::quad_rt::apple::__fixtfti
export fn __fixtfti(x: f128) -> i128std::softfloat::quad_rt::apple::__fixunstfsi
export fn __fixunstfsi(x: f128) -> u32std::softfloat::quad_rt::apple::__fixunstfdi
export fn __fixunstfdi(x: f128) -> u64std::softfloat::quad_rt::apple::__fixunstfti
export fn __fixunstfti(x: f128) -> u128std::softfloat::quad_rt::apple::__floatsitf
export fn __floatsitf(i: i32) -> f128std::softfloat::quad_rt::apple::__floatditf
export fn __floatditf(i: i64) -> f128std::softfloat::quad_rt::apple::__floattitf
export fn __floattitf(i: i128) -> f128std::softfloat::quad_rt::apple::__floatunsitf
export fn __floatunsitf(i: u32) -> f128std::softfloat::quad_rt::apple::__floatunditf
export fn __floatunditf(i: u64) -> f128std::softfloat::quad_rt::apple::__floatuntitf
export fn __floatuntitf(i: u128) -> f128std::softfloat::quad_rt::bare::__addtf3
export fn __addtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::bare::__subtf3
export fn __subtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::bare::__multf3
export fn __multf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::bare::__divtf3
export fn __divtf3(x: f128, y: f128) -> f128std::softfloat::quad_rt::bare::__negtf2
export fn __negtf2(x: f128) -> f128std::softfloat::quad_rt::bare::__eqtf2
export fn __eqtf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__netf2
export fn __netf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__lttf2
export fn __lttf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__letf2
export fn __letf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__getf2
export fn __getf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__gttf2
export fn __gttf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__unordtf2
export fn __unordtf2(x: f128, y: f128) -> i32std::softfloat::quad_rt::bare::__extendhftf2
export fn __extendhftf2(x: f16) -> f128std::softfloat::quad_rt::bare::__extendsftf2
export fn __extendsftf2(x: f32) -> f128std::softfloat::quad_rt::bare::__extenddftf2
export fn __extenddftf2(x: f64) -> f128std::softfloat::quad_rt::bare::__trunctfhf2
export fn __trunctfhf2(x: f128) -> f16std::softfloat::quad_rt::bare::__trunctfsf2
export fn __trunctfsf2(x: f128) -> f32std::softfloat::quad_rt::bare::__trunctfdf2
export fn __trunctfdf2(x: f128) -> f64std::softfloat::quad_rt::bare::__fixtfsi
export fn __fixtfsi(x: f128) -> i32std::softfloat::quad_rt::bare::__fixtfdi
export fn __fixtfdi(x: f128) -> i64std::softfloat::quad_rt::bare::__fixtfti
export fn __fixtfti(x: f128) -> i128std::softfloat::quad_rt::bare::__fixunstfsi
export fn __fixunstfsi(x: f128) -> u32std::softfloat::quad_rt::bare::__fixunstfdi
export fn __fixunstfdi(x: f128) -> u64std::softfloat::quad_rt::bare::__fixunstfti
export fn __fixunstfti(x: f128) -> u128std::softfloat::quad_rt::bare::__floatsitf
export fn __floatsitf(i: i32) -> f128std::softfloat::quad_rt::bare::__floatditf
export fn __floatditf(i: i64) -> f128std::softfloat::quad_rt::bare::__floattitf
export fn __floattitf(i: i128) -> f128std::softfloat::quad_rt::bare::__floatunsitf
export fn __floatunsitf(i: u32) -> f128std::softfloat::quad_rt::bare::__floatunditf
export fn __floatunditf(i: u64) -> f128std::softfloat::quad_rt::bare::__floatuntitf
export fn __floatuntitf(i: u128) -> f128Globals
val SIGN: u64 = 0x8000000000000000val INF: u64 = 0x7FF0000000000000val FRAC: u64 = 0x000FFFFFFFFFFFFFval IMPLICIT: u64 = 0x0010000000000000val QUIET: u64 = 0x0008000000000000val NAN: u64 = 0x7FF8000000000000val Q_ABS: u128 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFval Q_INF: u128 = 0x7FFF0000000000000000000000000000val Q_FRAC: u128 = 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFval Q_IMPLICIT: u128 = 0x00010000000000000000000000000000val Q_QUIET: u128 = 0x00008000000000000000000000000000val Q_NAN: u128 = 0x7FFF8000000000000000000000000000