Compare commits

..

7 Commits

Author SHA1 Message Date
Landon Curt Noll
2ea77e6151 Release 2.12.6.9
Experimental changes for macOS builds.
2018-10-15 19:37:48 -07:00
Landon Curt Noll
5cfa6199e5 Merge branch '10110111-master' 2018-09-30 16:11:23 -07:00
Landon Curt Noll
da6ccc146f Improvements to %g pull request
This code %g is preliminary.

Fixed some code style issues to match the current code style.

Added regression tests and help file updates to printf and strprintf.

Fixed use of magic number -4: using -P instead.

Noted two problem areas with XXX comments in qio.c:

    1) need a qprintfg function
    2) re-write to not modify conf->outdigits
2018-09-30 16:06:28 -07:00
Landon Curt Noll
fcfe237375 Merge branch 'master' of https://github.com/10110111/calc into 10110111-master 2018-09-30 14:22:41 -07:00
Landon Curt Noll
5fb3db4558 Fixed trigonometric and hyperbolic core dumps 2018-09-30 14:08:20 -07:00
Ruslan Kabatsayev
0558bafcb6 Use MODE_REAL_AUTO by default instead of MODE_REAL
This will save the user from embarrassment due to getting
~0.00000000000000000000 as the result instead of e.g. 1.23e-53.
2018-06-30 18:44:14 +03:00
Ruslan Kabatsayev
f58277f53d Implement %g format for printf 2018-06-30 18:35:35 +03:00
15 changed files with 275 additions and 69 deletions

41
CHANGES
View File

@@ -1,4 +1,43 @@
The following are the changes from calc version 2.12.6.6 to date:
The following are the changes from calc version 2.12.6.9 to date:
Fixed a number of core dump bugs related to the calculation of
tan(), cot(), sec(), csc(), tanh(), coth(), sech(), and csch(),
asin(), acos(), asinh(), acosh(), where when a call to an
underlying function produced an invalid value. Thanks goes to
github user wuxiuheng for reporting this problem.
A number of trigonometric and hyperbolic functions that incorrectly
returned E_LOGINF, now return a new error code that is more
specific to the trigonometric or hyperbolic function. The
following is a list of these new error codes: E_TAN3 E_TAN4
E_COT3 E_COT4 E_SEC3 E_CSC3 E_TANH3 E_TANH4 E_COTH3 E_COTH4
E_SECH3 E_CSCH3 E_ASIN3 E_ACOS3 E_ASINH3 E_ACOSH3 E_ATAN3 E_ACOT3
E_ASEC3 E_ACSC3 E_ATANH3 E_ACOTH3 E_ASECH3 E_ACSCH3.
Added regression tests 3729 thru 3732 to test E_TAN3, E_COT3,
E_SEC3 and E_CSC3 respectively.
Added experimential %g printf (and strprintf) format implementation
based on pull request from github user 10110111.
Made exterimental changes to macOS builds to not require use of
/usr/include. The INCDIR for macOS uses:
INCDIR= $(shell xcrun --show-sdk-path --sdk macosx)/usr/include
to determine the upper path of the /usr/include directory for macOS.
The Darwin target seems to not automatically detected. For now,
under macOS, declare the target as darwin:
# for macOS users only, force the target to be darwin
#
make target=Darwin clobber
make target=Darwin all
make target=Darwin chk
make target=Darwin install
The following are the changes from calc version 2.12.6.6 to 2.12.6.8:
For historical purposes, in lucas.cal, gen_v1(1, n) always returns 4.

View File

@@ -32,6 +32,16 @@ Installing calc from the bzip2-ed tarball in 4 easy steps:
targets, the default make is sufficent. On FreeBSD for example,
one must use gmake instead of make.
Some report that under macOS, one has to declare the target
to be darwin. So for macOS, one might have to do:
# for macOS users only, force the target to be darwin
#
make target=Darwin clobber
make target=Darwin all
make target=Darwin chk
make target=Darwin install
If your target system does not have GNU Make (or equivalent), then
you should try using the Makefile.simple and custom/Makefile.simple
files:

View File

