summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorS. Gilles <sgilles@math.umd.edu>2018-02-27 22:54:18 -0500
committerOri Bernstein <ori@eigenstate.org>2018-02-27 21:22:14 -0800
commit19248d9673c0da5c189bf81e7c89a339cf99e405 (patch)
tree03242c3569c0d4a82362ae6edb9299bc9e9f0ee8
parentabb53670c906a115ba5b0cbf97fb9e5d165e94d3 (diff)
downloadmc-19248d9673c0da5c189bf81e7c89a339cf99e405.tar.gz
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.
-rw-r--r--lib/std/fltbits.myr40
-rw-r--r--lib/std/fltfmt.myr2
-rw-r--r--lib/std/fltparse.myr4
-rw-r--r--lib/std/test/fltbits.myr14
4 files changed, 37 insertions, 23 deletions
diff --git a/lib/std/fltbits.myr b/lib/std/fltbits.myr
index 765ce04..f4ddd54 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 2a36daf..b0c08c4 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 9836d1f..e88eba6 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 4e64137..357d292 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")
}