ref: 19248d9673c0da5c189bf81e7c89a339cf99e405
parent: abb53670c906a115ba5b0cbf97fb9e5d165e94d3
author: S. Gilles <sgilles@math.umd.edu>
date: Tue Feb 27 17:54:18 EST 2018
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.
--- 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 @@
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 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 @@
var b
b = flt64bits((f : flt64))
- -> (b >> 52) & 0x7ffl == 0x7ffl && \
- b & ~(0x7ffl) != 0
+ -> (b >> 52) & 0x7fful == 0x7fful && \
+ b & ~(0x7fful) != 0
}
const flt64inf = {
--- a/lib/std/fltfmt.myr
+++ b/lib/std/fltfmt.myr
@@ -32,7 +32,7 @@
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)
}
/*
--- a/lib/std/fltparse.myr
+++ b/lib/std/fltparse.myr
@@ -125,7 +125,7 @@
minsig : uint64
maxsig : uint64
loshift : uint64
- nextinc : int64
+ nextinc : uint64
minexp : int16
maxexp : int16
sigbits : int16
@@ -265,7 +265,7 @@
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
--- 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")
}