ref: fdf87b91c1bbd64be75b8438ad6eaf492325e5b4
parent: bdcd9c57965c02da5e30e71ff5eaeb0a71b26ca4
author: S. Gilles <[email protected]>
date: Tue Sep 10 15:37:24 EDT 2019
Force scientific notation to print trailing 0s Also, recalculate 2*R + M+ during the Fixup loop. This prevents rare digit miscalculations: e.g. std.put("{e,s=4}\n", std.flt32frombits(0x2899fbf7))
--- a/lib/std/fltfmt.myr
+++ b/lib/std/fltfmt.myr
@@ -47,7 +47,7 @@
var valsb = mksb()
exp = max(exp, 1 - Dblbias)
- dragon4(valsb, false, mant, exp - 52, Dblbias, opts.mode, opts.cutoff, opts.scientific)
+ dragon4(valsb, false, mant, exp - 52, Dblbias, opts.mode, -opts.cutoff, opts.scientific)
-> blobfmt(sb, sbfin(valsb), opts, isneg)
}
@@ -68,7 +68,7 @@
var valsb = mksb()
exp = (max((exp : int64), 1 - Fltbias) : int32)
- dragon4(valsb, false, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, opts.cutoff, opts.scientific)
+ dragon4(valsb, false, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, -opts.cutoff, opts.scientific)
-> blobfmt(sb, sbfin(valsb), opts, isneg)
}
@@ -148,6 +148,9 @@
/* if we have zero for the mantissa, we can return early */
if f == 0
sbputs(sb, "0.0")
+ if scientific
+ sbputs(sb, "e0")
+ ;;
-> void
;;
@@ -207,24 +210,26 @@
bigfree(u)
;;
;;
+
if mode == MNormal
cutoff = k
else
if mode == MRelative
- cutoff += k - 1
- a = cutoff - k + 1
- else
- a = cutoff
+ if cutoff >= 0
+ cutoff = -1
+ ;;
+ cutoff += k
;;
+ a = cutoff - k
/* common between relative and absolute */
y = bigdup(s)
- if a < 0
- for i = 0; i < -a; i++
+ if a > 0
+ for i = 0; i < a; i++
bigmuli(y, 10)
;;
else
- for i = 0; i < a; i++
+ for i = 0; i < -a; i++
bigaddi(y, 9)
bigdivi(y, 10)
;;
@@ -241,9 +246,16 @@
bigfree(mp)
mp = bigdup(y)
roundup = true
+
+ /* recalculate 2*R + M+ for the loop termination */
+ bigfree(t)
+ t = bigdup(r)
+ bigshli(t, 1)
+ bigadd(t, mp)
;;
bigfree(y)
;;
+
u = bigdup(s)
bigshli(u, 1)
match bigcmp(t, u)
@@ -257,6 +269,7 @@
if scientific
tenpower = (k - 1 : int64)
+ cutoff += (1 - k)
k = 1
;;
@@ -324,7 +337,10 @@
;;
;;
k--
- while k >= -1
+ if !scientific && cutoff > -1
+ cutoff = -1
+ ;;
+ while k >= cutoff
format(sb, 0, k--)
;;
--- a/lib/std/test/fltfmt.myr
+++ b/lib/std/test/fltfmt.myr
@@ -145,8 +145,8 @@
testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
f64 = 12345.6789
- exp = "12345.6789"
- act = std.fmt("{s=200}", f64)
+ exp = "12345.67890000000000000000000000000000000"
+ act = std.fmt("{s=40}", f64)
testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
f64 = 12345.6789
@@ -168,6 +168,11 @@
exp = "-10.0"
act = std.fmt("{s=-23}", f32)
testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
+
+ f64 = 99.999
+ exp = "100.0"
+ act = std.fmt("{s=2}", f64)
+ testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
}
const scientific01 = {c
@@ -196,34 +201,76 @@
testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
f64 = 0.0
- exp = "0.0"
+ exp = "0.0e0"
act = std.fmt("{e}", f64)
testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
}
const scientific02 = {c
- var exp, act
- var f32 : flt32
- var f64 : flt64
+ var inputs : (uint32, byte[:])[:] = [
+ (0x00006b2e, "3.845e-41"), (0x0000001a, "3.600e-44"), (0xb806801a, "-3.207e-5"),
+ (0x865c1e25, "-4.140e-35"), (0x8f0e27a7, "-7.009e-30"), (0x1981f861, "1.344e-23"),
+ (0xfc00ebc4, "-2.678e36"), (0xffe3ee67, "NaN"), (0x2beaaea1, "1.668e-12"),
+ (0x2899fbf7, "1.710e-14"), (0x64807020, "1.895e22"), (0x397908de, "2.375e-4"),
+ (0x43cf5761, "4.147e2"), (0xe8dade34, "-8.269e24"), (0xdb42028a, "-5.461e16"),
+ (0xcb0dc6d9, "-9.291e6"), (0xfe788727, "-8.259e37"), (0x204d51af, "1.739e-19"),
+ (0xaceb03c8, "-6.680e-12"), (0x62936772, "1.360e21"), (0x01d04ef3, "7.652e-38"),
+ (0x096f9939, "2.884e-33"), (0x554393e6, "1.344e13"), (0x7d569963, "1.783e37"),
+ (0x7dab27eb, "2.844e37"), (0xa82adb2a, "-9.484e-15"), (0xef3c547e, "-5.829e28"),
+ (0x3f037508, "5.135e-1"), (0x35f91ece, "1.856e-6"), (0x64038c7d, "9.707e21"),
+ (0xa7014df5, "-1.794e-15"), (0x00000001, "1.000e-45"), (0x00000002, "3.000e-45"),
+ (0x142d3a25, "8.746e-27"), (0xf40956cc, "-4.352e31"), (0xcf94a73b, "-4.988e9"),
+ (0x8a5b4e0a, "-1.056e-32"), (0x6099c9f8, "8.865e19"), (0x999901e9, "-1.582e-23"),
+ (0x104d5fdf, "4.050e-29"), (0x53994694, "1.317e12"), (0xba0ffdd6, "-5.493e-4"),
+ (0x566478f7, "6.280e13"), (0xc828393e, "-1.723e5"), (0x35e78756, "1.725e-6"),
+ (0x8a7cc67a, "-1.217e-32"), (0xe5eac57c, "-1.386e23"), (0xba198513, "-5.856e-4"),
+ (0x912dced2, "-1.371e-28"), (0x62ceeff6, "1.909e21"), (0xc319fddf, "-1.540e2"),
+ (0x8d84f7de, "-8.195e-31"), (0xf9789b3a, "-8.068e34"), (0xffe0458a, "NaN"),
+ (0xa447b8cb, "-4.331e-17"), (0xe78db907, "-1.339e24"), (0x5b9ddc70, "8.887e16"),
+ (0x1e1135d1, "7.687e-21"), (0x1092b9bc, "5.787e-29"), (0x1fdaec1e, "9.272e-20"),
+ (0xfd481782, "-1.662e37"), (0x0a6f575b, "1.152e-32"), (0x11f9b948, "3.940e-28"),
+ (0x97a2e4ee, "-1.053e-24"), (0xc427eede, "-6.717e2"), (0x6841cbee, "3.661e24"),
+ (0x0fbe8791, "1.879e-29"), (0x9b1deb6b, "-1.306e-22"), (0x380c6359, "3.347e-5"),
+ (0xddc24e30, "-1.750e18"), (0x306b3607, "8.557e-10"), (0x646de701, "1.755e22"),
+ (0x4b4c8fea, "1.341e7"), (0x12633040, "7.169e-28"), (0xa2e27952, "-6.139e-18"),
+ (0x48daa5a6, "4.478e5"), (0x5c19903e, "1.729e17"), (0x1497718b, "1.529e-26"),
+ (0x888e7d7c, "-8.576e-34"), (0x0f6b694a, "1.161e-29"), (0xf6e7ac5f, "-2.349e33"),
+ (0x9686921a, "-2.174e-25"), (0xcfbec790, "-6.401e9"), (0x1e8da64f, "1.500e-20"),
+ (0xd903e53a, "-2.320e15"), (0x15d49a09, "8.587e-26"), (0x203eedc3, "1.617e-19"),
+ (0xdba9f019, "-9.567e16"), (0x8bc93716, "-7.751e-32"), (0x5bbcf273, "1.064e17"),
+ (0xa449bd7a, "-4.375e-17"), (0x2c75c7ac, "3.493e-12"), (0x85f83a6b, "-2.334e-35"),
+ (0x4cdf6322, "1.171e8"), (0x490b5e87, "5.709e5"), (0xb49a38f4, "-2.873e-7"),
+ (0x14eecf83, "2.411e-26"), (0xaddd8c33, "-2.519e-11"), (0x0b4ca7de, "3.942e-32"),
+ (0x8cba7b11, "-2.873e-31"), (0x3a4c41c4, "7.792e-4"), (0x0d13e993, "4.558e-31"),
+ (0xd84bbda9, "-8.961e14"), (0x5aa23a32, "2.283e16"), (0xf20deb5d, "-2.811e30"),
+ (0x62cccc86, "1.889e21"), (0x20ba0821, "3.152e-19"), (0x23c40663, "2.125e-17"),
+ (0x8ef7d8b1, "-6.110e-30"), (0x253c173c, "1.631e-16"), (0xe2d8fe86, "-2.001e21"),
+ (0x2e31df38, "4.044e-11"), (0x563dcd40, "5.217e13"), (0x78c75eff, "3.235e34"),
+ (0x9480ba67, "-1.300e-26"), (0xd4900806, "-4.949e12"), (0x8fb3cb79, "-1.773e-29"),
+ (0xf76ea58f, "-4.840e33"), (0x18ce7442, "5.337e-24"), (0x925f1cd6, "-7.040e-28"),
+ (0x1fcbbe53, "8.629e-20"), (0x723be188, "3.721e30"), (0xa01bf8c6, "-1.321e-19"),
+ (0xc034d668, "-2.826e0"), (0xa983e3c2, "-5.857e-14"), (0xf3d52e40, "-3.378e31"),
+ (0x64435bc6, "1.441e22"), (0xb9b06c80, "-3.365e-4"), (0x90ba67c2, "-7.352e-29"),
+ (0x17620ab6, "7.304e-25"), (0x93e2bd8a, "-5.724e-27"), (0xfe53a8b1, "-7.034e37"),
+ (0x856df9d0, "-1.119e-35"), (0x773f393f, "3.878e33"), (0x10231748, "3.216e-29"),
+ (0x68a2b99a, "6.148e24"), (0x57e0d3bc, "4.944e14"), (0x5eb4cd0d, "6.514e18"),
+ (0xf7593e1d, "-4.406e33"), (0x9a200d02, "-3.310e-23"), (0x8f50d4f1, "-1.030e-29"),
+ (0x6a39a779, "5.611e25"), (0x57b438d9, "3.963e14"), (0x8adc8f39, "-2.124e-32"),
+ (0xa5ce9605, "-3.584e-16"), (0xa64fbd28, "-7.207e-16"), (0x07d505a4, "3.205e-34"),
+ (0x88e15708, "-1.356e-33"), (0x871a5d45, "-1.161e-34"), (0x3bb2c09c, "5.455e-3"),
+ (0xda05263b, "-9.370e15"), (0x6e637d4a, "1.760e28"), (0xf001136a, "-1.598e29"),
+ (0x89399e5a, "-2.234e-33"), (0x57d88a36, "4.762e14"), (0x48625a24, "2.318e5"),
+ (0x469861fc, "1.950e4"), (0xe2dfa9ef, "-2.063e21"), (0xb30edce0, "-3.326e-8"),
+ (0x4cf5612c, "1.286e8"), (0xdb41cead, "-5.455e16"), (0xe9eaf854, "-3.551e25"),
+ (0x507b8568, "1.688e10"), (0x6785fae6, "1.265e24"), (0x0a36ba3c, "8.798e-33"),
+ (0x3dbc3e38, "9.192e-2"), (0x4a3d3834, "3.100e6"), (0x09ebc2d8, "5.676e-33"),
+ (0x2cf0fcdd, "6.849e-12"), (0xb2452cfb, "-1.148e-8"), (0xa25e17b3, "-3.010e-18"),
+ (0x2d9bd504, "1.772e-11"), (0x8afb1ff3, "-2.418e-32"), (0xccb86e05, "-9.669e7"),
+ (0xa2bbd81e, "-5.092e-18"), (0xd99a0fda, "-5.421e15"), (0x026f37f5, "1.758e-37"),
+ ][:]
- f32 = 9.125
- exp = "9.1e0"
- act = std.fmt("{s=2,e}", f32)
- testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
-
- f32 = 9.125
- exp = "9.1e0"
- act = std.fmt("{e,s=2}", f32)
- testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
-
- f32 = 9.125
- exp = "9.0e0"
- act = std.fmt("{e,s=1}", f32)
- testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
-
- f64 = -0.000345
- exp = "-3.4e-4"
- act = std.fmt("{e,s=2}", f64)
- testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
-
+ for (u, exp) : inputs
+ var act : byte[:] = std.fmt("{e,s=4}", std.flt32frombits(u))
+ testr.check(c, std.eq(exp, act), "0x{x,w=8,p=0} = {} should format to \"{}\", was \"{}\"", u, std.flt32frombits(u), exp, act)
+ ;;
}