From 05e91a3d1f61a4632572d0f26a0b787083d199d4 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgibbon Date: Thu, 6 Jun 2024 13:54:08 +0100 Subject: [PATCH] Use python ints throughout, adding float64 to test (Fixes #25, newly ailing test for float64 depending on later PR) --- src/gfloat/decode.py | 13 ++++++++----- src/gfloat/formats.py | 15 +++++++++++++++ src/gfloat/round.py | 5 +++-- test/test_encode.py | 2 ++ test/test_round.py | 2 ++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/gfloat/decode.py b/src/gfloat/decode.py index 47f1403..ffb0093 100644 --- a/src/gfloat/decode.py +++ b/src/gfloat/decode.py @@ -21,6 +21,8 @@ def decode_float(fi: FormatInfo, i: int) -> FloatValue: ValueError: If :paramref:`i` is outside the range of valid code points in :paramref:`fi`. """ + assert isinstance(i, int) + k = fi.k p = fi.precision t = p - 1 # Trailing significand field width @@ -56,13 +58,10 @@ def decode_float(fi: FormatInfo, i: int) -> FloatValue: expval = exp - expBias fsignificand = 1.0 + significand * 2**-t - # val: the raw value excluding specials - val = sign * fsignificand * 2.0**expval - - # Now overwrite the raw value with specials: Infs, NaN, -0, NaN_0 + # Handle specials: Infs, NaN, -0, NaN_0 signed_infinity = -np.inf if signbit else np.inf - fval = val + fval = None # All-bits-special exponent (ABSE) if w > 0 and exp == 2**w - 1: min_i_with_nan = 2 ** (p - 1) - fi.num_high_nans @@ -78,6 +77,10 @@ def decode_float(fi: FormatInfo, i: int) -> FloatValue: else: fval = np.nan + # In range - compute value + if fval is None: + fval = sign * fsignificand * 2.0**expval + # Compute FloatClass fclass = None if fval == 0: diff --git a/src/gfloat/formats.py b/src/gfloat/formats.py index b23cb28..2c9d026 100644 --- a/src/gfloat/formats.py +++ b/src/gfloat/formats.py @@ -3,6 +3,20 @@ from .block import BlockFormatInfo from .types import FormatInfo +#: FormatInfo for IEEE-754 Binary64 format +format_info_binary64 = FormatInfo( + name="binary64", + k=64, + precision=53, + emax=1023, + has_nz=True, + has_infs=True, + num_high_nans=2**52 - 1, + has_subnormals=True, + is_signed=True, + is_twos_complement=False, +) + #: FormatInfo for IEEE-754 Binary32 format format_info_binary32 = FormatInfo( name="binary32", @@ -204,6 +218,7 @@ def format_info_p3109(precision: int) -> FormatInfo: *_fp8_formats, *_fp16_formats, format_info_binary32, + format_info_binary64, ] # ------ diff --git a/src/gfloat/round.py b/src/gfloat/round.py index 8bec81e..3f5b78b 100644 --- a/src/gfloat/round.py +++ b/src/gfloat/round.py @@ -190,8 +190,9 @@ def encode_float(fi: FormatInfo, v: float) -> int: isig = 0 biased_exp = 0 else: - assert fi.bits < 64 # TODO: check implementation if fi is binary64 sig, exp = np.frexp(vpos) + exp = int(exp) # All calculations in Python ints + # sig in range [0.5, 1) sig *= 2 exp -= 1 @@ -225,6 +226,6 @@ def encode_float(fi: FormatInfo, v: float) -> int: isig = (1 << t) - isig # Pack values into a single integer - code = (sign << (k - 1)) | (biased_exp << t) | (isig << 0) + code = (int(sign) << (k - 1)) | (biased_exp << t) | (isig << 0) return code diff --git a/test/test_encode.py b/test/test_encode.py index de60b5c..ea5bf68 100644 --- a/test/test_encode.py +++ b/test/test_encode.py @@ -18,6 +18,8 @@ def test_encode(fi: FormatInfo) -> None: step = 13 elif fi.bits <= 32: step = 73013 + elif fi.bits <= 64: + step = (73013 << 32) + 39 for i in range(0, 2**fi.bits, step): fv = decode_float(fi, i) diff --git a/test/test_round.py b/test/test_round.py index e9719c5..2c6beb8 100644 --- a/test/test_round.py +++ b/test/test_round.py @@ -446,6 +446,8 @@ def test_round_roundtrip(fi: FormatInfo) -> None: step = 13 elif fi.bits <= 32: step = 73013 + elif fi.bits <= 64: + step = (73013 << 32) + 39 for i in range(0, 2**fi.bits, step): fv = decode_float(fi, i)