Canonicalise and feed one real(sp) value.
NaN is tested first, as the one value that is unordered with respect
to zero: neither value >= 0 nor value <= 0 holds. That ordered
form is used in preference to the more familiar value /= value
because it says the same thing without an equality test on a real,
which every compiler warns about. Infinities are then separated from
finite values by comparison against huge, so that exponent and
fraction are only ever applied to a finite, non-zero argument, and
zero is finally detected as the value that is not greater than zero in
magnitude – which is true for -0.0 as well as +0.0, and is where the
two signed zeroes become one.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int32), | intent(inout) | :: | state | |||
| real(kind=sp), | intent(in) | :: | value |
Value to encode; may be any value including -0.0, NaN and +/-Inf. |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer(kind=int64), | private | :: | class_code | ||||
| integer(kind=int64), | private | :: | expo | ||||
| integer(kind=int64), | private | :: | mantissa | ||||
| integer(kind=int64), | private | :: | sign_code |
pure subroutine feed_real_sp(state, value) !! Canonicalise and feed one `real(sp)` value. !! !! NaN is tested first, as the one value that is unordered with respect !! to zero: neither `value >= 0` nor `value <= 0` holds. That ordered !! form is used in preference to the more familiar `value /= value` !! because it says the same thing without an equality test on a real, !! which every compiler warns about. Infinities are then separated from !! finite values by comparison against `huge`, so that `exponent` and !! `fraction` are only ever applied to a finite, non-zero argument, and !! zero is finally detected as the value that is not greater than zero in !! magnitude -- which is true for -0.0 as well as +0.0, and is where the !! two signed zeroes become one. integer(int32), intent(inout) :: state real(sp), intent(in) :: value !! Value to encode; may be any value including -0.0, NaN and +/-Inf. integer(int64) :: class_code, sign_code, expo, mantissa sign_code = 0_int64 expo = 0_int64 mantissa = 0_int64 if (.not. (value >= 0.0_sp .or. value <= 0.0_sp)) then class_code = CLASS_NAN else if (value > huge(value)) then class_code = CLASS_POS_INF else if (value < -huge(value)) then class_code = CLASS_NEG_INF else if (.not. (abs(value) > 0.0_sp)) then class_code = CLASS_ZERO else class_code = CLASS_FINITE if (value < 0.0_sp) sign_code = 1_int64 expo = int(exponent(value), int64) mantissa = int(scale(fraction(abs(value)), digits(value)), int64) end if call feed_real_record(state, class_code, sign_code, expo, mantissa) end subroutine feed_real_sp