From 41b11ab7853dcca656219b73288e3b48d95eb273 Mon Sep 17 00:00:00 2001 From: Lucas Heitzmann Gabrielli Date: Mon, 7 Jun 2021 14:11:07 -0300 Subject: [PATCH 1/2] 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. --- config.c | 2 ++ file.c | 3 +++ func.c | 12 ++++++++++++ help/base | 5 ++++- help/base2 | 5 ++++- help/config | 7 +++++-- qio.c | 31 +++++++++++++++++++++++++++++++ zmath.h | 3 ++- 8 files changed, 63 insertions(+), 5 deletions(-) diff --git a/config.c b/config.c index 96416a0..6801e57 100644 --- a/config.c +++ b/config.c @@ -274,6 +274,8 @@ STATIC NAMETYPE modes[] = { {"scientific", MODE_EXP}, {"sci", MODE_EXP}, {"exp", MODE_EXP}, + {"engineering", MODE_ENG}, + {"eng", MODE_ENG}, {"hexadecimal", MODE_HEX}, {"hex", MODE_HEX}, {"octal", MODE_OCTAL}, diff --git a/file.c b/file.c index ecd15f3..68dc6a4 100644 --- a/file.c +++ b/file.c @@ -1048,6 +1048,9 @@ idprintf(FILEID id, char *fmt, int count, VALUE **vals) case 'e': newmode = MODE_EXP; break; + case 'n': + newmode = MODE_ENG; + break; case 'g': newmode = MODE_REAL_AUTO; break; diff --git a/func.c b/func.c index c03cf7b..9e92794 100644 --- a/func.c +++ b/func.c @@ -7839,6 +7839,9 @@ f_base(int count, NUMBER **vals) case 16: oldbase = math_setmode(MODE_HEX); break; + case 1000: + oldbase = math_setmode(MODE_ENG); + break; default: math_error("Unsupported base"); /*NOTREACHED*/ @@ -7893,6 +7896,9 @@ f_base2(int count, NUMBER **vals) case 16: oldbase = math_setmode2(MODE_HEX); break; + case 1000: + oldbase = math_setmode(MODE_ENG); + break; default: math_error("Unsupported base"); /*NOTREACHED*/ @@ -7933,6 +7939,9 @@ base_value(long mode, int defval) result = qalloc(); ztenpow(20, &result->num); break; + case MODE_ENG: + result = itoq(1000); + break; case MODE_HEX: result = itoq(16); break; @@ -7964,6 +7973,9 @@ base_value(long mode, int defval) result = qalloc(); ztenpow(20, &result->num); break; + case MODE_ENG: + result = itoq(1000); + break; case MODE_HEX: result = itoq(16); break; diff --git a/help/base b/help/base index 47208c5..15cf5ac 100644 --- a/help/base +++ b/help/base @@ -44,6 +44,9 @@ DESCRIPTION "sci" "exp" + 1000 "engineering" base 10 notation with exponent + "eng" multiple of 3 + For convenience, any non-integer value is assumed to mean base 10 fractions and any integer >= 2^64 is assumed to mean base 10 scientific notation. @@ -76,7 +79,7 @@ LINK LIBRARY int math_setmode(int newmode) 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 base2, config, str diff --git a/help/base2 b/help/base2 index bac9ca7..e64aa53 100644 --- a/help/base2 +++ b/help/base2 @@ -50,6 +50,9 @@ DESCRIPTION "sci" "exp" + 1000 "engineering" base 10 notation with exponent + "eng" multiple of 3 + 0 "off" disable double base output For convenience, any non-integer non-zero value is assumed to mean @@ -87,7 +90,7 @@ LINK LIBRARY int math_setmode2(int newmode) 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 SEE ALSO diff --git a/help/config b/help/config index 380744d..4f10398 100644 --- a/help/config +++ b/help/config @@ -165,8 +165,8 @@ DESCRIPTION config("display", int) The "display" parameter specifies the maximum number of digits after - the decimal point to be printed in real or exponential mode in - normal unformatted printing (print, strprint, fprint) or in + the decimal point to be printed in real, exponential or engineering + mode in normal unformatted printing (print, strprint, fprint) or in formatted printing (printf, strprintf, fprintf) when precision is not specified. The initial value for oldstd is 20, for newstd 10. The parameter may be changed to the value d by either @@ -234,6 +234,9 @@ DESCRIPTION "sci" "exp" + "engineering" base 10 notation with exponent base(10e6) + "eng" multiple of 3 + Where multiple strings are given, the first string listed is what config("mode") will return. diff --git a/qio.c b/qio.c index d3170c2..4b0a15d 100644 --- a/qio.c +++ b/qio.c @@ -247,6 +247,37 @@ qprintnum(NUMBER *q, int outmode, LEN outdigits) PRINTF1("e%ld", exp); 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: { const int P = conf->outdigits ? conf->outdigits : 1; diff --git a/zmath.h b/zmath.h index 83aa942..bc9613f 100644 --- a/zmath.h +++ b/zmath.h @@ -594,7 +594,8 @@ E_FUNC void zredcpower(REDC *rp, ZVALUE z1, ZVALUE z2, ZVALUE *res); #define MODE_OCTAL 6 #define MODE_BINARY 7 #define MODE_REAL_AUTO 8 -#define MODE_MAX 8 +#define MODE_ENG 9 +#define MODE_MAX 9 #define MODE2_OFF (MODE_MAX+1) /* XXX - perhaps we need the MODE_REAL_AUTO vs MODE_REAL as a config mode? */ From a4f8f367c3456789c24e7b0b133914cddbf371d6 Mon Sep 17 00:00:00 2001 From: Lucas Heitzmann Gabrielli Date: Wed, 9 Jun 2021 13:09:33 -0300 Subject: [PATCH 2/2] Skip printing exponent when 0. --- qio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qio.c b/qio.c index 4b0a15d..962f91a 100644 --- a/qio.c +++ b/qio.c @@ -275,7 +275,7 @@ qprintnum(NUMBER *q, int outmode, LEN outdigits) zfree(tmpval.den); qprintnum(q, MODE_REAL, outdigits); qfree(q); - PRINTF1("e%ld", exp); + if (exp) PRINTF1("e%ld", exp); break; case MODE_REAL_AUTO: