Eigenstate: myrddin-dev mailing list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] Adjust signs of fltbits functions


The fltXYbits and fltXYfrombits functions now return/take unsigned
integers uniformly, allowing easier round-tripping. Unsigned was
chosen to emphasize that the value of the result is probably unrelated
to the floating-point value.

The fltXYexplode and fltXYassem functions now return the mantissa
(significand) unsigned, but the exponent signed. This reflects the
allowed ranges represented by the encoding.
---
 lib/std/fltbits.myr      | 40 +++++++++++++++++++++-------------------
 lib/std/fltfmt.myr       |  2 +-
 lib/std/fltparse.myr     |  4 ++--
 lib/std/test/fltbits.myr | 14 +++++++++++++-
 4 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/lib/std/fltbits.myr b/lib/std/fltbits.myr
index 765ce04f..f4ddd54f 100644
--- a/lib/std/fltbits.myr
+++ b/lib/std/fltbits.myr
@@ -1,6 +1,6 @@
 pkg std =
-	const flt64bits	: (flt : flt64 -> int64)
-	const flt32bits	: (flt : flt32 -> int32)
+	const flt64bits	: (flt : flt64 -> uint64)
+	const flt32bits	: (flt : flt32 -> uint32)
 	const flt64inf	: (-> flt64)
 	const flt64nan	: (-> flt64)
 	const flt32inf	: (-> flt32)
@@ -9,28 +9,29 @@ pkg std =
 	generic isnan		: (f : @a -> bool) ::floating @a
 	const flt64frombits	: (bits : uint64 -> flt64)
 	const flt32frombits	: (bits : uint32 -> flt32)
-	const flt64explode	: (flt : flt64 -> (bool, int64, int64))
-	const flt32explode	: (flt : flt32 -> (bool, int32, int32))
-	const flt64assem	: (sign : bool, mant : int64, exp : int64 -> flt64)
-	const flt32assem	: (sign : bool, mant : int32, exp : int32 -> flt32)
+	const flt64explode	: (flt : flt64 -> (bool, uint64, int64))
+	const flt32explode	: (flt : flt32 -> (bool, uint32, int32))
+	const flt64assem	: (sign : bool, mant : uint64, exp : int64 -> flt64)
+	const flt32assem	: (sign : bool, mant : uint32, exp : int32 -> flt32)
 ;;
 
-const flt64bits	= {flt;	-> (&flt : int64#)#}
-const flt32bits	= {flt;	-> (&flt : int32#)#}
+const flt64bits	= {flt;	-> (&flt : uint64#)#}
+const flt32bits	= {flt;	-> (&flt : uint32#)#}
 const flt64frombits	= {bits;	-> (&bits : flt64#)#}
 const flt32frombits	= {bits;	-> (&bits : flt32#)#}
 
 const flt64explode = {flt
-	var bits, isneg, mant, exp
+	var bits, isneg, mant, uexp, exp
 
 	bits = flt64bits(flt)
 	isneg = (bits >> 63) != 0 	/* msb is sign bit */
-	exp = (bits >> 52) & 0x7ff 	/* exp is in bits [52..63] */
-	mant = bits & ((1l << 52) - 1)	/* msb is in bits [..51] */
+	uexp = (bits >> 52) & 0x7ff 	/* exp is in bits [52..63] */
+	mant = bits & ((1ul << 52) - 1)	/* mant is in bits [..51] */
 
 	/* add back the implicit bit if this is not a denormal */
-	if exp != 0
-		mant |= 1l << 52
+	if uexp != 0
+		mant |= 1ul << 52
+		exp = (uexp : int64)
 	else
 		exp = 1
 	;;
@@ -44,16 +45,17 @@ const flt64explode = {flt
 }
 
 const flt32explode = {flt
-	var bits, isneg, mant, exp
+	var bits, isneg, mant, uexp, exp
 
 	bits = flt32bits(flt)
 	isneg = (bits >> 31) != 0 	/* msb is sign bit */
-	exp = (bits >> 23) & 0xff	/* exp is in bits [23..30] */
-	mant = bits & ((1 << 23) - 1)	/* msb is in bits [0..22] */
+	uexp = (bits >> 23) & 0xff	/* exp is in bits [23..30] */
+	mant = bits & ((1 << 23) - 1)	/* mant is in bits [0..22] */
 
 	/* add back the implicit bit if this is not a denormal */
-	if exp != 0
+	if uexp != 0
 		mant |= 1 << 23
+		exp = (uexp : int32)
 	else
 		exp = 1
 	;;
@@ -89,8 +91,8 @@ generic isnan = {f
 	var b
 
 	b = flt64bits((f : flt64))
-	-> (b >> 52) & 0x7ffl == 0x7ffl && \
-		b & ~(0x7ffl) != 0
+	-> (b >> 52) & 0x7fful == 0x7fful && \
+		b & ~(0x7fful) != 0
 }
 
 const flt64inf = {
diff --git a/lib/std/fltfmt.myr b/lib/std/fltfmt.myr
index 2a36daf0..b0c08c42 100644
--- a/lib/std/fltfmt.myr
+++ b/lib/std/fltfmt.myr
@@ -32,7 +32,7 @@ const flt32bfmt = {sb, val, mode, precision
 	var isneg, exp, mant
 
 	(isneg, mant, exp) = flt32explode(val)
-	dragon4(sb, isneg, (mant : int64), (exp - 23 : int64), Fltbias, mode, precision)
+	dragon4(sb, isneg, (mant : uint64), (exp - 23 : int64), Fltbias, mode, precision)
 }
 
 /*
diff --git a/lib/std/fltparse.myr b/lib/std/fltparse.myr
index 9836d1f2..e88eba6d 100644
--- a/lib/std/fltparse.myr
+++ b/lib/std/fltparse.myr
@@ -125,7 +125,7 @@ type lim = struct
 	minsig	: uint64
 	maxsig	: uint64
 	loshift	: uint64
-	nextinc	: int64
+	nextinc	: uint64
 	minexp	: int16
 	maxexp	: int16
 	sigbits	: int16
@@ -265,7 +265,7 @@ const nextfloat = {z, lim
 	var za
 
 	(sign, mant, exp) = std.flt64explode(z)
-	if std.abs(mant - (1l << 52) - 1) < lim.nextinc
+	if std.abs((mant : int64) - (1l << 52) - 1) < (lim.nextinc : int64)
 		mant = 0
 		exp++
 	else
diff --git a/lib/std/test/fltbits.myr b/lib/std/test/fltbits.myr
index 4e641379..357d2923 100644
--- a/lib/std/test/fltbits.myr
+++ b/lib/std/test/fltbits.myr
@@ -1,5 +1,17 @@
 use std
 
+use testr
+
 const main = {
-	std.assert(std.isnan(std.flt64nan()), "isnan(nan) false\n")
+	testr.run([
+		[.name = "isnan", .fn = isnan01],
+	][:])
+}
+
+const isnan01 = {c
+	testr.check(c, std.isnan(std.flt64nan()), "std.flt64nan() should give a NaN")
+	testr.check(c, std.isnan(std.flt32nan()), "std.flt32nan() should give a NaN")
+
+	testr.check(c, std.isnan(std.flt64frombits(0xfff0000500000000ul)), "0xfff0000500000000 should be a NaN")
+	testr.check(c, !std.isnan(std.flt64frombits(0xfff0000000000000ul)), "Infinities should not be NaNs")
 }
-- 
2.16.2


References:
[PATCH 0/2] Signedness of bits from floats"S. Gilles" <sgilles@xxxxxxxxxxxx>