mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-16 00:13:00 +00:00
enmetric() for small values #256
This commit is contained in:
parent
14d7bed6db
commit
309211e308
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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){
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user