Unsigned 64-bit arithmetic for algorithms that are specified in terms of wrapping 64-bit words: hashes, counter-based generators, fixed-point tables.
Fortran has no unsigned integer type, and signed integer overflow is not
defined by the standard. The obvious spelling of a wrapping multiply is
therefore undefined behaviour, and a build with -ftrapv or
-fsanitize=signed-integer-overflow may abort on it. Every routine here
splits its operands into limbs so that no intermediate ever leaves the
range a signed 64-bit integer can represent.
Bit manipulation goes through ibits, which is defined on the integer
bit model and is therefore correct for negative operands: a negative
integer(int64) widened through ibits keeps its two’s-complement
pattern, which is exactly the unsigned value being modelled. ishft is
used only with non-negative (left-shift) counts.
A 64-bit unsigned value is carried in an integer(int64) holding its
two’s-complement bit pattern, so values at or above 2**63 appear as
negative Fortran integers. Fortran’s own < therefore compares them as
signed; use u64_less when the unsigned ordering is wanted.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer(kind=int64), | private, | parameter | :: | MASK16 | = | 65535_int64 |
Low 16-bit mask, used by the limb arithmetic below. |
| integer(kind=int64), | private, | parameter | :: | MASK32 | = | 4294967295_int64 |
Low 32-bit mask, used by the limb arithmetic below. |
(a + b) reduced modulo 264, without ever overflowing a signed
64-bit integer. Operands are split into 32-bit halves with ibits, so
each half sum stays below 233.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int64), | intent(in) | :: | a | |||
| integer(kind=int64), | intent(in) | :: | b |
.true. when a < b with both operands read as unsigned 64-bit
values.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int64), | intent(in) | :: | a | |||
| integer(kind=int64), | intent(in) | :: | b |
(a * b) reduced modulo 2**64, without ever overflowing a signed
64-bit integer.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int64), | intent(in) | :: | a | |||
| integer(kind=int64), | intent(in) | :: | b |
Logical (zero-filling) right shift of a 64-bit word by n bits,
0 <= n <= 63. Written with ibits rather than ishft(x, -n) or the
Fortran 2008 shiftr for the portability reasons given in the module
documentation.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int64), | intent(in) | :: | x | |||
| integer(kind=default_int), | intent(in) | :: | n |