Add engineering output mode

Similar to scientific mode, engineering mode also displays numbers in
base 10 exponential notation, with the difference that exponents are
always multiples of 3, to facilitate the interpretation in terms of
SI prefixes.

The mode is activated in config thru "engineering" or "eng. For base
and base2, it uses the special value 1000.
This commit is contained in:
Lucas Heitzmann Gabrielli
2021-06-07 14:11:07 -03:00
parent 3d33c6c6f4
commit 41b11ab785
8 changed files with 63 additions and 5 deletions

View File

@@ -274,6 +274,8 @@ STATIC NAMETYPE modes[] = {
{"scientific", MODE_EXP}, {"scientific", MODE_EXP},
{"sci", MODE_EXP}, {"sci", MODE_EXP},
{"exp", MODE_EXP}, {"exp", MODE_EXP},
{"engineering", MODE_ENG},
{"eng", MODE_ENG},
{"hexadecimal", MODE_HEX}, {"hexadecimal", MODE_HEX},
{"hex", MODE_HEX}, {"hex", MODE_HEX},
{"octal", MODE_OCTAL}, {"octal", MODE_OCTAL},

3
file.c
View File

@@ -1048,6 +1048,9 @@ idprintf(FILEID id, char *fmt, int count, VALUE **vals)
case 'e': case 'e':
newmode = MODE_EXP; newmode = MODE_EXP;
break; break;
case 'n':
newmode = MODE_ENG;
break;
case 'g': case 'g':
newmode = MODE_REAL_AUTO; newmode = MODE_REAL_AUTO;
break; break;

12
func.c
View File

@@ -7839,6 +7839,9 @@ f_base(int count, NUMBER **vals)
case 16: case 16:
oldbase = math_setmode(MODE_HEX); oldbase = math_setmode(MODE_HEX);
break; break;
case 1000:
oldbase = math_setmode(MODE_ENG);
break;
default: default:
math_error("Unsupported base"); math_error("Unsupported base");
/*NOTREACHED*/ /*NOTREACHED*/
@@ -7893,6 +7896,9 @@ f_base2(int count, NUMBER **vals)
case 16: case 16:
oldbase = math_setmode2(MODE_HEX); oldbase = math_setmode2(MODE_HEX);
break; break;
case 1000:
oldbase = math_setmode(MODE_ENG);
break;
default: default:
math_error("Unsupported base"); math_error("Unsupported base");
/*NOTREACHED*/ /*NOTREACHED*/
@@ -7933,6 +7939,9 @@ base_value(long mode, int defval)
result = qalloc(); result = qalloc();
ztenpow(20, &result->num); ztenpow(20, &result->num);
break; break;
case MODE_ENG:
result = itoq(1000);
break;
case MODE_HEX: case MODE_HEX:
result = itoq(16); result = itoq(16);
break; break;
@@ -7964,6 +7973,9 @@ base_value(long mode, int defval)
result = qalloc(); result = qalloc();
ztenpow(20, &result->num); ztenpow(20, &result->num);
break; break;
case MODE_ENG:
result = itoq(1000);
break;
case MODE_HEX: case MODE_HEX:
result = itoq(16); result = itoq(16);
break; break;

View File

@@ -44,6 +44,9 @@ DESCRIPTION
"sci" "sci"
"exp" "exp"
1000 "engineering" base 10 notation with exponent
"eng" multiple of 3
For convenience, any non-integer value is assumed to mean base 10 For convenience, any non-integer value is assumed to mean base 10
fractions and any integer >= 2^64 is assumed to mean base 10 fractions and any integer >= 2^64 is assumed to mean base 10
scientific notation. scientific notation.
@@ -76,7 +79,7 @@ LINK LIBRARY
int math_setmode(int newmode) int math_setmode(int newmode)
NOTE: newmode must be one of MODE_DEFAULT, MODE_FRAC, MODE_INT, NOTE: newmode must be one of MODE_DEFAULT, MODE_FRAC, MODE_INT,
MODE_REAL, MODE_EXP, MODE_HEX, MODE_OCTAL, MODE_BINARY MODE_REAL, MODE_EXP, MODE_ENG, MODE_HEX, MODE_OCTAL, MODE_BINARY
SEE ALSO SEE ALSO
base2, config, str base2, config, str

View File

@@ -50,6 +50,9 @@ DESCRIPTION
"sci" "sci"
"exp" "exp"
1000 "engineering" base 10 notation with exponent
"eng" multiple of 3
0 "off" disable double base output 0 "off" disable double base output
For convenience, any non-integer non-zero value is assumed to mean For convenience, any non-integer non-zero value is assumed to mean
@@ -87,7 +90,7 @@ LINK LIBRARY
int math_setmode2(int newmode) int math_setmode2(int newmode)
NOTE: newmode must be one of MODE_DEFAULT, MODE_FRAC, MODE_INT, NOTE: newmode must be one of MODE_DEFAULT, MODE_FRAC, MODE_INT,
MODE_REAL, MODE_EXP, MODE_HEX, MODE_OCTAL, MODE_BINARY, MODE_REAL, MODE_EXP, MODE_ENG, MODE_HEX, MODE_OCTAL, MODE_BINARY,
MODE2_OFF MODE2_OFF
SEE ALSO SEE ALSO

View File

@@ -165,8 +165,8 @@ DESCRIPTION
config("display", int) config("display", int)
The "display" parameter specifies the maximum number of digits after The "display" parameter specifies the maximum number of digits after
the decimal point to be printed in real or exponential mode in the decimal point to be printed in real, exponential or engineering
normal unformatted printing (print, strprint, fprint) or in mode in normal unformatted printing (print, strprint, fprint) or in
formatted printing (printf, strprintf, fprintf) when precision is not formatted printing (printf, strprintf, fprintf) when precision is not
specified. The initial value for oldstd is 20, for newstd 10. specified. The initial value for oldstd is 20, for newstd 10.
The parameter may be changed to the value d by either The parameter may be changed to the value d by either
@@ -234,6 +234,9 @@ DESCRIPTION
"sci" "sci"
"exp" "exp"
"engineering" base 10 notation with exponent base(10e6)
"eng" multiple of 3
Where multiple strings are given, the first string listed is what Where multiple strings are given, the first string listed is what
config("mode") will return. config("mode") will return.

31
qio.c
View File

@@ -247,6 +247,37 @@ qprintnum(NUMBER *q, int outmode, LEN outdigits)
PRINTF1("e%ld", exp); PRINTF1("e%ld", exp);
break; break;
case MODE_ENG:
if (qiszero(q)) {
PUTCHAR('0');
return;
}
tmpval = *q;
tmpval.num.sign = 0;
exp = qilog10(&tmpval);
if (exp == 0) { /* in range to output as real */
qprintnum(q, MODE_REAL, outdigits);
return;
}
tmpval.num = _one_;
tmpval.den = _one_;
if (exp > 0) {
exp -= exp % 3;
ztenpow(exp, &tmpval.den);
} else {
long remainder = exp % 3;
if (remainder)
exp -= remainder + 3;
ztenpow(-exp, &tmpval.num);
}
q = qmul(q, &tmpval);
zfree(tmpval.num);
zfree(tmpval.den);
qprintnum(q, MODE_REAL, outdigits);
qfree(q);
PRINTF1("e%ld", exp);
break;
case MODE_REAL_AUTO: case MODE_REAL_AUTO:
{ {
const int P = conf->outdigits ? conf->outdigits : 1; const int P = conf->outdigits ? conf->outdigits : 1;

View File

@@ -594,7 +594,8 @@ E_FUNC void zredcpower(REDC *rp, ZVALUE z1, ZVALUE z2, ZVALUE *res);
#define MODE_OCTAL 6 #define MODE_OCTAL 6
#define MODE_BINARY 7 #define MODE_BINARY 7
#define MODE_REAL_AUTO 8 #define MODE_REAL_AUTO 8
#define MODE_MAX 8 #define MODE_ENG 9
#define MODE_MAX 9
#define MODE2_OFF (MODE_MAX+1) #define MODE2_OFF (MODE_MAX+1)
/* XXX - perhaps we need the MODE_REAL_AUTO vs MODE_REAL as a config mode? */ /* XXX - perhaps we need the MODE_REAL_AUTO vs MODE_REAL as a config mode? */