[PATCH 2/5] Allow padding for fltXY formatting
[Thread Prev] | [Thread Next]
- Subject: [PATCH 2/5] Allow padding for fltXY formatting
- From: "S. Gilles" <sgilles@xxxxxxxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Mon, 9 Sep 2019 08:38:26 -0400
- To: "myrddin-dev" <myrddin-dev@xxxxxxxxxxxxxx>
- Cc: "S. Gilles" <sgilles@xxxxxxxxxxxx>
--- lib/std/fltfmt.myr | 86 +++++++++++++++++++++++++++++-------- lib/std/fmt.myr | 5 +++ lib/std/test/fltfmt.myr | 95 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 160 insertions(+), 26 deletions(-) diff --git a/lib/std/fltfmt.myr b/lib/std/fltfmt.myr index ee035520..a215c12a 100644 --- a/lib/std/fltfmt.myr +++ b/lib/std/fltfmt.myr @@ -3,6 +3,7 @@ use "bigint" use "die" use "extremum" use "fltbits" +use "option" use "slpush" use "strbuf" use "types" @@ -17,6 +18,8 @@ pkg std = pkglocal type fltparams = struct mode : int prec : int + padto : size + padfill : char ;; pkglocal const flt64bfmt : (sb : strbuf#, opts : fltparams, val : flt64 -> void) @@ -30,46 +33,93 @@ const flt64bfmt = {sb, opts, val var isneg, exp, mant if isnan(val) - sbputs(sb, "NaN") - -> void + -> nanfmt(sb, opts) ;; (isneg, exp, mant) = flt64explode(val) if exp > Dblbias - if isneg - std.sbputs(sb, "-Inf") - else - std.sbputs(sb, "Inf") - ;; - -> void + -> inffmt(sb, opts, isneg) ;; + var valsb = mksb() + exp = max(exp, 1 - Dblbias) - dragon4(sb, isneg, mant, exp - 52, Dblbias, opts.mode, opts.prec) + dragon4(valsb, false, mant, exp - 52, Dblbias, opts.mode, opts.prec) + + -> blobfmt(sb, sbfin(valsb), opts, isneg) } const flt32bfmt = {sb, opts, val var isneg, exp, mant if isnan(val) - sbputs(sb, "NaN") - -> void + -> nanfmt(sb, opts) ;; (isneg, exp, mant) = flt32explode(val) if (exp : int64) > Fltbias - if isneg - std.sbputs(sb, "-Inf") - else - std.sbputs(sb, "Inf") - ;; - -> void + -> inffmt(sb, opts, isneg) ;; + var valsb = mksb() + exp = (max((exp : int64), 1 - Fltbias) : int32) - dragon4(sb, isneg, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, opts.prec) + dragon4(valsb, false, (mant : uint64), (exp - 23 : int64), Fltbias, opts.mode, opts.prec) + + -> blobfmt(sb, sbfin(valsb), opts, isneg) +} + +const nanfmt = {sb, opts + var npad = clamp(opts.padto - 3, 0, opts.padto) + + for var j = 0; j < npad; j++ + sbputc(sb, opts.padfill) + ;; + + sbputs(sb, "NaN") +} + +const inffmt = {sb, opts, isneg + var s = "Inf" + var l = 3 + + if isneg + s = "-Inf" + l = 4 + ;; + + var npad = clamp(opts.padto - l, 0, opts.padto) + + for var j = 0; j < npad; j++ + sbputc(sb, opts.padfill) + ;; + + sbputs(sb, s) +} + +const blobfmt = {sb, blob, opts, isneg + /* No exotic characters, so no need for strcellwidth */ + var width = blob.len + + if isneg + width++ + ;; + + var npad = clamp(opts.padto - width, 0, opts.padto) + + if opts.padfill == '0' && isneg + sbputb(sb, ('-' : byte)) + ;; + for var j = 0; j < npad; j++ + sbputc(sb, opts.padfill) + ;; + if opts.padfill != '0' && isneg + sbputb(sb, ('-' : byte)) + ;; + + sbputs(sb, blob) } /* diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr index 540d6d8e..51dc36ef 100644 --- a/lib/std/fmt.myr +++ b/lib/std/fmt.myr @@ -454,10 +454,14 @@ const fltparams = {params fp = [ .mode = MNormal, .prec = 0, + .padfill = ' ', + .padto = 0, ] for p : params match p + | ("w", wid): fp.padto = getint(wid, "fmt: width must be integer") + | ("p", pad): fp.padfill = decode(pad) | (opt, arg): std.write(2, "fmt: ") std.write(2, opt) @@ -466,6 +470,7 @@ const fltparams = {params std.die("\nunreachable\n") ;; ;; + iassert(fp.padto >= 0, "pad must be >= 0") -> fp } diff --git a/lib/std/test/fltfmt.myr b/lib/std/test/fltfmt.myr index 349f8bc2..7670fff8 100644 --- a/lib/std/test/fltfmt.myr +++ b/lib/std/test/fltfmt.myr @@ -8,21 +8,24 @@ const main = { [.name = "put0", .fn = put0], [.name = "putNaN", .fn = putNaN], [.name = "putInf", .fn = putInf], + [.name = "putinteger", .fn = putinteger], + [.name = "putlowprec", .fn = putlowprec], + [.name = "padding", .fn = padding], ][:]) } const put0 = {c - var f : flt32 = 0.0 - var g : flt64 = 0.0 + var f : flt32 = 0.0 + var g : flt64 = 0.0 testr.check(c, std.eq(std.fmt("f is {}", f), "f is 0.0"), "0.0 should format to \"0.0\"") testr.check(c, std.eq(std.fmt("g is {}", g), "g is 0.0"), "0.0 should format to \"0.0\"") } const putNaN = {c - var f : flt32 = std.flt32nan() - var g : flt64 = std.flt64nan() - var f2 : flt32 = std.flt32frombits(0x7fc00ab0) - var g2 : flt64 = std.flt64frombits(0x7ff800000000abc0) + var f : flt32 = std.flt32nan() + var g : flt64 = std.flt64nan() + var f2 : flt32 = std.flt32frombits(0x7fc00ab0) + var g2 : flt64 = std.flt64frombits(0x7ff800000000abc0) testr.check(c, std.eq(std.fmt("f is {}", f), "f is NaN"), "NaN should format to \"NaN\"") testr.check(c, std.eq(std.fmt("g is {}", g), "g is NaN"), "NaN should format to \"NaN\"") testr.check(c, std.eq(std.fmt("f2 is {}", f2), "f2 is NaN"), "alt NaN should format to \"NaN\"") @@ -30,9 +33,85 @@ const putNaN = {c } const putInf = {c - var f : flt32 = std.flt32inf() - var g : flt64 = std.flt64inf() + var f : flt32 = std.flt32inf() + var g : flt64 = std.flt64inf() testr.check(c, std.eq(std.fmt("f is {}", f), "f is Inf"), "Inf should format to \"Inf\"") testr.check(c, std.eq(std.fmt("g is {}", g), "g is Inf"), "Inf should format to \"Inf\"") + f *= -1.0 + g *= -1.0 + testr.check(c, std.eq(std.fmt("f is {}", f), "f is -Inf"), "-Inf should format to \"-Inf\"") + testr.check(c, std.eq(std.fmt("g is {}", g), "g is -Inf"), "-Inf should format to \"-Inf\"") } +const putinteger = {c + var data : (int, byte[:])[:] = [ + (1, "1.0"), (2, "2.0"), (184, "184.0"), (-37, "-37.0") + ][:] + + for (f, exp) : data + var f32 : flt32 = (f : flt32) + var f64 : flt64 = (f : flt64) + var act32 : byte[:] = std.fmt("{}", f32) + var act64 : byte[:] = std.fmt("{}", f64) + + testr.check(c, std.eq(act32, exp), "{} should format [flt32] to \"{}\", was \"{}\"", f, exp, act32) + testr.check(c, std.eq(act64, exp), "{} should format [flt64] to \"{}\", was \"{}\"", f, exp, act64) + ;; +} + +const putlowprec = {c + var data : (flt64, byte[:])[:] = [ + (1.5, "1.5"), (0.0025, "0.0025"), (4.25, "4.25"), (-229.25, "-229.25") + ][:] + + for (f, exp) : data + var f32 : flt32 = (f : flt32) + var f64 : flt64 = (f : flt64) + var act32 : byte[:] = std.fmt("{}", f32) + var act64 : byte[:] = std.fmt("{}", f64) + + testr.check(c, std.eq(act32, exp), "{} should format [flt32] to \"{}\", was \"{}\"", f, exp, act32) + testr.check(c, std.eq(act64, exp), "{} should format [flt64] to \"{}\", was \"{}\"", f, exp, act64) + ;; +} + +const padding = {c + var exp, act + var f32 : flt32 + var f64 : flt64 + + f32 = 1.0 + exp = "XXXX1.0" + act = std.fmt("{w=7,p=X}", f32) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act) + + f64 = 1.0 + exp = "XXXX1.0" + act = std.fmt("{w=7,p=X}", f64) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f64, exp, act) + + f32 = -2.5 + exp = "YYYYYY-2.5" + act = std.fmt("{w=10,p=Y}", f32) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act) + + f64 = -100000.5 + exp = "-100000.5" + act = std.fmt("{w=9,p=Y}", f64) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f64, exp, act) + + f32 = -13.25 + exp = "-013.25" + act = std.fmt("{w=7,p=0}", f32) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act) + + f32 = -1.0 * std.flt32inf() + exp = "0000000-Inf" + act = std.fmt("{w=11,p=0}", f32) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f32, exp, act) + + f64 = std.flt64nan() + exp = " NaN" + act = std.fmt("{w=18,p= }", f64) + testr.check(c, std.eq(exp, act), "{} should format [flt32] to \"{}\", was \"{}\"", f64, exp, act) +} -- 2.23.0
[PATCH 0/5] Allow printing floating point in scientific notation | "S. Gilles" <sgilles@xxxxxxxxxxxx> |
- Prev by Date: [PATCH 1/5] Collect fltXYbfmt parameters into analogue of intparams
- Next by Date: [PATCH 3/5] Specify sigfigs (cutoff + Relative mode) for fltXY formatting
- Previous by thread: [PATCH 1/5] Collect fltXYbfmt parameters into analogue of intparams
- Next by thread: [PATCH 3/5] Specify sigfigs (cutoff + Relative mode) for fltXY formatting
- Index(es):