@@ -575,7 +575,7 @@ HAVE_UNUSED=
ifeq ($(target),Darwin)
# default INCDIR for macOS
INCDIR= /usr/local/include
INCDIR= $(shell xcrun --show-sdk-path --sdk macosx)/usr/include
else
#endif /* end of skip for non-Gnu makefiles */
@@ -1054,7 +1054,7 @@ EXT=
# The default calc versions
#
VERSION= 2.12.6.8
VERSION= 2.12.6.9
# Names of shared libraries with versions
#
@@ -2179,7 +2179,7 @@ TARGETS= ${EARLY_TARGETS} ${BLD_TYPE} ${LATE_TARGETS}
all: check_include ${BLD_TYPE} CHANGES
check_include:
$(Q) if [ ! -d /usr/include ]; then \
$(Q) if [ ! -d ${INCDIR} ]; then \
echo "ERROR: critical directory missing: /usr/include" 1>&2; \
echo "Without this critical directory, we cannot compile." 1>&2; \
echo 1>&2; \
@@ -2191,7 +2191,7 @@ check_include:
echo 1>&2; \
exit 1; \
fi
$(Q) if [ ! -f /usr/include/stdio.h ]; then \
$(Q) if [ ! -f ${INCDIR}/stdio.h ]; then \
echo "ERROR: critical include files are missing" 1>&2; \
echo "Without this critical directory, we cannot compile." 1>&2; \
echo 1>&2; \

View File

@@ -3227,9 +3227,9 @@ define test_error()
print '3600: Beginning test_error';
/* bump ecnt up by 148 */
ecnt += 148;
print '3601: ecnt += 148';
/* bump ecnt up by 156 */
ecnt += 156;
print '3601: ecnt += 156';
strx = "x";
print '3602: strx = "x"';
@@ -3418,11 +3418,15 @@ define test_error()
n = 8191;
print '3727: n = 8191';
/* test 3728 removed due to non-portable strerror() output */
vrfy(tan(2e9i) == error(10435), '3729: tan(2e9i) == error(10435)');
vrfy(cot(2e9i) == error(10437), '3730: cot(2e9i) == error(10437)');
vrfy(sec(2e9i) == error(10439), '3731: sec(2e9i) == error(10439)');
vrfy(csc(2e9i) == error(10440), '3732: csc(2e9i) == error(10440)');
/* errmax and errcount should be bumped up the 148 errors above */
vrfy(errcount() == ecnt, '3729: errcount() == ecnt');
vrfy(errcount() == ecnt, '3733: errcount() == ecnt');
print '3730: Ending test_error';
print '3734: Ending test_error';
}
print '054: parsed test_error()';
@@ -4102,38 +4106,46 @@ define test_strprintf()
'4821: strprintf("%b", 27/29) == "0b11011/0b11101"');
vrfy(strprintf("%e", 12345) == "~1.23e4",
'4822: strprintf("%e", 12345) == "~1.23e4"');
vrfy(strprintf("%g", .385) == "~.38",
'4823: strprintf("%g", .385) == "~.38"');
vrfy(strprintf("%g", 385) == "~3.8e2",
'4824: strprintf("%g", 385) == "~3.8e2"');
/* mode tests with tilde == 0 */
c = config("tilde", 0);
print '4823: c = config("tilde", 0)';
print '4825: c = config("tilde", 0)';
vrfy(strprintf("%e", 12345) == "1.23e4",
'4824: strprintf("%e", 12345) == "1.23e4"');
'4826: strprintf("%e", 12345) == "1.23e4"');
vrfy(strprintf("%.3e", 12345) == "1.234e4",
'4825: strprintf("%.3e", 12345) == "1.234e4"');
'4827: strprintf("%.3e", 12345) == "1.234e4"');
vrfy(strprintf("%e", .00012345) == "1.23e-4",
'4826: strprintf("%e", .00012345) == "1.23e-4"');
'4828: strprintf("%e", .00012345) == "1.23e-4"');
vrfy(strprintf("%d %d", 27) == "27 ",
'4827: strprintf("%d %d", 27) == "27 "');
'4829: strprintf("%d %d", 27) == "27 "');
vrfy(strprintf("%d", 27, 29) == "27",
'4828: strprintf("%d", 27, 29) == "27"');
'4830: strprintf("%d", 27, 29) == "27"');
vrfy(strprintf("%r = %f", 27/29, 27/29) == "27/29 = .93",
'4829: strprintf("%r = %f", 27/29, 27/29) == "27/29 = .93"');
'4831: strprintf("%r = %f", 27/29, 27/29) == "27/29 = .93"');
vrfy(strprintf("%s", "abc") == "abc",
'4830: strprintf("%s", "abc") == "abc"');
'4832: strprintf("%s", "abc") == "abc"');
vrfy(strprintf("%f", "abc") == "abc",
'4831: strprintf("%f", "abc") == "abc"');
'4833: strprintf("%f", "abc") == "abc"');
vrfy(strprintf("%e", "abc") == "abc",
'4832: strprintf("%e", "abc") == "abc"');
'4834: strprintf("%e", "abc") == "abc"');
vrfy(strprintf("%5s", "abc") == " abc",
'4833: strprintf("%5s", "abc") == " abc"');
'4835: strprintf("%5s", "abc") == " abc"');
vrfy(strprintf("%-5s", "abc") == "abc ",
'4834: strprintf("%-5s", "abc") == "abc "');
'4836: strprintf("%-5s", "abc") == "abc "');
vrfy(strprintf("%g", .385) == ".38",
'4837: strprintf("%g", .385) == ".38"');
vrfy(strprintf("%g", 385) == "3.8e2",
'4838: strprintf("%g", 385) == "3.8e2"');
/* restore config */
c = config("all", callcfg);
print '4835: c = config("all", callcfg)';
print '4839: c = config("all", callcfg)';
print '4836: Ending test_strprintf';
print '4840: Ending test_strprintf';
}
print '088: parsed test_fileop()';
@@ -7932,8 +7944,8 @@ print '8901: read -once "test8900"';
read -once "test8900";
print '8902: about to run test8900(1,,8903)';
testnum = test8900(1,,8903);
print '8999: ecnt = 203;'
ecnt = 203;
print '8999: ecnt = 211;'
ecnt = 211;
/* 89xx: test calc resource functions by Christoph Zurnieden */

View File

@@ -451,6 +451,7 @@ E_FPATHOPEN1 Non-string arguments for fpathopen
E_FPATHOPEN2 Unrecognized mode for fpathopen
E_LOG1 Bad epsilon argument for log
E_LOG2 Non-numeric first argument for log
E_LOG3 Cannot calculate log for this value
E_FGETFILE1 Non-file argument for fgetfile
E_FGETFILE2 File argument for fgetfile not open for reading
E_FGETFILE3 Unable to set file position in fgetfile
@@ -471,3 +472,27 @@ E_ISSPACE Bad argument for isspace
E_ISXDIGIT Bad argument for isxdigit
E_STRTOUPPER Bad argument type for strtoupper
E_STRTOLOWER Bad argument type for strtolower
E_TAN3 Invalid value for calculating the sin numerator for tan
E_TAN4 Invalid value for calculating the cos denominator for tan
E_COT3 Invalid value for calculating the sin numerator for cot
E_COT4 Invalid value for calculating the cos denominator for cot
E_SEC3 Invalid value for calculating the cos reciprocal for sec
E_CSC3 Invalid value for calculating the sin reciprocal for csc
E_TANH3 Invalid value for calculating the sinh numerator for tanh
E_TANH4 Invalid value for calculating the cosh denominator for tanh
E_COTH3 Invalid value for calculating the sinh numerator for coth
E_COTH4 Invalid value for calculating the cosh denominator for coth
E_SECH3 Invalid value for calculating the cosh reciprocal for sech
E_CSCH3 Invalid value for calculating the sinh reciprocal for csch
E_ASIN3 Invalid value for calculating asin
E_ACOS3 Invalid value for calculating acos
E_ASINH3 Invalid value for calculating asinh
E_ACOSH3 Invalid value for calculating acosn
E_ATAN3 Invalid value for calculating atan
E_ACOT3 Invalid value for calculating acot
E_ASEC3 Invalid value for calculating asec
E_ACSC3 Invalid value for calculating acsc
E_ATANH3 Invalid value for calculating atan
E_ACOTH3 Invalid value for calculating acot
E_ASECH3 Invalid value for calculating asec
E_ACSCH3 Invalid value for calculating acsc

View File

