enmetric() for small values #256

This commit is contained in:
nick black 2020-01-07 00:24:20 -05:00
parent 14d7bed6db
commit 309211e308
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
4 changed files with 94 additions and 26 deletions

View File

@ -410,20 +410,22 @@ int main(int argc, char** argv){
} }
bool failed = false; bool failed = false;
printf("\n"); printf("\n");
printf(" total│frames│output(B)│ rendering│%%r│%6s│\n", "FPS"); printf(" total│frames│output(B)│rendering│%%r│%6s│\n", "FPS");
printf("══╤═╤════════╪══════╪═════════╪═════════╪══╪══════╡\n"); printf("══╤═╤════════╪══════╪═════════╪═════════╪══╪══════╡\n");
for(size_t i = 0 ; i < strlen(demos) ; ++i){ for(size_t i = 0 ; i < strlen(demos) ; ++i){
char totalbuf[BPREFIXSTRLEN + 1]; char totalbuf[BPREFIXSTRLEN + 1];
char rtimebuf[PREFIXSTRLEN + 1];
char timebuf[PREFIXSTRLEN + 1]; char timebuf[PREFIXSTRLEN + 1];
qprefix(results[i].timens, GIG, timebuf, 0); 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); bprefix(results[i].stats.render_bytes, 1, totalbuf, 0);
double avg = results[i].stats.render_ns / (double)results[i].stats.renders; 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, results[i].selector,
PREFIXSTRLEN, timebuf, PREFIXSTRLEN, timebuf,
results[i].stats.renders, results[i].stats.renders,
BPREFIXSTRLEN, totalbuf, BPREFIXSTRLEN, totalbuf,
results[i].stats.render_ns / 1000, PREFIXSTRLEN, rtimebuf,
results[i].timens ? results[i].timens ?
results[i].stats.render_ns * 100 / results[i].timens : 0, results[i].stats.render_ns * 100 / results[i].timens : 0,
GIG / avg, GIG / avg,

View File

@ -18,6 +18,8 @@ convinit(void){
const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec, const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec,
unsigned mult, int uprefix){ unsigned mult, int uprefix){
const char prefixes[] = "KMGTPEZY"; // 10^21-1 encompasses 2^64-1 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; unsigned consumed = 0;
uintmax_t dv; uintmax_t dv;
@ -29,12 +31,22 @@ const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec,
return NULL; return NULL;
} }
dv = mult; dv = mult;
// FIXME verify that input < 2^89, wish we had static_assert() :/ if(decimal <= val || val == 0){
while((val / decimal) >= dv && consumed < strlen(prefixes)){ // FIXME verify that input < 2^89, wish we had static_assert() :/
dv *= mult; while((val / decimal) >= dv && consumed < strlen(prefixes)){
++consumed; dv *= mult;
if(UINTMAX_MAX / dv < mult){ // near overflow--can't scale dv again ++consumed;
break; 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 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 // 1,024). That can overflow with large 64-bit values, but we can first
// divide both sides by mult, and then scale by 100. // divide both sides by mult, and then scale by 100.
if(omitdec && (val % dv) == 0){ if(omitdec && (val % dv) == 0){
sprintfed = sprintf(buf, "%ju%c", val / dv, sprintfed = sprintf(buf, "%ju%c", val / dv, prefixes[consumed - 1]);
prefixes[consumed - 1]);
}else{ }else{
uintmax_t remain = (dv == mult) ? uintmax_t remain = (dv == mult) ?
(val % dv) * 100 / dv : (val % dv) * 100 / dv :
((val % dv) / mult * 100) / (dv / mult); ((val % dv) / mult * 100) / (dv / mult);
sprintfed = sprintf(buf, "%ju%s%02ju%c", sprintfed = sprintf(buf, "%ju%s%02ju%c", val / dv, decisep, remain,
val / dv,
decisep,
remain,
prefixes[consumed - 1]); prefixes[consumed - 1]);
} }
if(uprefix){ if(uprefix){
buf[sprintfed] = uprefix; buf[sprintfed] = uprefix;
buf[sprintfed + 1] = '\0'; buf[sprintfed + 1] = '\0';
} }
}else{ // unscaled output, consumed == 0, dv == mult return buf;
// val / decimal < dv (or we ran out of prefixes) }
if(omitdec && val % decimal == 0){ // unscaled output, consumed == 0, dv == mult
sprintf(buf, "%ju", val / decimal); // 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{ }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); sprintf(buf, "%ju%s%02ju", val / decimal, decisep, remain);
} }
} }

View File

@ -498,11 +498,15 @@ interrogate_terminfo(notcurses* nc, const notcurses_options* opts){
} }
nc->CCCflag = tigetflag("ccc") == 1; nc->CCCflag = tigetflag("ccc") == 1;
if((nc->colors = tigetnum("colors")) <= 0){ 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; nc->colors = 1;
}else if(nc->RGBflag && (unsigned)nc->colors < (1u << 24u)){ }else if(nc->RGBflag && (unsigned)nc->colors < (1u << 24u)){
fprintf(stderr, "Warning: advertised RGB flag but only %d colors\n", if(!opts->suppress_banner){
nc->colors); fprintf(stderr, "Warning: advertised RGB flag but only %d colors\n",
nc->colors);
}
} }
term_verify_seq(&nc->cup, "cup"); term_verify_seq(&nc->cup, "cup");
if(nc->cup == NULL){ if(nc->cup == NULL){

View File

@ -325,7 +325,7 @@ TEST_CASE("Enmetric") {
// computation of that output. For instance, we might feed a number of // computation of that output. For instance, we might feed a number of
// nanoseconds, but want output in seconds. // nanoseconds, but want output in seconds.
// This requires 'decimal' = 1000000000. // This requires 'decimal' = 1000000000.
SUBCASE("ScaledGig") { SUBCASE("ScaledGigSupra") {
char gold[PREFIXSTRLEN + 1] = "9.02"; char gold[PREFIXSTRLEN + 1] = "9.02";
char buf[PREFIXSTRLEN + 1]; char buf[PREFIXSTRLEN + 1];
uintmax_t val = 9027854993; uintmax_t val = 9027854993;
@ -334,4 +334,49 @@ TEST_CASE("Enmetric") {
CHECK(!strcmp(buf, gold)); 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));
}
} }