Floating-point representation v0.1.0
CopySign
pub func CopySign(
magnitude: float64,
sign: float64
) -> float64
pub func CopySign(
magnitude: float32,
sign: float32
) -> float32
magnitude carrying the sign of sign.
Works on every value including NaNs and zeros, since it moves one bit and reads no others.
| Overload | Summary |
|---|---|
pub func CopySign(magnitude: float64, sign: float64) -> float64 | magnitude carrying the sign of sign. |
pub func CopySign(magnitude: float32, sign: float32) -> float32 | Copies the sign of sign onto magnitude at float32 precision. |
Parameters
| Name | Type | Description |
|---|---|---|
magnitude | float64 / float32 | value supplying every bit except the sign |
sign | float64 / float32 | value supplying the sign bit |
Returns: the magnitude of magnitude with the sign of sign
NextAfter
pub func NextAfter(
from: float64,
toward: float64
) -> float64
pub func NextAfter(
from: float32,
toward: float32
) -> float32
The value adjacent to from in the direction of toward.
One representable value in that direction, subnormals and zeros included: stepping down from the smallest positive
normal lands in the subnormals rather than jumping to zero, and stepping down from +0.0 gives the smallest
negative subnormal rather than -0.0. from equal to toward returns toward, which is what makes the sign of a
zero come from the destination. A NaN in either argument gives a NaN.
| Overload | Summary |
|---|---|
pub func NextAfter(from: float64, toward: float64) -> float64 | The value adjacent to from in the direction of toward. |
pub func NextAfter(from: float32, toward: float32) -> float32 | Finds the float32 value adjacent to from in the direction of toward. |
Parameters
| Name | Type | Description |
|---|---|---|
from | float64 / float32 | starting value |
toward | float64 / float32 | direction selected by another value |
Returns: the value adjacent to from toward toward, or toward when they compare equal
NextUp
pub func NextUp(value: float64) -> float64
pub func NextUp(value: float32) -> float32
Finds the next float32 value above value.
| Overload | Summary |
|---|---|
pub func NextUp(value: float64) -> float64 | The next representable value above value. |
pub func NextUp(value: float32) -> float32 | Finds the next float32 value above value. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | starting value |
Returns: the adjacent value toward positive infinity
NextDown
pub func NextDown(value: float64) -> float64
pub func NextDown(value: float32) -> float32
Finds the next float32 value below value.
| Overload | Summary |
|---|---|
pub func NextDown(value: float64) -> float64 | The next representable value below value. |
pub func NextDown(value: float32) -> float32 | Finds the next float32 value below value. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | starting value |
Returns: the adjacent value toward negative infinity
ScaleByPowerOfTwo
pub func ScaleByPowerOfTwo(
value: float64,
exponent: int64
) -> float64
pub func ScaleByPowerOfTwo(
value: float32,
exponent: int64
) -> float32
value multiplied by two raised to exponent, with one rounding.
The obvious spelling - multiplying by a computed power of two - overflows for large exponents and rounds twice when
the answer lands in the subnormals. This steps in bounded pieces so neither happens: the result is correctly rounded
once, and an exponent far outside the range saturates to an infinity or a zero rather than wrapping the exponent
field into a wrong answer.
| Overload | Summary |
|---|---|
pub func ScaleByPowerOfTwo(value: float64, exponent: int64) -> float64 | value multiplied by two raised to exponent, with one rounding. |
pub func ScaleByPowerOfTwo(value: float32, exponent: int64) -> float32 | Multiplies value by two raised to exponent at float32 precision. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | value to scale |
exponent | int64 | binary exponent added to value |
Returns: value * 2^exponent, rounded once
ExponentOf
pub func ExponentOf(value: float64) -> int64
pub func ExponentOf(value: float32) -> int64
The exponent of value: the power of two of its most significant bit.
A normal value's exponent is such that its magnitude lies in [2^e, 2^(e+1)); a subnormal reports the exponent it
would have with unbounded range, so the relationship keeps holding into the subnormals. Zero has no exponent and
reports NoExponent, and a NaN or infinity reports IndeterminateExponent; both are values far outside any real
exponent, so neither can be mistaken for one.
| Overload | Summary |
|---|---|
pub func ExponentOf(value: float64) -> int64 | The exponent of value: the power of two of its most significant bit. |
pub func ExponentOf(value: float32) -> int64 | Extracts the binary exponent of value at float32 precision. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | value whose exponent is extracted |
Returns: its binary exponent, NoExponent for zero, or IndeterminateExponent for a NaN or infinity
NoExponent
pub const NoExponent: int64 = int64::Min;
What ExponentOf reports for zero, which has no exponent at all.
IndeterminateExponent
pub const IndeterminateExponent: int64 = int64::Max;
What ExponentOf reports for a NaN or an infinity.
Decompose
pub func Decompose(
value: float64,
exponent: *var int64
) -> float64
pub func Decompose(
value: float32,
exponent: *var int64
) -> float32
Splits value into a fraction in [0.5, 1) and a power of two, so that fraction * 2^exponent == value.
The classic decomposition. Zero gives zero with an exponent of zero, and a NaN or infinity is returned unchanged
with an exponent of zero - neither has a decomposition, and inventing one would be worse than returning the value
itself. The sign stays with the fraction. exponent must be non-null and writable.
| Overload | Summary |
|---|---|
pub func Decompose(value: float64, exponent: *var int64) -> float64 | Splits value into a fraction in [0.5, 1) and a power of two, so that fraction * 2^exponent == value. |
pub func Decompose(value: float32, exponent: *var int64) -> float32 | Decomposes value into a float32 fraction and a binary exponent. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | value to decompose |
exponent | *var int64 | receives the binary exponent |
Returns: the signed fraction, normally with magnitude in [0.5, 1)
SplitIntegral
pub func SplitIntegral(
value: float64,
integral: *var float64
) -> float64
pub func SplitIntegral(
value: float32,
integral: *var float32
) -> float32
Splits value into its integral and fractional parts, both carrying its sign.
integral receives the part toward zero and the fractional part is returned, so the two always sum back to value
exactly. An infinity puts itself in integral and returns a zero of the same sign; a NaN puts a NaN in both.
integral must be non-null and writable.
| Overload | Summary |
|---|---|
pub func SplitIntegral(value: float64, integral: *var float64) -> float64 | Splits value into its integral and fractional parts, both carrying its sign. |
pub func SplitIntegral(value: float32, integral: *var float32) -> float32 | Splits value into integral and fractional float32 parts. |
Parameters
| Name | Type | Description |
|---|---|---|
value | float64 / float32 | value to split |
integral | *var float64 / *var float32 | receives the part rounded toward zero |
Returns: the signed fractional part
UlpDistance
pub func UlpDistance(
left: float64,
right: float64
) -> uint64
pub func UlpDistance(
left: float32,
right: float32
) -> uint64
How many representable values lie between left and right.
The natural way to state a floating-point error bound: two values are one ulp apart when nothing is representable
between them, and a function accurate to half an ulp returns the nearest representable value to the true answer.
Counting steps rather than subtracting is what makes the measure meaningful near zero, where the absolute difference
between neighbours is vanishingly small, and near the maximum, where it is enormous. Values of opposite sign are
counted through zero, with the two zeros treated as one value - the step from the smallest negative subnormal to the
smallest positive one is two, not three. A NaN in either argument has no distance and reports the largest uint64,
which no real distance can reach.
| Overload | Summary |
|---|---|
pub func UlpDistance(left: float64, right: float64) -> uint64 | How many representable values lie between left and right. |
pub func UlpDistance(left: float32, right: float32) -> uint64 | Counts the representable float32 values between left and right. |
Parameters
| Name | Type | Description |
|---|---|---|
left | float64 / float32 | first value |
right | float64 / float32 | second value |
Returns: their distance in representable values, or the largest uint64 when either is a NaN