@@ -274,6 +274,7 @@ STATIC NAMETYPE modes[] = {
{"oct", MODE_OCTAL},
{"binary", MODE_BINARY},
{"bin", MODE_BINARY},
{"float-auto", MODE_REAL_AUTO},
{"off", MODE2_OFF},
{NULL, 0}
};

View File

@@ -348,7 +348,7 @@ EXT=
# The default calc versions
#
VERSION= 2.12.6.8
VERSION= 2.12.6.9
# Names of shared libraries with versions
#

View File

@@ -348,7 +348,7 @@ EXT=
# The default calc versions
#
VERSION= 2.12.6.8
VERSION= 2.12.6.9
# Names of shared libraries with versions
#

3
file.c
View File

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

99
func.c
View File

@@ -2122,6 +2122,9 @@ f_log(int count, VALUE **vals)
default:
return error_value(E_LOG2);
}
if (c == NULL) {
return error_value(E_LOG3);
}
result.v_type = V_COM;
result.v_com = c;
if (cisreal(c)) {
@@ -2239,8 +2242,15 @@ f_tan(int count, VALUE **vals)
case V_COM:
tmp1.v_type = V_COM;
tmp1.v_com = c_sin(vals[0]->v_com, err);
if (tmp1.v_com == NULL) {
return error_value(E_TAN3);
}
tmp2.v_type = V_COM;
tmp2.v_com = c_cos(vals[0]->v_com, err);
if (tmp2.v_com == NULL) {
comfree(tmp1.v_com);
return error_value(E_TAN4);
}
divvalue(&tmp1, &tmp2, &result);
comfree(tmp1.v_com);
comfree(tmp2.v_com);
@@ -2276,6 +2286,9 @@ f_sec(int count, VALUE **vals)
case V_COM:
tmp.v_type = V_COM;
tmp.v_com = c_cos(vals[0]->v_com, err);
if (tmp.v_com == NULL) {
return error_value(E_SEC3);
}
invertvalue(&tmp, &result);
comfree(tmp.v_com);
break;
@@ -2314,8 +2327,15 @@ f_cot(int count, VALUE **vals)
case V_COM:
tmp1.v_type = V_COM;
tmp1.v_com = c_cos(vals[0]->v_com, err);
if (tmp1.v_com == NULL) {
return error_value(E_COT3);
}
tmp2.v_type = V_COM;
tmp2.v_com = c_sin(vals[0]->v_com, err);
if (tmp2.v_com == NULL) {
comfree(tmp1.v_com);
return error_value(E_COT4);
}
divvalue(&tmp1, &tmp2, &result);
comfree(tmp1.v_com);
comfree(tmp2.v_com);
@@ -2354,6 +2374,9 @@ f_csc(int count, VALUE **vals)
case V_COM:
tmp.v_type = V_COM;
tmp.v_com = c_sin(vals[0]->v_com, err);
if (tmp.v_com == NULL) {
return error_value(E_CSC3);
}
invertvalue(&tmp, &result);
comfree(tmp.v_com);
break;
@@ -2476,8 +2499,15 @@ f_tanh(int count, VALUE **vals)
case V_COM:
tmp1.v_type = V_COM;
tmp1.v_com = c_sinh(vals[0]->v_com, err);
if (tmp1.v_com == NULL) {
return error_value(E_TANH3);
}
tmp2.v_type = V_COM;
tmp2.v_com = c_cosh(vals[0]->v_com, err);
if (tmp2.v_com == NULL) {
comfree(tmp1.v_com);
return error_value(E_TANH4);
}
divvalue(&tmp1, &tmp2, &result);
comfree(tmp1.v_com);
comfree(tmp2.v_com);
@@ -2517,8 +2547,15 @@ f_coth(int count, VALUE **vals)
case V_COM:
tmp1.v_type = V_COM;
tmp1.v_com = c_cosh(vals[0]->v_com, err);
if (tmp1.v_com == NULL) {
return error_value(E_COTH3);
}
tmp2.v_type = V_COM;
tmp2.v_com = c_sinh(vals[0]->v_com, err);
if (tmp2.v_com == NULL) {
comfree(tmp1.v_com);
return error_value(E_COTH4);
}
divvalue(&tmp1, &tmp2, &result);
comfree(tmp1.v_com);
comfree(tmp2.v_com);
@@ -2555,6 +2592,9 @@ f_sech(int count, VALUE **vals)
case V_COM:
tmp.v_type = V_COM;
tmp.v_com = c_cosh(vals[0]->v_com, err);
if (tmp.v_com == NULL) {
return error_value(E_SECH3);
}
invertvalue(&tmp, &result);
comfree(tmp.v_com);
break;
@@ -2592,6 +2632,9 @@ f_csch(int count, VALUE **vals)
case V_COM:
tmp.v_type = V_COM;
tmp.v_com = c_sinh(vals[0]->v_com, err);
if (tmp.v_com == NULL) {
return error_value(E_CSCH3);
}
invertvalue(&tmp, &result);
comfree(tmp.v_com);
break;
@@ -2626,7 +2669,7 @@ f_atan(int count, VALUE **vals)
case V_COM:
tmp = c_atan(vals[0]->v_com, err);
if (tmp == NULL)
return error_value(E_LOGINF);
return error_value(E_ATAN3);
result.v_type = V_COM;
result.v_com = tmp;
if (cisreal(tmp)) {
@@ -2666,7 +2709,7 @@ f_acot(int count, VALUE **vals)
case V_COM:
tmp = c_acot(vals[0]->v_com, err);
if (tmp == NULL)
return error_value(E_LOGINF);
return error_value(E_ACOT3);
result.v_type = V_COM;
result.v_com = tmp;
if (cisreal(tmp)) {
@@ -2718,6 +2761,9 @@ f_asin(int count, VALUE **vals)
default:
return error_value(E_ASIN2);
}
if (result.v_com == NULL) {
return error_value(E_ASIN3);
}
if (result.v_type == V_COM && cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -2764,6 +2810,9 @@ f_acos(int count, VALUE **vals)
default:
return error_value(E_ACOS2);
}
if (result.v_com == NULL) {
return error_value(E_ACOS3);
}
if (result.v_type == V_COM && cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -2794,7 +2843,7 @@ f_asec(int count, VALUE **vals)
switch (vals[0]->v_type) {
case V_NUM:
if (qiszero(vals[0]->v_num))
return error_value(E_LOGINF);
return error_value(E_ASEC3);
result.v_num = qasec(vals[0]->v_num, err);
result.v_type = V_NUM;
if (result.v_num == NULL) {
@@ -2813,9 +2862,10 @@ f_asec(int count, VALUE **vals)
default:
return error_value(E_ASEC2);
}
if (result.v_com == NULL) {
return error_value(E_ASEC3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -2847,7 +2897,7 @@ f_acsc(int count, VALUE **vals)
switch (vals[0]->v_type) {
case V_NUM:
if (qiszero(vals[0]->v_num))
return error_value(E_LOGINF);
return error_value(E_ACSC3);
result.v_num = qacsc(vals[0]->v_num, err);
result.v_type = V_NUM;
if (result.v_num == NULL) {
@@ -2866,9 +2916,10 @@ f_acsc(int count, VALUE **vals)
default:
return error_value(E_ACSC2);
}
if (result.v_com == NULL) {
return error_value(E_ACSC3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -2903,6 +2954,9 @@ f_asinh(int count, VALUE **vals)
break;
case V_COM:
tmp = c_asinh(vals[0]->v_com, err);
if (tmp == NULL) {
return error_value(E_ASINH3);
}
result.v_type = V_COM;
result.v_com = tmp;
if (cisreal(tmp)) {
@@ -2955,6 +3009,9 @@ f_acosh(int count, VALUE **vals)
default:
return error_value(E_ACOSH2);
}
if (result.v_com == NULL) {
return error_value(E_ACOSH3);
}
if (result.v_type == V_COM && cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -3002,9 +3059,10 @@ f_atanh(int count, VALUE **vals)
default:
return error_value(E_ATANH2);
}
if (result.v_com == NULL) {
return error_value(E_ATANH3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -3053,9 +3111,10 @@ f_acoth(int count, VALUE **vals)
default:
return error_value(E_ACOTH2);
}
if (result.v_com == NULL) {
return error_value(E_ACOTH3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -3087,7 +3146,7 @@ f_asech(int count, VALUE **vals)
switch (vals[0]->v_type) {
case V_NUM:
if (qiszero(vals[0]->v_num))
return error_value(E_LOGINF);
return error_value(E_ASECH3);
result.v_num = qasech(vals[0]->v_num, err);
result.v_type = V_NUM;
if (result.v_num == NULL) {
@@ -3106,9 +3165,10 @@ f_asech(int count, VALUE **vals)
default:
return error_value(E_ASECH2);
}
if (result.v_com == NULL) {
return error_value(E_ASECH3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -3140,7 +3200,7 @@ f_acsch(int count, VALUE **vals)
switch (vals[0]->v_type) {
case V_NUM:
if (qiszero(vals[0]->v_num))
return error_value(E_LOGINF);
return error_value(E_ACSCH3);
result.v_num = qacsch(vals[0]->v_num, err);
result.v_type = V_NUM;
if (result.v_num == NULL) {
@@ -3159,9 +3219,10 @@ f_acsch(int count, VALUE **vals)
default:
return error_value(E_ACSCH2);
}
if (result.v_com == NULL) {
return error_value(E_ACSCH3);
}
if (result.v_type == V_COM) {
if (result.v_com == NULL)
return error_value(E_LOGINF);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);
@@ -3260,7 +3321,7 @@ f_agd(int count, VALUE **vals)
return error_value(E_AGD2);
}
if (result.v_com == NULL)
return error_value(E_AGD3);
return error_value(E_AGD3);
if (cisreal(result.v_com)) {
q = qlink(result.v_com->real);
comfree(result.v_com);

View File

@@ -28,7 +28,7 @@ DESCRIPTION
zero or more decimal digits
an optional '. followed by zero or more decimal deigits
an optional 'l'
one of the letters: d, s, c, f, e, r, o, x, b,
one of the letters: d, s, c, f, e, g, r, o, x, b,
If any other character is read, the '%' and any characters
between '%' and the character are ignored and no specifier is
@@ -51,26 +51,27 @@ DESCRIPTION
d, s, c current config("mode")
f real (decimal, floating point)
e exponential
g real or exponential depending on config("display")
r fractional
o octal
x hexadecimal
b binary
If the number of arguments after fmt is less than the
number of format specifiers in fmt, the "missing" arguments
may be taken to be null values - these contribute nothing to the
output; if a positive width w has been specified, the effect is
to produce w spaces, e.g. printf("abc%6dxyz") prints "abc xyz".
If the number of arguments after fmt is less than the number
of format specifiers in fmt, the "missing" arguments may be
taken to be null values - these contribute nothing to the output;
if a positive width w has been specified, the effect is to
produce w spaces, e.g., printf("abc%6dxyz") prints "abc xyz".
If i <= the number of specifiers in fmt, the value of argument x_i
is printed in the format specified by the i-th specifier.
If a positive width w has been specified and normal printing of x_i
does not include a '\n' character, what is printed will if necessary
be padded with spaces so that the length of the printed output
is at least the w. Note that control
characters like '\t', '\b' each count as one character. If
the 'right-pad' flag has been set, the padding is on the right;
otherwise it is on the left.
If i <= the number of specifiers in fmt, the value of argument
x_i is printed in the format specified by the i-th specifier.
If a positive width w has been specified and normal printing
of x_i does not include a '\n' character, what is printed will
if necessary be padded with spaces so that the length of the
printed output is at least the w. Note that control characters
like '\t', '\b' each count as one character. If the 'right-pad'
flag has been set, the padding is on the right; otherwise it
is on the left.
If i > the number of specifiers in fmt, the value of argument x_i
does not contribute to the printing. However, as all arguments
@@ -84,9 +85,9 @@ DESCRIPTION
mode.
In the case of floating-point (f) format the precision determines
the maximum number of decimal places to be
displayed. Other aspects of this printing may be affected by the
configuration parameters "outround", "tilde", "fullzero", "leadzero".
the maximum number of decimal places to be displayed. Other
aspects of this printing may be affected by the configuration
parameters "outround", "tilde", "fullzero", "leadzero".
EXAMPLE
; c = config("epsilon", 1e-6); c = config("display", 6);
@@ -116,6 +117,11 @@ EXAMPLE
[2] = "undefined"
[3] = NULL
; c = config("display", 50);
; printf("%g %g\n%g %g\n", 1e5, 1e49, 1e50, 1e500);
100000 100000000000000000000000000000000000000000000000000
1e50 1e500
LIMITS
The number of arguments of printf() is not to exceed 1024.
@@ -126,7 +132,7 @@ LINK LIBRARY
SEE ALSO
fprintf, strprintf, print
## Copyright (C) 1999-2006 Landon Curt Noll
## Copyright (C) 1999-2006,2018 Landon Curt Noll
##
## Calc is open software; you can redistribute it and/or modify it under
## the terms of the version 2.1 of the GNU Lesser General Public License

View File

@@ -27,6 +27,13 @@ EXAMPLE
"1.732051, 1.732051,1.732051 , ~1.7320,~1.7320,~1.
"
; c = config("display", 50);
; fmt2 = "%g %g\n%g %g\n"
; strprintf(fmt2, 1e5, 1e49, 1e50, 1e500);
"100000 100000000000000000000000000000000000000000000000000
1e50 1e500
"
LIMITS
The number of arguments of strprintf() is not to exceed 1024.
@@ -39,7 +46,7 @@ SEE ALSO
printf, fprintf, print
## Copyright (C) 1999-2006 Landon Curt Noll
## Copyright (C) 1999-2006,2018 Landon Curt Noll
##
## Calc is open software; you can redistribute it and/or modify it under
## the terms of the version 2.1 of the GNU Lesser General Public License

36
qio.c
View File

@@ -97,6 +97,15 @@ qprintf(char *fmt, ...)
q = va_arg(ap, NUMBER *);
qprintfe(q, width, precision);
break;
case 'g':
q = va_arg(ap, NUMBER *);
/* XXX - we need a qprintfg function */
#if 0 /* XXX - we need a qprintfg() function */
qprintfg(q, width, precision);
#else /* XXX - use qprintfe until we have a qprintfg() function */
qprintfe(q, width, precision);
#endif /* XXX - we need a qprintfg() function */
break;
case 'r':
case 'R':
q = va_arg(ap, NUMBER *);
@@ -233,6 +242,33 @@ qprintnum(NUMBER *q, int outmode)
PRINTF1("e%ld", exp);
break;
case MODE_REAL_AUTO:
{
/*
* XXX - re-write to not modify conf->outdigits
*
* Modifying the configuration value could be dangerious
* when a calculation is aborted within an opcode.
* Better to use qprintfg() use inline code that
* does not depend on changing conf->outdigits.
*/
const int P = conf->outdigits ? conf->outdigits : 1;
long olddigits;
tmpval = *q;
tmpval.num.sign = 0;
exp = qilog10(&tmpval);
olddigits = conf->outdigits;
if (P > exp && exp >= -P) {
conf->outdigits = P - 1 - exp;
qprintnum(q, MODE_REAL);
} else {
conf->outdigits = P - 1;
qprintnum(q, MODE_EXP);
}
conf->outdigits = olddigits;
break;
}
case MODE_HEX:
qprintfx(q, 0L);
break;

View File

@@ -45,7 +45,7 @@ static char *program;
#define MAJOR_VER 2 /* major library version */
#define MINOR_VER 12 /* minor library version */
#define MAJOR_PATCH 6 /* major software level under library version */
#define MINOR_PATCH 8 /* minor software level or 0 if not patched */
#define MINOR_PATCH 9 /* minor software level or 0 if not patched */
/*

View File

@@ -579,10 +579,16 @@ E_FUNC void zredcpower(REDC *rp, ZVALUE z1, ZVALUE z2, ZVALUE *res);
#define MODE_HEX 5
#define MODE_OCTAL 6
#define MODE_BINARY 7
#define MODE_MAX 7
#define MODE_REAL_AUTO 8
#define MODE_MAX 8
#define MODE2_OFF (MODE_MAX+1)
/* XXX - perhaps we need the MODE_REAL_AUTO vs MODE_REAL as a config mode? */
#if 0 /* XXX - can we safely set MODE_INITIAL to MODE_REAL_AUTO ?? */
#define MODE_INITIAL MODE_REAL_AUTO
#else
#define MODE_INITIAL MODE_REAL
#endif
#define MODE2_INITIAL MODE2_OFF