shithub: mc

Download patch

ref: fdf87b91c1bbd64be75b8438ad6eaf492325e5b4
parent: bdcd9c57965c02da5e30e71ff5eaeb0a71b26ca4
author: S. Gilles <sgilles@math.umd.edu>
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)
+	;;
 }