Eigenstate: myrddin-dev mailing list

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

[PATCH 5/5] Allow printing fltXY in scientific notation


---

Also includes a oneline fix for option parsing for things like `std.put("{x,p=Y}\n", 123)'.

 lib/std/fltfmt.myr      | 28 +++++++++++++------
 lib/std/fmt.myr         |  3 +++
 lib/std/test/fltfmt.myr | 60 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/lib/std/fltfmt.myr b/lib/std/fltfmt.myr
index 25b1583b..570da488 100644
--- a/lib/std/fltfmt.myr
+++ b/lib/std/fltfmt.myr
@@ -3,6 +3,7 @@ use "bigint"
 use "die"
 use "extremum"
 use "fltbits"
+use "intfmt"
 use "option"
 use "slpush"
 use "strbuf"
@@ -16,10 +17,11 @@ pkg std =
 	pkglocal const MRelative = 2
 
 	pkglocal type fltparams = struct
-		mode	: int
-		cutoff	: size
-		padto	: size
-		padfill	: char
+		mode		: int
+		cutoff		: size
+		scientific	: bool
+		padto		: size
+		padfill		: char
 	;;
 
 	pkglocal const flt64bfmt	: (sb : strbuf#, opts : fltparams, val : flt64 -> void)
@@ -45,7 +47,7 @@ const flt64bfmt = {sb, opts, val
 	var valsb = mksb()
 
 	exp = max(exp, 1 - Dblbias)
-	dragon4(valsb, false, mant, exp - 52, Dblbias, opts.mode, opts.cutoff)
+	dragon4(valsb, false, mant, exp - 52, Dblbias, opts.mode, opts.cutoff, opts.scientific)
 
 	-> blobfmt(sb, sbfin(valsb), opts, isneg)
 }
@@ -66,7 +68,7 @@ const flt32bfmt = {sb, opts, val
 	var valsb = mksb()
 
 	exp = (max((exp : int64), 1 - Fltbias) : int32)
-	dragon4(valsb, false, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, opts.cutoff)
+	dragon4(valsb, false, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, opts.cutoff, opts.scientific)
 
 	-> blobfmt(sb, sbfin(valsb), opts, isneg)
 }
@@ -130,13 +132,14 @@ f: mantissa
 
 floating value: x = f^(e - p)
 */
-const dragon4 = {sb, isneg, f, e, p, mode, cutoff
+const dragon4 = {sb, isneg, f, e, p, mode, cutoff, scientific
 	var r, s, t, u, v, y
 	var udig
 	var mm, mp	/* margins above and below */
 	var roundup
 	var low, high
 	var k
+	var tenpower : int64 = 0
 	var a, i
 
 	if isneg
@@ -252,6 +255,11 @@ const dragon4 = {sb, isneg, f, e, p, mode, cutoff
 		;;
 	;;
 
+	if scientific
+		tenpower = (k - 1 : int64)
+		k = 1
+	;;
+
 	if k <= 0
 		sbputs(sb, "0.")
 		for var i = 0; i < -k; i++
@@ -320,12 +328,16 @@ const dragon4 = {sb, isneg, f, e, p, mode, cutoff
 		format(sb, 0, k--)
 	;;
 
+	if scientific
+		sbputs(sb, "e")
+		intfmt(sb, [ .base = 10 ], true, (tenpower : uint64), 64)
+	;;
+
 	bigfree(u)
 	bigfree(r)
 	bigfree(s)
 	bigfree(mm)
 	bigfree(mp)
-
 }
 
 const lowdig = {u
diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr
index b981a74f..c4c3797e 100644
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -210,6 +210,7 @@ const sbfmtv = {sb, fmt, ap -> size
 			if startp != nbuf
 				param[nparam++] = (buf[startp:nbuf], "")
 			;;
+			startp = nbuf
 		| (`ParamOpt, '}'):
 			state = `Copy
 			if startp != nbuf
@@ -455,12 +456,14 @@ const fltparams = {params
 	fp = [
 		.mode = MNormal,
 		.cutoff = 0,
+		.scientific = false,
 		.padfill = ' ',
 		.padto = 0,
 	]
 
 	for p : params
 		match p
+		| ("e", ""):	fp.scientific = true
 		| ("w", wid):	fp.padto = getint(wid, "fmt: width must be integer")
 		| ("p", pad):	fp.padfill = decode(pad)
 		| ("s", sig):
diff --git a/lib/std/test/fltfmt.myr b/lib/std/test/fltfmt.myr
index 7e844dd7..0ef790b2 100644
--- a/lib/std/test/fltfmt.myr
+++ b/lib/std/test/fltfmt.myr
@@ -12,6 +12,8 @@ const main = {
 		[.name = "putlowprec", .fn = putlowprec],
 		[.name = "padding", .fn = padding],
 		[.name = "sigfigs", .fn = sigfigs],
+		[.name = "scientific01", .fn = scientific01],
+		[.name = "scientific02", .fn = scientific02],
 	][:])
 }
 
@@ -167,3 +169,61 @@ const sigfigs = {c
 	act = std.fmt("{s=-23}", f32)
 	testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
 }
+
+const scientific01 = {c
+	var exp, act
+	var f32 : flt32
+	var f64 : flt64
+
+	f32 = 9.125
+	exp = "9.125e0"
+	act = std.fmt("{e}", f32)
+	testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
+
+	f32 = -9.125
+	exp = "-9.125e0"
+	act = std.fmt("{e}", f32)
+	testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
+
+	f32 = 101.25
+	exp = "1.0125e2"
+	act = std.fmt("{e}", f32)
+	testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act)
+
+	f64 = 0.000345
+	exp = "3.45e-4"
+	act = std.fmt("{e}", f64)
+	testr.check(c, std.eq(exp, act), "{} should format [flt64] to \"{}\", was \"{}\"", f64, exp, act)
+
+	f64 = 0.0
+	exp = "0.0"
+	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
+
+	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)
+
+}
-- 
2.23.0


References:
[PATCH 0/5] Allow printing floating point in scientific notation"S. Gilles" <sgilles@xxxxxxxxxxxx>