diff --git a/src/demo/demo.c b/src/demo/demo.c index 25e7d8f6f..ccbdaf215 100644 --- a/src/demo/demo.c +++ b/src/demo/demo.c @@ -410,20 +410,22 @@ int main(int argc, char** argv){ } bool failed = false; printf("\n"); - printf(" total│frames│output(B)│ rendering│%%r│%6s│\n", "FPS"); - printf("══╤═╤════════╪══════╪═════════╪══════════╪══╪══════╡\n"); + printf(" total│frames│output(B)│rendering│%%r│%6s│\n", "FPS"); + printf("══╤═╤════════╪══════╪═════════╪═════════╪══╪══════╡\n"); for(size_t i = 0 ; i < strlen(demos) ; ++i){ char totalbuf[BPREFIXSTRLEN + 1]; + char rtimebuf[PREFIXSTRLEN + 1]; char timebuf[PREFIXSTRLEN + 1]; qprefix(results[i].timens, GIG, timebuf, 0); + qprefix(results[i].stats.render_ns, GIG, rtimebuf, 0); bprefix(results[i].stats.render_bytes, 1, totalbuf, 0); double avg = results[i].stats.render_ns / (double)results[i].stats.renders; - printf("%2zu│%c│%*ss│%6lu│%*s│%8juµs│%2ld│%6.1f│%s\n", i, + printf("%2zu│%c│%*ss│%6lu│%*s│ %*ss│%2ld│%6.1f│%s\n", i, results[i].selector, PREFIXSTRLEN, timebuf, results[i].stats.renders, BPREFIXSTRLEN, totalbuf, - results[i].stats.render_ns / 1000, + PREFIXSTRLEN, rtimebuf, results[i].timens ? results[i].stats.render_ns * 100 / results[i].timens : 0, GIG / avg, diff --git a/src/lib/enmetric.c b/src/lib/enmetric.c index b1753ac9f..0cd4324d9 100644 --- a/src/lib/enmetric.c +++ b/src/lib/enmetric.c @@ -18,6 +18,8 @@ convinit(void){ const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec, unsigned mult, int uprefix){ const char prefixes[] = "KMGTPEZY"; // 10^21-1 encompasses 2^64-1 + // FIXME can't use multibyte μ unless we enlarge the target buffer + const char subprefixes[] = "munpfazy"; // 10^24-1 unsigned consumed = 0; uintmax_t dv; @@ -29,12 +31,22 @@ const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec, return NULL; } dv = mult; - // FIXME verify that input < 2^89, wish we had static_assert() :/ - while((val / decimal) >= dv && consumed < strlen(prefixes)){ - dv *= mult; - ++consumed; - if(UINTMAX_MAX / dv < mult){ // near overflow--can't scale dv again - break; + if(decimal <= val || val == 0){ + // FIXME verify that input < 2^89, wish we had static_assert() :/ + while((val / decimal) >= dv && consumed < strlen(prefixes)){ + dv *= mult; + ++consumed; + if(UINTMAX_MAX / dv < mult){ // near overflow--can't scale dv again + break; + } + } + }else{ + while(val < decimal && consumed < strlen(subprefixes)){ + val *= mult; + ++consumed; + if(UINTMAX_MAX / dv < mult){ // near overflow--can't scale dv again + break; + } } } if(dv != mult){ // if consumed == 0, dv must equal mult @@ -51,29 +63,34 @@ const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec, // 1,024). That can overflow with large 64-bit values, but we can first // divide both sides by mult, and then scale by 100. if(omitdec && (val % dv) == 0){ - sprintfed = sprintf(buf, "%ju%c", val / dv, - prefixes[consumed - 1]); + sprintfed = sprintf(buf, "%ju%c", val / dv, prefixes[consumed - 1]); }else{ uintmax_t remain = (dv == mult) ? (val % dv) * 100 / dv : ((val % dv) / mult * 100) / (dv / mult); - sprintfed = sprintf(buf, "%ju%s%02ju%c", - val / dv, - decisep, - remain, + sprintfed = sprintf(buf, "%ju%s%02ju%c", val / dv, decisep, remain, prefixes[consumed - 1]); } if(uprefix){ buf[sprintfed] = uprefix; buf[sprintfed + 1] = '\0'; } - }else{ // unscaled output, consumed == 0, dv == mult - // val / decimal < dv (or we ran out of prefixes) - if(omitdec && val % decimal == 0){ + return buf; + } + // unscaled output, consumed == 0, dv == mult + // val / decimal < dv (or we ran out of prefixes) + if(omitdec && val % decimal == 0){ + if(consumed){ + sprintf(buf, "%ju%c", val / decimal, subprefixes[consumed - 1]); + }else{ sprintf(buf, "%ju", val / decimal); + } + }else{ + uintmax_t divider = (decimal > mult ? decimal / mult : 1) * 10; + uintmax_t remain = (val % decimal) / divider; + if(consumed){ + sprintf(buf, "%ju%s%02ju%c", val / decimal, decisep, remain, subprefixes[consumed - 1]); }else{ - uintmax_t divider = (decimal > mult ? decimal / mult : 1) * 10; - uintmax_t remain = (val % decimal) / divider; sprintf(buf, "%ju%s%02ju", val / decimal, decisep, remain); } } diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 8ac78c4b9..09d3deaaa 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -498,11 +498,15 @@ interrogate_terminfo(notcurses* nc, const notcurses_options* opts){ } nc->CCCflag = tigetflag("ccc") == 1; if((nc->colors = tigetnum("colors")) <= 0){ - fprintf(stderr, "This terminal doesn't appear to support colors\n"); + if(!opts->suppress_banner){ + fprintf(stderr, "This terminal doesn't appear to support colors\n"); + } nc->colors = 1; }else if(nc->RGBflag && (unsigned)nc->colors < (1u << 24u)){ - fprintf(stderr, "Warning: advertised RGB flag but only %d colors\n", - nc->colors); + if(!opts->suppress_banner){ + fprintf(stderr, "Warning: advertised RGB flag but only %d colors\n", + nc->colors); + } } term_verify_seq(&nc->cup, "cup"); if(nc->cup == NULL){ diff --git a/tests/enmetric.cpp b/tests/enmetric.cpp index 2734c5880..47bfd47b2 100644 --- a/tests/enmetric.cpp +++ b/tests/enmetric.cpp @@ -325,7 +325,7 @@ TEST_CASE("Enmetric") { // computation of that output. For instance, we might feed a number of // nanoseconds, but want output in seconds. // This requires 'decimal' = 1000000000. - SUBCASE("ScaledGig") { + SUBCASE("ScaledGigSupra") { char gold[PREFIXSTRLEN + 1] = "9.02"; char buf[PREFIXSTRLEN + 1]; uintmax_t val = 9027854993; @@ -334,4 +334,49 @@ TEST_CASE("Enmetric") { CHECK(!strcmp(buf, gold)); } + SUBCASE("ScaledGigUnity") { + char gold[PREFIXSTRLEN + 1] = "1.00"; + char buf[PREFIXSTRLEN + 1]; + uintmax_t decimal = 1000000000; + uintmax_t val = decimal; + REQUIRE(qprefix(val, decimal, buf, 0)); + CHECK(!strcmp(buf, gold)); + } + + SUBCASE("ScaledGigJustAbove") { + char gold[PREFIXSTRLEN + 1] = "1.00"; + char buf[PREFIXSTRLEN + 1]; + uintmax_t val = 1000000001; + uintmax_t decimal = 1000000000; + REQUIRE(qprefix(val, decimal, buf, 0)); + CHECK(!strcmp(buf, gold)); + } + + SUBCASE("ScaledGigJustBelow") { + char gold[PREFIXSTRLEN + 1] = "999.99m"; + char buf[PREFIXSTRLEN + 1]; + uintmax_t val = 999999999; + uintmax_t decimal = 1000000000; + REQUIRE(qprefix(val, decimal, buf, 0)); + CHECK(!strcmp(buf, gold)); + } + + SUBCASE("ScaledGigSub") { + char gold[PREFIXSTRLEN + 1] = "27.85m"; + char buf[PREFIXSTRLEN + 1]; + uintmax_t val = 27854993; + uintmax_t decimal = 1000000000; + REQUIRE(qprefix(val, decimal, buf, 0)); + CHECK(!strcmp(buf, gold)); + } + + SUBCASE("ScaledGigSubSub") { + char gold[PREFIXSTRLEN + 1] = "7.85m"; + char buf[PREFIXSTRLEN + 1]; + uintmax_t val = 7854993; + uintmax_t decimal = 1000000000; + REQUIRE(qprefix(val, decimal, buf, 0)); + CHECK(!strcmp(buf, gold)); + } + }