stringifor_numbers
StringiFor, conversions between decimal and binary reals on 64 bit integers (internal module, not re-exported).
Fortran has no unsigned integer, and a signed overflow is not allowed: the 64 bit words are handled as bit patterns, and the arithmetic on them goes through 32 bit limbs that cannot overflow.
Source: src/lib/stringifor_numbers.F90
Dependencies
Contents
- shortest_digits
- strip_zeros
- add
- multiply
- multiply32
- decimal_to_r8
- decimal_to_r4
- floor_shift
- BIAS_BITS
- round_to_odd
- eisel_lemire
Variables
| Name | Type | Attributes | Description |
|---|---|---|---|
LOW32 | integer(kind=I8P) | parameter | The low 32 bits. |
Subroutines
shortest_digits
Return the shortest decimal digits * 10**exponent that reads back as the binary float, the closest of them if more than one (Schubfach: Giulietti, The Schubfach way to render doubles, 2020). Finite and not zero; no trailing zeros.
The float is given by its fields, so one kernel serves R4P and R8P: every step only relies on the 128 bits of the power.
Attributes: elemental
subroutine shortest_digits(fraction, biased, mantissa_bits, digits, exponent)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
fraction | integer(kind=I8P) | in | Stored mantissa. | |
biased | integer | in | Biased exponent. | |
mantissa_bits | integer | in | Bits of the stored mantissa. | |
digits | integer(kind=I8P) | out | Decimal digits. | |
exponent | integer | out | Decimal exponent. |
Call graph
strip_zeros
Move the trailing zeros of the digits to the exponent.
Attributes: elemental
subroutine strip_zeros(digits, exponent)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
digits | integer(kind=I8P) | inout | Decimal digits, not zero. | |
exponent | integer | inout | Decimal exponent. |
Call graph
add
Add two words as unsigned integers.
Attributes: elemental
subroutine add(a, b, sum, carry)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
a | integer(kind=I8P) | in | First word. | |
b | integer(kind=I8P) | in | Second word. | |
sum | integer(kind=I8P) | out | Low 64 bits of the sum. | |
carry | integer(kind=I8P) | out | Carry, 0 or 1. |
Call graph
multiply
Multiply two words as unsigned integers, 64 x 64 = 128 bits.
Attributes: elemental
subroutine multiply(a, b, high, low)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
a | integer(kind=I8P) | in | First word. | |
b | integer(kind=I8P) | in | Second word. | |
high | integer(kind=I8P) | out | High word. | |
low | integer(kind=I8P) | out | Low word. |
Call graph
multiply32
Multiply two 32 bit limbs: a product of a limb and 16 bits fits in a signed word, a product of two limbs may not.
Attributes: elemental
subroutine multiply32(a, b, high, low)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
a | integer(kind=I8P) | in | First limb. | |
b | integer(kind=I8P) | in | Second limb. | |
high | integer(kind=I8P) | out | High limb. | |
low | integer(kind=I8P) | out | Low limb. |
Call graph
Functions
decimal_to_r8
Return the real nearest to mantissa * 10**exponent, ties to even (Eisel-Lemire). Mantissa not negative.
Attributes: elemental
Returns: real(kind=R8P)
function decimal_to_r8(mantissa, exponent) result(number)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
mantissa | integer(kind=I8P) | in | Digits, as an integer. | |
exponent | integer | in | Decimal exponent. |
Call graph
decimal_to_r4
Return the real nearest to mantissa * 10**exponent, ties to even (Eisel-Lemire). Mantissa not negative.
Attributes: elemental
Returns: real(kind=R4P)
function decimal_to_r4(mantissa, exponent) result(number)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
mantissa | integer(kind=I8P) | in | Digits, as an integer. | |
exponent | integer | in | Decimal exponent. |
Call graph
floor_shift
Return floor(value / 2**bits): nvfortran has no SHIFTA, and a right shift of a negative number needs the floor.
Attributes: elemental
Returns: integer
function floor_shift(value, bits) result(shifted)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
value | integer | in | The value. | |
bits | integer | in | The bits of the shift. |
Call graph
BIAS_BITS
Return the bits of the exponent field of a format.
Attributes: elemental
Returns: integer
function BIAS_BITS(mantissa_bits) result(bits)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
mantissa_bits | integer | in | Bits of the stored mantissa. |
Call graph
round_to_odd
Return the high word of g * cp (g of 128 bits) with its lowest bit set if any bit below is set.
Attributes: elemental
Returns: integer(kind=I8P)
function round_to_odd(g_high, g_low, cp) result(rounded)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
g_high | integer(kind=I8P) | in | High word of g. | |
g_low | integer(kind=I8P) | in | Low word of g. | |
cp | integer(kind=I8P) | in | The multiplier. |
Call graph
eisel_lemire
Return the bits of the positive binary float nearest to digits * 10**q, of the format with those parameters.
The 128 bits of the table are enough for every 64 bit digits, so this has no fallback (Mushtak, Lemire, Fast Number Parsing Without Fallback, 2023); the oracle checks it against exact arithmetic.
Attributes: elemental
Returns: integer(kind=I8P)
function eisel_lemire(digits, q, mantissa_bits, bias, infinity, even_min, even_max) result(bits)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
digits | integer(kind=I8P) | in | Decimal digits, not zero. | |
q | integer | in | Decimal exponent, in the range of the table. | |
mantissa_bits | integer | in | Bits of the stored mantissa. | |
bias | integer | in | Exponent bias. | |
infinity | integer | in | Biased exponent of the infinity. | |
even_min | integer | in | Lowest q where a product can be an exact tie. | |
even_max | integer | in | Highest q where a product can be an exact tie. |
Call graph