From 86f1d9e029dd95d31e796a23cc0b0f4ea63326c0 Mon Sep 17 00:00:00 2001 From: Landon Curt Noll Date: Sun, 3 Sep 2023 23:37:09 -0700 Subject: [PATCH] add new aversin and acoversin builtin functions. Added new aversin(x, [,eps]) for inverse versed sine and acoversin(x, [,eps]) for inverse coversed sine. Improved trig function help files to reference use of complex arguments that while supported were not documented. Removed old Makefile testing rules for make dbx and make gdb. Improved "make run" to execute calccalc using shared libraries from the local directory, and with reading of the startup scripts disabled. Changed "make prep" to perform various tests that are used to help verify that calc is ready for a release. Added Makefile testing rule testfuncsort to check for the sort of the builtin function list. Changed the order that builtin functions are listed by "show builtin" and the help/builtin to match the sorting of "LANG=C LC_ALL=C sort -d -u". --- .gitignore | 2 + CHANGES | 26 +++- Makefile | 99 ++++++++++++--- Makefile.config | 1 + cal/regress.cal | 30 ++++- calcerr.tbl | 6 + cmath.h | 2 + comfunc.c | 108 ++++++++++++++++- func.c | 312 +++++++++++++++++++++++++++++++++++++----------- help/Makefile | 63 +++++----- help/acos | 17 ++- help/acot | 19 ++- help/acoversin | 63 ++++++++++ help/acsc | 19 ++- help/asec | 19 ++- help/asin | 17 ++- help/atan | 19 ++- help/aversin | 64 ++++++++++ help/cos | 7 +- help/cot | 5 +- help/coversin | 9 +- help/csc | 7 +- help/sec | 7 +- help/sin | 5 +- help/tan | 5 +- help/versin | 7 +- qmath.h | 4 + qtrans.c | 267 +++++++++++++++++++++++++++++++++++++++-- trailblank | 200 +++++++++++++++++++++++++++++++ update_ver | 189 +++++++++++++++++++++++++++++ 30 files changed, 1421 insertions(+), 177 deletions(-) create mode 100644 help/acoversin create mode 100644 help/aversin create mode 100755 trailblank create mode 100755 update_ver diff --git a/.gitignore b/.gitignore index e038844..0583566 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ endian endian_calc.h fposval fposval.h +func.show +func.sort have_arc4random have_arc4random.h have_ban_pragma diff --git a/CHANGES b/CHANGES index 9df9f1a..443b4cb 100644 --- a/CHANGES +++ b/CHANGES @@ -100,7 +100,31 @@ The following are the changes from calc version 2.14.3.5 to date: the LIMIT range for such eps values. Added new versin(x, [,eps]) for versed sine and coversin(x, [,eps]) - for versed cosine. + for inverse versed sine. + + Added new aversin(x, [,eps]) for inverse versed sine and acoversin(x, [,eps]) + for inverse coversed sine. + + Improved trig function help files to reference use of complex arguments + that while supported were not documented. + + Removed old Makefile testing rules for make dbx and make gdb. + + Improved "make run" to execute calccalc using shared libraries + from the local directory, and with reading of the startup scripts + disabled. + + Changed "make prep" to perform various tests that are used to + help verify that calc is ready for a release. Added the + update_ver tool, (formerly verupdate) and the trailblank tool + that existed outside of the calc source base but neverthless + used in the calc release process. Both of these tools are used + by "make prep". + + Added Makefile testing rule "make testfuncsort" to check for + the sort of the builtin function list. Changed the order that + builtin functions are listed by "show builtin" and the help/builtin + to match the sorting of "LANG=C LC_ALL=C sort -d -u". The following are the changes from calc version 2.14.3.4 to 2.14.3.5: diff --git a/Makefile b/Makefile index 11e7d10..a1e7f8d 100644 --- a/Makefile +++ b/Makefile @@ -327,9 +327,18 @@ STATIC_FIRST_TARGETS= ${LICENSE} .static LATE_TARGETS= calc.1 calc.usage \ cal/.all help/.all help/builtin cscript/.all +# calc tools - tools used by the maintainers of the calc source base +# +# trailblank - find trailing blanks and other file format picky issues +# update_ver - update version numbers in Makefile.config +# +TRAILBLANK= trailblank +UPDATE_VER= update_ver +CALC_TOOLS= ${TRAILBLANK} ${UPDATE_VER} + # complete list of targets # -TARGETS= ${EARLY_TARGETS} ${BLD_TYPE} ${LATE_TARGETS} +TARGETS= ${EARLY_TARGETS} ${BLD_TYPE} ${LATE_TARGETS} ${CALC_TOOLS} # rules that are not also names of files # @@ -372,9 +381,6 @@ check_include: exit 1; \ fi -prep: - ${Q} ${MAKE} -f ${MAKE_FILE} all DEBUG='-g3' - calc-dynamic-only: ${DYNAMIC_FIRST_TARGETS} ${EARLY_TARGETS} \ ${CALC_DYNAMIC_LIBS} ${SYM_DYNAMIC_LIBS} calc${EXT} \ ${SAMPLE_TARGETS} ${LATE_TARGETS} @@ -2979,6 +2985,7 @@ env: @echo 'SAMPLE_STATIC_TARGETS=${SAMPLE_STATIC_TARGETS}'; echo '' @echo 'SAMPLE_TARGETS=${SAMPLE_TARGETS}'; echo '' @echo 'SCRIPTDIR=${SCRIPTDIR}'; echo '' + @echo 'SDIFF=${SDIFF}'; echo '' @echo 'SED=${SED}'; echo '' @echo 'SHELL=${SHELL}'; echo '' @echo 'SORT=${SORT}'; echo '' @@ -3089,27 +3096,82 @@ debug: ### # -# testing rules +# maintainer rules - rules that are useful for people who maintain the calc source # -# make run -# * only run calc interactively with the ${CALC_ENV} environment +# testfuncsort # -# make dbx -# * run the dbx debugger on calc with the ${CALC_ENV} environment +# Check on the sort of the builtin function list. +# If the builtins[] array in func.c is in dictionary sorted order, +# this rule prints nothing. If there is a builtin function that +# is out of order, sdiff is used to print the builtin function sort +# problem and does an exit 1. # -# make gdb -# * run the gdb debugger on calc with the ${CALC_ENV} environment +# prep +# +# Perform tests and build actions that are needed prior to a release +# of calc. The "make prep" should NOT exit non-zero but instead it +# should print "All is OK" and exit 0. +# +# run +# +# Execute calc using shared libraries from the local directory. +# Run calc with reading of the startup scripts disabled. # ### +testfuncsort: ./calc${EXT} + @${RM} -f func.show func.sort + @CALCPATH=./cal LD_LIBRARY_PATH=. DYLD_LIBRARY_PATH=. CALCHELP=./help CALCCUSTOMHELP=./custom \ + ./calc${EXT} -d -u show builtin | grep '^[A-Za-z0-9]' > func.show + @CALCPATH=./cal LD_LIBRARY_PATH=. DYLD_LIBRARY_PATH=. CALCHELP=./help CALCCUSTOMHELP=./custom \ + ./calc${EXT} -d -u show builtin | grep '^[A-Za-z0-9]' | LANG=C LC_ALL=C ${SORT} -d -u > func.sort + @-if ! cmp -s func.show func.sort; then \ + echo 1>&2; \ + echo "ERROR: builtins[] arrray in func.c is not in dictionary sorted order" 1>&2; \ + echo 1>&2; \ + echo "CALCPATH=./cal LD_LIBRARY_PATH=. DYLD_LIBRARY_PATH=. CALCHELP=./help CALCCUSTOMHELP=./custom" \ + "./calc${EXT} -d -u show builtin | grep '^[A-Za-z0-9]' > func.show" 1>&2; \ + echo "CALCPATH=./cal LD_LIBRARY_PATH=. DYLD_LIBRARY_PATH=. CALCHELP=./help CALCCUSTOMHELP=./custom" \ + "./calc${EXT} -d -u show builtin | grep '^[A-Za-z0-9]' | LANG=C LC_ALL=C ${SORT} -d -u > func.sort" 1>&2; \ + echo 1>&2; \ + echo ${SDIFF} func.show func.sort 1>&2; \ + echo 1>&2; \ + ${SDIFF} func.show func.sort 1>&2; \ + exit 1; \ + fi + @${RM} -f func.show func.sort + +prep: + echo '=-=-= start of ${MAKE} clobber =-=-=' + ${MAKE} clobber + echo '=-=-= end of ${MAKE} clobber =-=-=' + echo '=-=-= start of ${TRAILBLANK} =-=-=' + ./${TRAILBLANK} + echo '=-=-= end of ${TRAILBLANK} =-=-=' + echo '=-=-= start of ${MAKE} all CCWERR=-Werror =-=-=' + ${MAKE} all CCWERR=-Werror + echo '=-=-= end of ${MAKE} all CCWERR=-Werror =-=-=' + echo '=-=-= start of ${MAKE} tags =-=-=' + ${MAKE} tags + echo '=-=-= end of ${MAKE} tags =-=-=' + echo '=-=-= start of ${MAKE} depend =-=-=' + ${MAKE} depend + echo '=-=-= end of ${MAKE} depend =-=-=' + echo '=-=-= start of ${MAKE} testfuncsort =-=-=' + ${MAKE} testfuncsort + echo '=-=-= end of ${MAKE} testfuncsort =-=-=' + echo '=-=-= start of ${UPDATE_VER} =-=-=' + ./${UPDATE_VER} + echo '=-=-= end of ${UPDATE_VER} =-=-=' + echo '=-=-= start of ${MAKE} chk =-=-=' + ${MAKE} chk + echo '=-=-= end of ${MAKE} chk =-=-=' + @echo + @echo All is OK + @echo + run: - ${CALC_ENV} ./calc${EXT} - -dbx: - ${CALC_ENV} dbx ./calc${EXT} - -gdb: - ${CALC_ENV} gdb ./calc${EXT} + CALCPATH=./cal LD_LIBRARY_PATH=. DYLD_LIBRARY_PATH=. CALCHELP=./help CALCCUSTOMHELP=./custom ./calc${EXT} -q ### # @@ -3329,6 +3391,7 @@ clobber: clean echo ${RM} -rf .DS_Store; \ ${RM} -rf .DS_Store; \ fi + ${RM} -f func.show func.sort ${V} echo '=-=-=-=-= ${MAKE_FILE} end of $@ rule =-=-=-=-=' # install everything diff --git a/Makefile.config b/Makefile.config index 9aecf11..09442df 100644 --- a/Makefile.config +++ b/Makefile.config @@ -1302,6 +1302,7 @@ MV= mv PWDCMD= pwd RM= rm RMDIR= rmdir +SDIFF= sdiff SED= sed SORT= sort SPLINT= splint diff --git a/cal/regress.cal b/cal/regress.cal index b004602..07fbfee 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -3507,7 +3507,7 @@ define test_trig() tnum = test3400(1, 3401); vrfy(tnum++ == 3407, '3407: tnum == 3407'); - /* test versed sine */ + /* test versed trigonometric sine */ pi = pi(1e-20); vrfy(round(versin(0.2, 1e-10), 10) == 0.0199334222, strcat(str(tnum++), @@ -3533,7 +3533,7 @@ define test_trig() strcat(str(tnum++), ': round(versin(2 + 3i, 1e-10), 10) == 5.189625691+9.1092278938i')); - /* test coversed sine */ + /* test coversed trigonometric sine */ pi = pi(1e-20); vrfy(round(coversin(0.2, 1e-10), 10) == 0.8013306692, strcat(str(tnum++), @@ -3559,6 +3559,32 @@ define test_trig() strcat(str(tnum++), ': round(coversin(2 + 3i, 1e-10), 10) == -8.1544991469+4.16890696i')); + /* test inverse versed trigonometric sine */ + vrfy(round(aversin(0.5, 1e-10), 10) == 1.0471975512, + strcat(str(tnum++), + ': round(aversin(0.5, 1e-10), 10) == 1.0471975512')); + vrfy(aversin(0) == 0, + strcat(str(tnum++), ': aversin(0) == 0')); + vrfy(round(aversin(-5, 1e-10), 10) == 0.1673829554+2.4921599676i, + strcat(str(tnum++), + ': round(aversin(0.5, 1e-10), 10) == 0.1673829554+2.4921599676i')); + vrfy(round(aversin(2 + 3i, 1e-10), 10) == 1.8783999763+1.8641615439i, + strcat(str(tnum++), + ': round(aversin(2 + 3i, 1e-10), 10) == 1.8783999763+1.8641615439i')); + + /* test inverse coversed trigonometric sine */ + vrfy(round(acoversin(0.5, 1e-10), 10) == 0.5235987756, + strcat(str(tnum++), + ': round(acoversin(0.5, 1e-10), 10) == 0.5235987756')); + vrfy(acoversin(1) == 0, + strcat(str(tnum++), ': acoversin(1) == 0')); + vrfy(round(acoversin(-5, 1e-10), 10) == 1.4034133718-2.4921599681i, + strcat(str(tnum++), + ': round(acoversin(0.5, 1e-10), 10) == 1.4034133718-2.4921599681i')); + vrfy(round(acoversin(2 + 3i, 1e-10), 10) == -0.3076036495-1.8641615442i, + strcat(str(tnum++), + ': round(acoversin(2 + 3i, 1e-10), 10) == -0.3076036495-1.8641615442i')); + print strcat(str(tnum++), ': Ending test_trig'); } print '051: parsed test_trig()'; diff --git a/calcerr.tbl b/calcerr.tbl index 0680dd2..446c75b 100644 --- a/calcerr.tbl +++ b/calcerr.tbl @@ -553,6 +553,12 @@ E_LOGN_5 Non-numeric second argument for logn E_VERSIN1 Bad epsilon for versin E_VERSIN2 Bad first argument for versin E_VERSIN3 Too-large im(argument) for versin +E_AVERSIN1 Bad epsilon for aversin +E_AVERSIN2 Bad first argument for aversin +E_AVERSIN3 Too-large im(argument) for aversin E_COVERSIN1 Bad epsilon for coversin E_COVERSIN2 Bad first argument for coversin E_COVERSIN3 Too-large im(argument) for coversin +E_ACOVERSIN1 Bad epsilon for acoversin +E_ACOVERSIN2 Bad first argument for acoversin +E_ACOVERSIN3 Too-large im(argument) for acoversin diff --git a/cmath.h b/cmath.h index 7dec39f..123bf49 100644 --- a/cmath.h +++ b/cmath.h @@ -123,7 +123,9 @@ E_FUNC COMPLEX *c_agd(COMPLEX *c, NUMBER *epsilon); * historical trig functions */ E_FUNC COMPLEX *c_versin(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_aversin(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_coversin(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_acoversin(COMPLEX *c, NUMBER *epsilon); diff --git a/comfunc.c b/comfunc.c index 75e69cb..b994f2b 100644 --- a/comfunc.c +++ b/comfunc.c @@ -1355,12 +1355,12 @@ c_versin(COMPLEX *c, NUMBER *epsilon) not_reached(); } if (check_epsilon(epsilon) == false) { - math_error("Invalid epsilon value for complex versin"); + math_error("Invalid epsilon arg for %s", __func__); not_reached(); } /* - * return r = 1 - cos(x) + * calculate complex trig function value */ ctmp = c_cos(c, epsilon); if (ctmp == NULL) { @@ -1368,11 +1368,61 @@ c_versin(COMPLEX *c, NUMBER *epsilon) not_reached(); } r = c_sub(&_cone_, ctmp); + + /* + * return complex 1 - cos(x) + */ comfree(ctmp); return r; } +/* + * c_aversin - inverse versed sine for COMPLEX values + * + * This uses the formula: + * + * aversin(x) = acos(1 - x) + * + * given: + * q complex value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * complex value result of trig function on q with error epsilon + */ +COMPLEX * +c_aversin(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* inverse trig value result */ + COMPLEX *x; /* argument to inverse trig function */ + + /* + * firewall + */ + if (c == NULL) { + math_error("%s: c is NULL", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate complex inverse trig function value + */ + x = c_sub(&_cone_, c); + r = c_acos(x, epsilon); + comfree(x); + + /* + * return complex acos(1 - x) + */ + return r; +} + + /* * c_coversin - coversed sine for COMPLEX values * @@ -1401,12 +1451,12 @@ c_coversin(COMPLEX *c, NUMBER *epsilon) not_reached(); } if (check_epsilon(epsilon) == false) { - math_error("Invalid epsilon value for complex coversin"); + math_error("Invalid epsilon arg for %s", __func__); not_reached(); } /* - * return r = 1 - sin(x) + * calculate complex trig function value */ ctmp = c_sin(c, epsilon); if (ctmp == NULL) { @@ -1414,6 +1464,56 @@ c_coversin(COMPLEX *c, NUMBER *epsilon) not_reached(); } r = c_sub(&_cone_, ctmp); + + /* + * return complex 1 - sin(x) + */ comfree(ctmp); return r; } + + +/* + * c_acoversin - inverse versed sine for COMPLEX values + * + * This uses the formula: + * + * acoversin(x) = asin(1 - x) + * + * given: + * q complex value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * complex value result of trig function on q with error epsilon + */ +COMPLEX * +c_acoversin(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* inverse trig value result */ + COMPLEX *x; /* argument to inverse trig function */ + + /* + * firewall + */ + if (c == NULL) { + math_error("%s: c is NULL", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate complex inverse trig function value + */ + x = c_sub(&_cone_, c); + r = c_asin(x, epsilon); + comfree(x); + + /* + * return complex asin(1 - x) + */ + return r; +} diff --git a/func.c b/func.c index 24b14de..e74e500 100644 --- a/func.c +++ b/func.c @@ -10641,7 +10641,7 @@ f_versin(int count, VALUE **vals) } /* - * compute sine to a given error tolerance + * compute trig function to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -10655,6 +10655,10 @@ f_versin(int count, VALUE **vals) } result.v_com = c; result.v_type = V_COM; + + /* + * case: complex trig function returned real, convert result to NUMBER + */ if (cisreal(c)) { result.v_num = qlink(c->real); result.v_type = V_NUM; @@ -10668,6 +10672,88 @@ f_versin(int count, VALUE **vals) } +/* + * f_aversin - inverse versed sine + */ +S_FUNC VALUE +f_aversin(int count, VALUE **vals) +{ + VALUE result; + COMPLEX *c; + NUMBER *eps; + + /* initialize VALUE */ + result.v_subtype = V_NOSUBTYPE; + + /* + * set error tolerance for builtin function + * + * Use eps VALUE arg if given and value is in a valid range. + */ + eps = conf->epsilon; + if (count == 2) { + if (verify_eps(vals[1]) == false) { + return error_value(E_AVERSIN1); + } + eps = vals[1]->v_num; + } + + /* + * compute inverse trig function to a given error tolerance + */ + if (vals[0]->v_type == V_NUM) { + + /* try to compute result using real triv function */ + result.v_num = qaversin_or_NULL(vals[0]->v_num, eps); + + /* + * case: trig function returned a NUMBER + */ + if (result.v_num != NULL) { + result.v_type = V_NUM; + + /* + * case: trig function returned NULL - need to try COMPLEX trig function + */ + } else { + /* convert NUMBER argument from NUMBER to COMPLEX */ + vals[0]->v_com = qqtoc(vals[0]->v_num, &_qone_); + vals[0]->v_type = V_COM; + } + } + if (vals[0]->v_type == V_COM) { + + /* + * case: argument was COMPLEX or + * trig function returned NULL and argument was converted to COMPLEX + */ + c = c_aversin(vals[0]->v_com, eps); + if (c == NULL) { + return error_value(E_AVERSIN3); + } + result.v_com = c; + result.v_type = V_COM; + + /* + * case: complex trig function returned real, convert result to NUMBER + */ + if (cisreal(c)) { + result.v_num = qlink(c->real); + result.v_type = V_NUM; + comfree(c); + } + } + if (vals[0]->v_type != V_NUM && vals[0]->v_type != V_COM) { + + /* + * case: argument type is not valid for this function + */ + return error_value(E_AVERSIN2); + } + return result; +} + + /* * f_coversin - coversed sine */ @@ -10695,7 +10781,7 @@ f_coversin(int count, VALUE **vals) } /* - * compute cosinr to a given error tolerance + * compute trig function to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -10709,6 +10795,10 @@ f_coversin(int count, VALUE **vals) } result.v_com = c; result.v_type = V_COM; + + /* + * case: complex trig function returned real, convert result to NUMBER + */ if (cisreal(c)) { result.v_num = qlink(c->real); result.v_type = V_NUM; @@ -10722,6 +10812,88 @@ f_coversin(int count, VALUE **vals) } +/* + * f_acoversin - inverse coversed sine + */ +S_FUNC VALUE +f_acoversin(int count, VALUE **vals) +{ + VALUE result; + COMPLEX *c; + NUMBER *eps; + + /* initialize VALUE */ + result.v_subtype = V_NOSUBTYPE; + + /* + * set error tolerance for builtin function + * + * Use eps VALUE arg if given and value is in a valid range. + */ + eps = conf->epsilon; + if (count == 2) { + if (verify_eps(vals[1]) == false) { + return error_value(E_ACOVERSIN1); + } + eps = vals[1]->v_num; + } + + /* + * compute inverse trig function to a given error tolerance + */ + if (vals[0]->v_type == V_NUM) { + + /* try to compute result using real triv function */ + result.v_num = qacoversin_or_NULL(vals[0]->v_num, eps); + + /* + * case: trig function returned a NUMBER + */ + if (result.v_num != NULL) { + result.v_type = V_NUM; + + /* + * case: trig function returned NULL - need to try COMPLEX trig function + */ + } else { + /* convert NUMBER argument from NUMBER to COMPLEX */ + vals[0]->v_com = qqtoc(vals[0]->v_num, &_qone_); + vals[0]->v_type = V_COM; + } + } + if (vals[0]->v_type == V_COM) { + + /* + * case: argument was COMPLEX or + * trig function returned NULL and argument was converted to COMPLEX + */ + c = c_acoversin(vals[0]->v_com, eps); + if (c == NULL) { + return error_value(E_ACOVERSIN3); + } + result.v_com = c; + result.v_type = V_COM; + + /* + * case: complex trig function returned real, convert result to NUMBER + */ + if (cisreal(c)) { + result.v_num = qlink(c->real); + result.v_type = V_NUM; + comfree(c); + } + } + if (vals[0]->v_type != V_NUM && vals[0]->v_type != V_COM) { + + /* + * case: argument type is not valid for this function + */ + return error_value(E_ACOVERSIN2); + } + return result; +} + + #endif /* !FUNCLIST */ @@ -10767,15 +10939,17 @@ STATIC CONST struct builtin builtins[] = { {"access", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_access}, "determine accessibility of file a for mode b"}, {"acos", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acos}, - "arccosine of a within accuracy b"}, + "inverse cosine of a within accuracy b"}, {"acosh", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acosh}, "inverse hyperbolic cosine of a within accuracy b"}, {"acot", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acot}, - "arccotangent of a within accuracy b"}, + "inverse cotangent of a within accuracy b"}, {"acoth", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acoth}, "inverse hyperbolic cotangent of a within accuracy b"}, + {"acoversin", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acoversin}, + "inverse coversed sine of a within accuracy b"}, {"acsc", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acsc}, - "arccosecant of a within accuracy b"}, + "inverse cosecant of a within accuracy b"}, {"acsch", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_acsch}, "inverse csch of a within accuracy b"}, {"agd", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_agd}, @@ -10789,21 +10963,23 @@ STATIC CONST struct builtin builtins[] = { {"argv", 0, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_argv}, "calc argc or argv string"}, {"asec", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_asec}, - "arcsecant of a within accuracy b"}, + "inverse secant of a within accuracy b"}, {"asech", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_asech}, "inverse hyperbolic secant of a within accuracy b"}, {"asin", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_asin}, - "arcsine of a within accuracy b"}, + "inverse sine of a within accuracy b"}, {"asinh", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_asinh}, "inverse hyperbolic sine of a within accuracy b"}, {"assoc", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_assoc}, "create new association array"}, {"atan", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_atan}, - "arctangent of a within accuracy b"}, + "inverse tangent of a within accuracy b"}, {"atan2", 2, 3, FE, OP_NOP, {.numfunc_3 = qatan2}, {.null = NULL}, "angle to point (b,a) within accuracy c"}, {"atanh", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_atanh}, "inverse hyperbolic tangent of a within accuracy b"}, + {"aversin", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_aversin}, + "inverse versed sine of a within accuracy b"}, {"avg", 0, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_avg}, "arithmetic mean of values"}, {"base", 0, 1, 0, OP_NOP, {.numfunc_cnt = f_base}, {.null = NULL}, @@ -10826,12 +11002,12 @@ STATIC CONST struct builtin builtins[] = { "round value a to b number of binary places"}, {"btrunc", 1, 2, 0, OP_NOP, {.numfunc_cnt = f_btrunc}, {.null = NULL}, "truncate a to b number of binary places"}, - {"calc_tty", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_calc_tty}, - "set tty for interactivity"}, {"calclevel", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_calclevel}, "current calculation level"}, {"calcpath", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_calcpath}, "current CALCPATH search path value"}, + {"calc_tty", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_calc_tty}, + "set tty for interactivity"}, {"catalan", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_catalan}, "catalan number for index a"}, {"ceil", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ceil}, @@ -10921,20 +11097,14 @@ STATIC CONST struct builtin builtins[] = { "evaluate expression from string to value"}, {"exp", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_exp}, "exponential of value a within accuracy b"}, - {"factor", 1, 3, 0, OP_NOP, {.numfunc_cnt = f_factor}, {.null = NULL}, - "lowest prime factor < b of a, return c if error"}, - {"fcnt", 2, 2, 0, OP_NOP, {.numfunc_2 = f_faccnt}, {.null = NULL}, - "count of times one number divides another"}, - {"fib", 1, 1, 0, OP_NOP, {.numfunc_1 = qfib}, {.null = NULL}, - "Fibonacci number F(n)"}, - {"forall", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_forall}, - "do function for all elements of list or matrix"}, - {"frem", 2, 2, 0, OP_NOP, {.numfunc_2 = qfacrem}, {.null = NULL}, - "number with all occurrences of factor removed"}, {"fact", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_fact}, "factorial"}, + {"factor", 1, 3, 0, OP_NOP, {.numfunc_cnt = f_factor}, {.null = NULL}, + "lowest prime factor < b of a, return c if error"}, {"fclose", 0, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_fclose}, "close file"}, + {"fcnt", 2, 2, 0, OP_NOP, {.numfunc_2 = f_faccnt}, {.null = NULL}, + "count of times one number divides another"}, {"feof", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_feof}, "whether EOF reached for file"}, {"ferror", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ferror}, @@ -10954,12 +11124,16 @@ STATIC CONST struct builtin builtins[] = { {"fgetstr", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_fgetstr}, "read next null-terminated string from file, null\n" "\t\t\tcharacter is kept"}, + {"fib", 1, 1, 0, OP_NOP, {.numfunc_1 = qfib}, {.null = NULL}, + "Fibonacci number F(n)"}, {"files", 0, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_files}, "return opened file or max number of opened files"}, {"floor", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_floor}, "greatest integer less than or equal to number"}, {"fopen", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_fopen}, "open file name a in mode b"}, + {"forall", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_forall}, + "do function for all elements of list or matrix"}, {"fpathopen", 2, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_fpathopen}, "open file name a in mode b, search for a along\n" "\t\t\tCALCPATH or path c"}, @@ -10971,6 +11145,8 @@ STATIC CONST struct builtin builtins[] = { "write one or more strings to a file"}, {"fputstr", 2, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_fputstr}, "write one or more null-terminated strings to a file"}, + {"frac", 1, 1, 0, OP_FRAC, {.numfunc_1 = qfrac}, {.null = NULL}, + "fractional part of value"}, {"free", 0, IN, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_free}, "free listed or all global variables"}, {"freebernoulli", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_freebern}, @@ -10983,6 +11159,8 @@ STATIC CONST struct builtin builtins[] = { "free redc data cache"}, {"freestatics", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_freestatics}, "free all un-scoped static variables"}, + {"frem", 2, 2, 0, OP_NOP, {.numfunc_2 = qfacrem}, {.null = NULL}, + "number with all occurrences of factor removed"}, {"freopen", 2, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_freopen}, "reopen a file stream to a named file"}, {"fscan", 2, IN, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_fscan}, @@ -10997,8 +11175,6 @@ STATIC CONST struct builtin builtins[] = { "return the size of the file"}, {"ftell", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ftell}, "return the file position"}, - {"frac", 1, 1, 0, OP_FRAC, {.numfunc_1 = qfrac}, {.null = NULL}, - "fractional part of value"}, {"g2d", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_g2d}, "convert gradians to degrees"}, {"g2gm", 3, 4, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_g2gm}, @@ -11032,22 +11208,22 @@ STATIC CONST struct builtin builtins[] = { "high bit number in base 2 representation"}, {"hm2h", 2, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_hm2h}, "convert a hours, b min to hours, rounding type c\n"}, - {"hms2h", 3, 4, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_hms2h}, - "convert a hours, b min, c sec to hours, rounding type d\n"}, {"hmean", 0, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_hmean}, "harmonic mean of values"}, + {"hms2h", 3, 4, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_hms2h}, + "convert a hours, b min, c sec to hours, rounding type d\n"}, {"hnrmod", 4, 4, 0, OP_NOP, {.numfunc_4 = f_hnrmod}, {.null = NULL}, "v mod h*2^n+r, h>0, n>0, r = -1, 0 or 1"}, {"hypot", 2, 3, FE, OP_NOP, {.numfunc_3 = qhypot}, {.null = NULL}, "hypotenuse of right triangle within accuracy c"}, {"ilog", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_ilog}, "integral log of a to integral base b"}, - {"ilogn", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_ilog}, - "same is ilog"}, {"ilog10", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ilog10}, "integral log of a number base 10"}, {"ilog2", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ilog2}, "integral log of a number base 2"}, + {"ilogn", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_ilog}, + "same is ilog"}, {"im", 1, 1, 0, OP_IM, {.null = NULL}, {.null = NULL}, "imaginary part of complex number"}, {"indices", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_indices}, @@ -11062,22 +11238,32 @@ STATIC CONST struct builtin builtins[] = { "multiplicative inverse of value"}, {"iroot", 2, 2, 0, OP_NOP, {.numfunc_2 = qiroot}, {.null = NULL}, "integer b'th root of a"}, + {"isalnum", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isalnum}, + "whether character is alpha-numeric"}, + {"isalpha", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isalpha}, + "whether character is alphabetic"}, {"isassoc", 1, 1, 0, OP_ISASSOC, {.null = NULL}, {.null = NULL}, "whether a value is an association"}, {"isatty", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isatty}, "whether a file is a tty"}, {"isblk", 1, 1, 0, OP_ISBLK, {.null = NULL}, {.null = NULL}, "whether a value is a block"}, + {"iscntrl", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_iscntrl}, + "whether character is a control character"}, {"isconfig", 1, 1, 0, OP_ISCONFIG, {.null = NULL}, {.null = NULL}, "whether a value is a config state"}, {"isdefined", 1, 1, 0, OP_ISDEFINED, {.null = NULL}, {.null = NULL}, "whether a string names a function"}, + {"isdigit", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isdigit}, + "whether character is a digit"}, {"iserror", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_iserror}, "where a value is an error"}, {"iseven", 1, 1, 0, OP_ISEVEN, {.null = NULL}, {.null = NULL}, "whether a value is an even integer"}, {"isfile", 1, 1, 0, OP_ISFILE, {.null = NULL}, {.null = NULL}, "whether a value is a file"}, + {"isgraph", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isgraph}, + "whether character is a graphical character"}, {"ishash", 1, 1, 0, OP_ISHASH, {.null = NULL}, {.null = NULL}, "whether a value is a hash state"}, {"isident", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isident}, @@ -11086,6 +11272,8 @@ STATIC CONST struct builtin builtins[] = { "whether a value is an integer"}, {"islist", 1, 1, 0, OP_ISLIST, {.null = NULL}, {.null = NULL}, "whether a value is a list"}, + {"islower", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_islower}, + "whether character is lower case"}, {"ismat", 1, 1, 0, OP_ISMAT, {.null = NULL}, {.null = NULL}, "whether a value is a matrix"}, {"ismult", 2, 2, 0, OP_NOP, {.numfunc_2 = f_ismult}, {.null = NULL}, @@ -11098,14 +11286,18 @@ STATIC CONST struct builtin builtins[] = { "whether a value is an object"}, {"isobjtype", 1, 1, 0, OP_ISOBJTYPE, {.null = NULL}, {.null = NULL}, "whether a string names an object type"}, - {"isodd", 1, 1, 0, OP_ISODD, {.null = NULL}, {.null = NULL}, - "whether a value is an odd integer"}, {"isoctet", 1, 1, 0, OP_ISOCTET, {.null = NULL}, {.null = NULL}, "whether a value is an octet"}, + {"isodd", 1, 1, 0, OP_ISODD, {.null = NULL}, {.null = NULL}, + "whether a value is an odd integer"}, {"isprime", 1, 2, 0, OP_NOP, {.numfunc_cnt = f_isprime}, {.null = NULL}, "whether a is a small prime, return b if error"}, + {"isprint", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isprint}, + "whether character is printable"}, {"isptr", 1, 1, 0, OP_ISPTR, {.null = NULL}, {.null = NULL}, "whether a value is a pointer"}, + {"ispunct", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ispunct}, + "whether character is a punctuation"}, {"isqrt", 1, 1, 0, OP_NOP, {.numfunc_1 = qisqrt}, {.null = NULL}, "integer part of square root"}, {"isrand", 1, 1, 0, OP_ISRAND, {.null = NULL}, {.null = NULL}, @@ -11116,14 +11308,20 @@ STATIC CONST struct builtin builtins[] = { "whether a value is a real number"}, {"isrel", 2, 2, 0, OP_NOP, {.numfunc_2 = f_isrel}, {.null = NULL}, "whether two numbers are relatively prime"}, - {"isstr", 1, 1, 0, OP_ISSTR, {.null = NULL}, {.null = NULL}, - "whether a value is a string"}, {"issimple", 1, 1, 0, OP_ISSIMPLE, {.null = NULL}, {.null = NULL}, "whether value is a simple type"}, + {"isspace", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isspace}, + "whether character is a space character"}, {"issq", 1, 1, 0, OP_NOP, {.numfunc_1 = f_issquare}, {.null = NULL}, "whether or not number is a square"}, + {"isstr", 1, 1, 0, OP_ISSTR, {.null = NULL}, {.null = NULL}, + "whether a value is a string"}, {"istype", 2, 2, 0, OP_ISTYPE, {.null = NULL}, {.null = NULL}, "whether the type of a is same as the type of b"}, + {"isupper", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isupper}, + "whether character is upper case"}, + {"isxdigit", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isxdigit}, + "whether character is a hexadecimal digit"}, {"jacobi", 2, 2, 0, OP_NOP, {.numfunc_2 = qjacobi}, {.null = NULL}, "-1 = > a is not quadratic residue mod b\n" "\t\t\t1 = > b is composite, or a is quad residue of b"}, @@ -11203,37 +11401,11 @@ STATIC CONST struct builtin builtins[] = { "numerator of fraction"}, {"ord", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ord}, "integer corresponding to character value"}, - {"isupper", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isupper}, - "whether character is upper case"}, - {"islower", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_islower}, - "whether character is lower case"}, - {"isalnum", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isalnum}, - "whether character is alpha-numeric"}, - {"isalpha", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isalpha}, - "whether character is alphabetic"}, - {"iscntrl", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_iscntrl}, - "whether character is a control character"}, - {"isdigit", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isdigit}, - "whether character is a digit"}, - {"isgraph", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isgraph}, - "whether character is a graphical character"}, - {"isprint", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isprint}, - "whether character is printable"}, - {"ispunct", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_ispunct}, - "whether character is a punctuation"}, - {"isspace", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isspace}, - "whether character is a space character"}, - {"isxdigit", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_isxdigit}, - "whether character is a hexadecimal digit"}, {"param", 1, 1, 0, OP_ARGVALUE, {.null = NULL}, {.null = NULL}, "value of parameter n (or parameter count if n\n" "\t\t\tis zero)"}, {"perm", 2, 2, 0, OP_NOP, {.numfunc_2 = qperm}, {.null = NULL}, "permutation number a!/(a-b)!"}, - {"prevcand", 1, 5, 0, OP_NOP, {.numfunc_cnt = f_prevcand}, {.null = NULL}, - "largest value = = d mod e < a, ptest(a,b,c) true"}, - {"prevprime", 1, 2, 0, OP_NOP, {.numfunc_cnt = f_pprime}, {.null = NULL}, - "return previous small prime, return b if err"}, {"pfact", 1, 1, 0, OP_NOP, {.numfunc_1 = qpfact}, {.null = NULL}, "product of primes up till number"}, {"pi", 0, 1, FE, OP_NOP, {.numfunc_1 = qpi}, {.null = NULL}, @@ -11255,14 +11427,18 @@ STATIC CONST struct builtin builtins[] = { "number of bits in a that match b (or 1)"}, {"power", 2, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_power}, "value a raised to the power b within accuracy c"}, - {"protect", 1, 3, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_protect}, - "read or set protection level for variable"}, - {"ptest", 1, 3, 0, OP_NOP, {.numfunc_cnt = f_primetest}, {.null = NULL}, - "probabilistic primality test"}, + {"prevcand", 1, 5, 0, OP_NOP, {.numfunc_cnt = f_prevcand}, {.null = NULL}, + "largest value = = d mod e < a, ptest(a,b,c) true"}, + {"prevprime", 1, 2, 0, OP_NOP, {.numfunc_cnt = f_pprime}, {.null = NULL}, + "return previous small prime, return b if err"}, {"printf", 1, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_printf}, "print formatted output to stdout"}, {"prompt", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_prompt}, "prompt for input line using value a"}, + {"protect", 1, 3, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_protect}, + "read or set protection level for variable"}, + {"ptest", 1, 3, 0, OP_NOP, {.numfunc_cnt = f_primetest}, {.null = NULL}, + "probabilistic primality test"}, {"push", 1, IN, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_listpush}, "push values onto front of list"}, {"putenv", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_putenv}, @@ -11368,26 +11544,22 @@ STATIC CONST struct builtin builtins[] = { "assign value to stoponerror flag"}, {"str", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_str}, "simple value converted to string"}, - {"strtoupper", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_strtoupper}, - "Make string upper case"}, - {"strtolower", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_strtolower}, - "Make string lower case"}, + {"strcasecmp", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_strcasecmp}, + "compare two strings case independent"}, {"strcat", 1,IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_strcat}, "concatenate strings together"}, {"strcmp", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_strcmp}, "compare two strings"}, - {"strcasecmp", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_strcasecmp}, - "compare two strings case independent"}, {"strcpy", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_strcpy}, "copy string to string"}, {"strerror", 0, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_strerror}, "string describing error type"}, {"strlen", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_strlen}, "length of string"}, - {"strncmp", 3, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_3 = f_strncmp}, - "compare strings a, b to c characters"}, {"strncasecmp", 3, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_3 = f_strncasecmp}, "compare strings a, b to c characters case independent"}, + {"strncmp", 3, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_3 = f_strncmp}, + "compare strings a, b to c characters"}, {"strncpy", 3, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_3 = f_strncpy}, "copy up to c characters from string to string"}, {"strpos", 2, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_2 = f_strpos}, @@ -11398,6 +11570,10 @@ STATIC CONST struct builtin builtins[] = { "scan a string for assignments to one or more variables"}, {"strscanf", 2, IN, FA, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_strscanf}, "formatted scan of string for assignments to variables"}, + {"strtolower", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_strtolower}, + "Make string lower case"}, + {"strtoupper", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_strtoupper}, + "Make string upper case"}, {"substr", 3, 3, 0, OP_NOP, {.null = NULL}, {.valfunc_3 = f_substr}, "substring of a from position b for c chars"}, {"sum", 0, IN, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_sum}, diff --git a/help/Makefile b/help/Makefile index 9d0f913..74cafa8 100644 --- a/help/Makefile +++ b/help/Makefile @@ -199,37 +199,38 @@ BLT_HELP_FILES= ${BLT_HELP_FILES_3} ${BLT_HELP_FILES_5} \ # # to keep this list in nice sorted order. # -DETAIL_HELP= abs access acos acosh acot acoth acsc acsch address agd \ - append appr arg argv arrow asec asech asin asinh assign atan atan2 \ - atanh avg base base2 bernoulli bit blk blkcpy blkfree blocks bround \ - btrunc calc_tty calclevel calcpath catalan ceil cfappr cfsim char \ - cmdbuf cmp comb conj cos cosh cot coth count coversin cp csc csch \ - ctime d2dm d2dms d2g d2r delete den dereference det digit digits \ - display dms2d dp epsilon errcount errmax errno error estr euler eval \ - exp fact factor fclose fcnt feof ferror fflush fgetc fgetfield \ - fgetfile fgetline fgets fgetstr fib files floor fopen forall fpathopen \ - fprintf fputc fputs fputstr frac free freebernoulli freeeuler \ - freeglobals freeredc freestatics frem freopen fscan fscanf fseek fsize \ - ftell g2d g2gm g2gms g2r gcd gcdrem gd getenv gms2g h2hm h2hms hash \ - head highbit hmean hms2h hnrmod hypot ilog ilog10 ilog2 im indices \ - inputlevel insert int inverse iroot isalnum isalpha isassoc isatty \ - isblk iscntrl isconfig isdefined isdigit iserror iseven isfile isgraph \ - ishash isident isint islist islower ismat ismult isnull isnum isobj \ - isobjtype isodd isprime isprint isptr ispunct isqrt isrand israndom \ - isreal isrel issimple isspace issq isstr istype isupper isxdigit \ - jacobi join lcm lcmfact lfactor ln log log2 logn lowbit ltol makelist \ - matdim matfill matmax matmin matsum mattrace mattrans max memsize meq \ - min minv mmin mne mod modify name near newerror nextcand nextprime \ - norm null num oldvalue ord param perm pfact pi pix places pmod polar \ - poly pop popcnt pound power prevcand prevprime printf prompt protect \ - ptest push putenv quo quomod r2d r2g rand randbit random randombit \ - randperm rcin rcmul rcout rcpow rcsq re remove reverse rewind rm root \ - round rsearch runtime saveval scale scan scanf search sec sech seed \ - segment select sgn sha1 sin sinh size sizeof sleep sort sqrt srand \ - srandom ssq stoponerror str strcasecmp strcat strcmp strcpy strerror \ - strlen strncasecmp strncmp strncpy strpos strprintf strscan strscanf \ - strtolower strtoupper substr sum swap system systime tail tan tanh \ - test time trunc usertime versin version xor +DETAIL_HELP= abs access acos acosh acot acoth acoversin acsc acsch \ + address agd append appr arg argv arrow asec asech asin asinh assign \ + atan atan2 atanh aversin avg base base2 bernoulli bit blk blkcpy \ + blkfree blocks bround btrunc calc_tty calclevel calcpath catalan ceil \ + cfappr cfsim char cmdbuf cmp comb conj cos cosh cot coth count \ + coversin cp csc csch ctime d2dm d2dms d2g d2r delete den dereference \ + det digit digits display dms2d dp epsilon errcount errmax errno error \ + estr euler eval exp fact factor fclose fcnt feof ferror fflush fgetc \ + fgetfield fgetfile fgetline fgets fgetstr fib files floor fopen forall \ + fpathopen fprintf fputc fputs fputstr frac free freebernoulli \ + freeeuler freeglobals freeredc freestatics frem freopen fscan fscanf \ + fseek fsize ftell g2d g2gm g2gms g2r gcd gcdrem gd getenv gms2g h2hm \ + h2hms hash head highbit hmean hms2h hnrmod hypot ilog ilog10 ilog2 im \ + indices inputlevel insert int inverse iroot isalnum isalpha isassoc \ + isatty isblk iscntrl isconfig isdefined isdigit iserror iseven isfile \ + isgraph ishash isident isint islist islower ismat ismult isnull isnum \ + isobj isobjtype isodd isprime isprint isptr ispunct isqrt isrand \ + israndom isreal isrel issimple isspace issq isstr istype isupper \ + isxdigit jacobi join lcm lcmfact lfactor ln log log2 logn lowbit ltol \ + makelist matdim matfill matmax matmin matsum mattrace mattrans max \ + memsize meq min minv mmin mne mod modify name near newerror nextcand \ + nextprime norm null num oldvalue ord param perm pfact pi pix places \ + pmod polar poly pop popcnt pound power prevcand prevprime printf \ + prompt protect ptest push putenv quo quomod r2d r2g rand randbit \ + random randombit randperm rcin rcmul rcout rcpow rcsq re remove \ + reverse rewind rm root round rsearch runtime saveval scale scan scanf \ + search sec sech seed segment select sgn sha1 sin sinh size sizeof \ + sleep sort sqrt srand srandom ssq stoponerror str strcasecmp strcat \ + strcmp strcpy strerror strlen strncasecmp strncmp strncpy strpos \ + strprintf strscan strscanf strtolower strtoupper substr sum swap \ + system systime tail tan tanh test time trunc usertime versin version \ + xor # This list is of files that are clones of DETAIL_HELP files. They are # built from DETAIL_HELP files. diff --git a/help/acos b/help/acos index 5d45833..376de6b 100644 --- a/help/acos +++ b/help/acos @@ -5,13 +5,13 @@ SYNOPSIS acos(x [,eps]) TYPES - x real, -1 <= x <= 1 + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the acos of x to a multiple of eps with error less in + Returns the inverse cosine of x to a multiple of eps with error less in absolute value than .75 * eps. v = acos(x) is the number in [0, pi] for which cos(v) = x. @@ -20,14 +20,25 @@ EXAMPLE ; print acos(.5, 1e-5), acos(.5, 1e-10), acos(.5, 1e-15), acos(.5, 1e-20) 1.0472 1.0471975512 1.047197551196598 1.04719755119659774615 + ; print acos(5), acos(5i) + 2.29243166956117768776i 1.57079632679489661923-2.31243834127275262025i + + ; print acos(5+5i) + 0.79039774680951249644-2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qacos(NUMBER *x, NUMBER *eps) + COMPLEX *c_acos(COMPLEX *c, NUMBER *epsilon) SEE ALSO - asin, atan, asec, acsc, acot, epsilon + sin, cos, tan, cot, sec, csc + asin, atan, acot, asec, acsc + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2023 Landon Curt Noll ## diff --git a/help/acot b/help/acot index a8d7c10..17aa53a 100644 --- a/help/acot +++ b/help/acot @@ -5,29 +5,38 @@ SYNOPSIS acot(x [,eps]) TYPES - x real + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the acot of x to a multiple of eps with error less in + Returns the inverse cotangent of x to a multiple of eps with error less in absolute value than .75 * eps. - v = acot(x) is the number in (0, pi) for which cot(v) = x. - EXAMPLE ; print acot(2, 1e-5), acot(2, 1e-10), acot(2, 1e-15), acot(2, 1e-20) 0.46365 0.463647609 0.463647609000806 0.46364760900080611621 + ; print acot(5), acot(5i) + 0.19739555984988075837 -0.20273255405408219099i + + ; print acos(5+5i) + 0.79039774680951249644-2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qacot(NUMBER *x, NUMBER *eps) + COMPLEX *c_acot(COMPLEX *c, NUMBER *epsilon) SEE ALSO - asin, acos, atan, asec, acsc, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, atan, asec, acsc + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/acoversin b/help/acoversin new file mode 100644 index 0000000..72643a6 --- /dev/null +++ b/help/acoversin @@ -0,0 +1,63 @@ +NAME + acoversin - inverse coversed trigonometric sine + +SYNOPSIS + acoversin(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return number + +DESCRIPTION + Calculate the inverse coversed sine of x to a multiple of eps with error less in + absolute value than .75 * eps. + + The coversed sine function is sometimes called covers, or acosiv, or acvs, + may be defined as: + + acoversin(x) = asin(1 - x) + +EXAMPLE + ; print acoversin(.5, 1e-5), acoversin(.5, 1e-10), acoversin(.5, 1e-15), acoversin(.5, 1e-20) + 0.5236 0.5235987756 0.523598775598299 0.52359877559829887308 + + ; print acoversin(1), acoversin(-5), acoversin(2 + 3i) + 0 1.40341337183925787843-2.49215996813383545614i -0.30760364953071124992-1.86416154415788242834i + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qacoversin(NUMBER *x, NUMBER *eps) + COMPLEX *c_acoversin(COMPLEX *x, NUMBER *eps) + +SEE ALSO + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc + versin, coversin + aversin + epsilon + +## Copyright (C) 2023 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 +## as published by the Free Software Foundation. +## +## Calc is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +## Public License for more details. +## +## A copy of version 2.1 of the GNU Lesser General Public License is +## distributed with calc under the filename COPYING-LGPL. You should have +## received a copy with calc; if not, write to Free Software Foundation, Inc. +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## Under source code control: 2023/08/31 23:07:08 +## File existed as early as: 2023 +## +## chongo /\oo/\ http://www.isthe.com/chongo/ +## Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ diff --git a/help/acsc b/help/acsc index b47a6f6..5537b46 100644 --- a/help/acsc +++ b/help/acsc @@ -5,29 +5,38 @@ SYNOPSIS acsc(x [,eps]) TYPES - x real, with absolute value >= 1 + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the acsc of x to a multiple of eps with error less in + Returns the inverse cosecant of x to a multiple of eps with error less in absolute value than .75 * eps. - v = acsc(x) is the number in [-pi/2, pi/2] for which csc(v) = x. - EXAMPLE ; print acsc(2, 1e-5), acsc(2, 1e-10), acsc(2, 1e-15), acsc(2, 1e-20) 0.5236 0.5235987756 0.523598775598299 0.52359877559829887308 + ; print acsc(5), acsc(5i) + 0.20135792079033079145 -0.19869011034924140648i + + ; print acos(5+5i) + 0.79039774680951249644-2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qacsc(NUMBER *x, NUMBER *eps) + COMPLEX *c_acsc(COMPLEX *c, NUMBER *epsilon) SEE ALSO - asin, acos, atan, asec, acot, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, asec + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/asec b/help/asec index cc6c797..5e9915a 100644 --- a/help/asec +++ b/help/asec @@ -5,29 +5,38 @@ SYNOPSIS asec(x [,eps]) TYPES - x real, with absolute value >= 1 + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the asec of x to a multiple of eps with error less in + Returns the inverse secant of x to a multiple of eps with error less in absolute value than .75 * eps. - v = asec(x) is the number in [0, pi] for which sec(v) = x. - EXAMPLE ; print asec(2, 1e-5), asec(2, 1e-10), asec(2, 1e-15), asec(2, 1e-20) 1.0472 1.0471975512 1.047197551196598 1.04719755119659774615 + ; print asec(5), asec(5i) + 1.36943840600456582778 1.57079632679489661923+0.19869011034924140647i + + ; print acos(5+5i) + 0.79039774680951249644-2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qasec(NUMBER *x, NUMBER *eps) + COMPLEX *c_asec(COMPLEX *c, NUMBER *epsilon) SEE ALSO - asin, acos, atan, acsc, acot, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, acsc + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/asin b/help/asin index a08b604..24b64fe 100644 --- a/help/asin +++ b/help/asin @@ -5,13 +5,13 @@ SYNOPSIS asin(x [,eps]) TYPES - x real, -1 <= x <= 1 + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the asin of x to a multiple of eps with error less in + Returns the inverse sine of x to a multiple of eps with error less in absolute value than .75 * eps. v = asin(x) is the number in [-pi/2, pi/2] for which sin(v) = x. @@ -20,14 +20,25 @@ EXAMPLE ; print asin(.5, 1e-5), asin(.5, 1e-10), asin(.5, 1e-15), asin(.5, 1e-20) 0.5236 0.5235987756 0.523598775598299 0.52359877559829887308 + ; print asin(5), asin(5i) + 1.57079632679489661923-2.2924316695611776878i 2.31243834127275262025i + + ; print asin(5+5i) + 0.78039857998538412279+2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qasin(NUMBER *q, NUMBER *epsilon) + COMPLEX *c_asin(COMPLEX *c, NUMBER *epsilon) SEE ALSO - acos, atan, asec, acsc, acot, epsilon + sin, cos, tan, cot, sec, csc + acos, atan, acot, asec, acsc + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/atan b/help/atan index 70fc6c1..e83f0a1 100644 --- a/help/atan +++ b/help/atan @@ -5,29 +5,38 @@ SYNOPSIS atan(x [,eps]) TYPES - x real + x number (real or complex) eps 0 < real < 1, defaults to epsilon() return real DESCRIPTION - Returns the atan of x to a multiple of eps with error less in + Returns the inverse tangent of x to a multiple of eps with error less in absolute value than .75 * eps. - v = atan(x) is the number in (-pi/2, pi/2) for which tan(v) = x. - EXAMPLE ; print atan(2, 1e-5), atan(2, 1e-10), atan(2, 1e-15), atan(2, 1e-20) 1.10715 1.1071487178 1.107148717794091 1.10714871779409050302 + ; print atan(5), atan(5i) + 1.37340076694501586086 1.57079632679489661923+0.20273255405408219099i + + ; print acos(5+5i) + 0.79039774680951249644-2.64919617780647114961i + LIMITS 0 < eps < 1 LINK LIBRARY NUMBER *qatan(NUMBER *x, NUMBER *eps) + COMPLEX *c_atan(COMPLEX *c, NUMBER *epsilon) SEE ALSO - asin, acos, asec, acsc, acot, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, acot, asec, acsc + versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2023 Landon Curt Noll ## diff --git a/help/aversin b/help/aversin new file mode 100644 index 0000000..25ac632 --- /dev/null +++ b/help/aversin @@ -0,0 +1,64 @@ +NAME + aversin - inverse versed trigonometric sine + +SYNOPSIS + aversin(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return real + +DESCRIPTION + Returns the inverse versed sine of x to a multiple of eps with error less in + absolute value than .75 * eps. + + The inverse versed sine function is sometimes called avers, sometimes called aver, + may be defined as: + + aversin(x) = acos(1 - x) + +EXAMPLE + ; print aversin(.5, 1e-5), aversin(.5, 1e-10), aversin(.5, 1e-15), aversin(.5, 1e-20) + 1.0472 1.0471975512 1.047197551196598 1.04719755119659774615 + + ; print aversin(0), aversin(-5), aversin(2 + 3i) + 0 0.16738295495563874081+2.49215996813383545614i 1.87839997632560786916+1.86416154415788242831i + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qaversin_or_NULL(NUMBER *q, NUMBER *epsilon); + NUMBER *qaversin(NUMBER *q, NUMBER *epsilon); + COMPLEX *c_aversin(COMPLEX *c, NUMBER *epsilon); + +SEE ALSO + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc + versin, coversin + acoversin + epsilon + +## Copyright (C) 2023 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 +## as published by the Free Software Foundation. +## +## Calc is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +## Public License for more details. +## +## A copy of version 2.1 of the GNU Lesser General Public License is +## distributed with calc under the filename COPYING-LGPL. You should have +## received a copy with calc; if not, write to Free Software Foundation, Inc. +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## Under source code control: 2023/09/03 00:26:24 +## File existed as early as: 2023 +## +## chongo /\oo/\ http://www.isthe.com/chongo/ +## Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ diff --git a/help/cos b/help/cos index 34dc27f..09b24a4 100644 --- a/help/cos +++ b/help/cos @@ -1,5 +1,5 @@ NAME - cos - cosine + cos - trigonometric cosine SYNOPSIS cos(x [,eps]) @@ -33,8 +33,11 @@ LINK LIBRARY COMPLEX *c_cos(COMPLEX *x, NUMBER *eps) SEE ALSO - sin, tan, sec, csc, cot, epsilon + sin, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/cot b/help/cot index 2863916..c323652 100644 --- a/help/cot +++ b/help/cot @@ -26,8 +26,11 @@ LINK LIBRARY COMPLEX *c_acot(COMPLEX *c, NUMBER *eps); SEE ALSO - sin, cos, tan, sec, csc, epsilon + sin, cos, tan, sec, csc + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/coversin b/help/coversin index 7870d3e..5d10830 100644 --- a/help/coversin +++ b/help/coversin @@ -1,5 +1,5 @@ NAME - coversin - coversed sine + coversin - coversed trigonometric sine SYNOPSIS coversin(x [,eps]) @@ -11,7 +11,7 @@ TYPES return number DESCRIPTION - Calculate the versed cosine of x to a multiple of eps with error less in + Calculate the coversed sine of x to a multiple of eps with error less in absolute value than .75 * eps. The coversed sine function is sometimes called covers, or cosiv, or cvs, @@ -41,8 +41,11 @@ LINK LIBRARY COMPLEX *c_coversin(COMPLEX *x, NUMBER *eps) SEE ALSO - sin, cos, tan, sec, csc, cot, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc versin + aversin. acoversin + epsilon ## Copyright (C) 2023 Landon Curt Noll ## diff --git a/help/csc b/help/csc index f277ac0..3e15fb4 100644 --- a/help/csc +++ b/help/csc @@ -1,5 +1,5 @@ NAME - csc - trigonometric cosecant function + csc - trigonometric cosecant SYNOPSIS csc(x [,eps]) @@ -25,8 +25,11 @@ LINK LIBRARY NUMBER *qcsc(NUMBER *x, NUMBER *eps) SEE ALSO - sin, cos, tan, sec, cot, epsilon + sin, cos, tan, cot, sec + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2023 Landon Curt Noll ## diff --git a/help/sec b/help/sec index afdc317..07ce615 100644 --- a/help/sec +++ b/help/sec @@ -1,5 +1,5 @@ NAME - sec - trigonometric secant function + sec - trigonometric secant SYNOPSIS sec(x [,eps]) @@ -26,8 +26,11 @@ LINK LIBRARY NUMBER *qsec(NUMBER *x, NUMBER *eps) SEE ALSO - sin, cos, tan, csc, cot, epsilon + sin, cos, tan, cot, csc + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2023 Landon Curt Noll ## diff --git a/help/sin b/help/sin index 8272bdb..1a71755 100644 --- a/help/sin +++ b/help/sin @@ -33,8 +33,11 @@ LINK LIBRARY COMPLEX *c_sin(COMPLEX *x, NUMBER *eps) SEE ALSO - cos, tan, sec, csc, cot, epsilon + cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/tan b/help/tan index ba7dd9e..5310a1f 100644 --- a/help/tan +++ b/help/tan @@ -27,8 +27,11 @@ LINK LIBRARY COMPLEX *c_atan(COMPLEX *c, NUMBER *eps); SEE ALSO - sin, cos, sec, csc, cot, epsilon + sin, cos, cot, sec, csc + asin, acos, atan, acot, asec, acsc versin, coversin + aversin. acoversin + epsilon ## Copyright (C) 1999,2023 Landon Curt Noll ## diff --git a/help/versin b/help/versin index e6410e2..388cdda 100644 --- a/help/versin +++ b/help/versin @@ -1,5 +1,5 @@ NAME - versin - versed sine + versin - versed trigonometric sine SYNOPSIS versin(x [,eps]) @@ -41,8 +41,11 @@ LINK LIBRARY COMPLEX *c_versin(COMPLEX *x, NUMBER *eps) SEE ALSO - sin, cos, tan, sec, csc, cot, epsilon + sin, cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc coversin + aversin. acoversin + epsilon ## Copyright (C) 2023 Landon Curt Noll ## diff --git a/qmath.h b/qmath.h index d17a659..bf946ab 100644 --- a/qmath.h +++ b/qmath.h @@ -227,7 +227,11 @@ E_FUNC void qfreeeuler(void); * historical trig functions */ E_FUNC NUMBER *qversin(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaversin_or_NULL(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaversin(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qcoversin(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qacoversin_or_NULL(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qacoversin(NUMBER *q, NUMBER *epsilon); /* diff --git a/qtrans.c b/qtrans.c index 38d912e..8db8a02 100644 --- a/qtrans.c +++ b/qtrans.c @@ -421,6 +421,8 @@ qcsc(NUMBER *q, NUMBER *epsilon) qfree(csc); return res; } + + /* * Calculate the arcsine function. * The result is in the range -pi/2 to pi/2. @@ -437,14 +439,16 @@ qasin(NUMBER *q, NUMBER *epsilon) math_error("Zero epsilon value for asin"); not_reached(); } - if (qiszero(q)) + if (qiszero(q)) { return qlink(&_qzero_); + } ztmp = q->num; neg = ztmp.sign; ztmp.sign = 0; r = zrel(ztmp, q->den); - if (r > 0) + if (r > 0) { return NULL; + } if (r == 0) { epsilon1 = qscale(epsilon, 1L); qtmp2 = qpi(epsilon1); @@ -1981,8 +1985,6 @@ qacoth(NUMBER *q, NUMBER *epsilon) * * versin(x) = 1 - cos(x) * - * This calls qsincos() and discards the value of sin. - * * given: * q real value to pass to the trig function * epsilon error tolerance / precision for trig calculation @@ -1997,31 +1999,147 @@ qversin(NUMBER *q, NUMBER *epsilon) NUMBER *versin; long n; - if (qiszero(epsilon)) { - math_error("Zero epsilon value for %s", __func__); + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); not_reached(); } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate trig function value + */ n = -qilog2(epsilon); - if (qiszero(q) || n < 0) - return qlink(&_qzero_); qsincos(q, n + 2, &sin, &cos); qfree(sin); versin = qsub(&_qone_, cos); qfree(cos); + + /* + * round value to nearest epsilon + */ res = qmappr(versin, epsilon, 24); qfree(versin); + + /* + * return 1 - cos(x) + */ return res; } /* - * qversin - coversed sine for NUMBER values + * qaversin_or_NULL - inverse versed sine for NUMBER values * * This uses the formula: * - * coversin(x) = 1 - sin(x) + * aversin(x) = acos(1 - x) * - * This calls qsincos() and discards the value of cos. + * given: + * q real value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * != NULL ==> real value result of trig function on q with error epsilon, + * NULL ==> trig function value cannot be expressed as a NUMBER + * + * NOTE: If this function returns NULL, consider calling the equivalent + * COMPLEX function from comfunc.c. See the help file for the + * related builtin for details. + */ +NUMBER * +qaversin_or_NULL(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *x; /* argument to inverse trig function */ + + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate inverse trig function value + */ + x = qsub(&_qone_, q); + res = qacos(x, epsilon); + qfree(x); + if (res == NULL) { + return NULL; + } + + /* + * return acos(1 - x) + */ + return res; +} + + +/* + * qaversin - inverse versed sine for NUMBER values + * + * This uses the formula: + * + * aversin(x) = acos(1 - x) + * + * given: + * q real value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * real value result of trig function on q with error epsilon + */ +NUMBER * +qaversin(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate inverse trig function value + */ + res = qaversin_or_NULL(q, epsilon); + if (res == NULL) { + math_error("cannot compute inverse cos for aversin"); + not_reached(); + } + + /* + * return acos(1 - x) + */ + return res; +} + + +/* + * qcoversin - coversed sine for NUMBER values + * + * This uses the formula: + * + * coversin((x) = 1 - sin(x) * * given: * q real value to pass to the trig function @@ -2037,10 +2155,21 @@ qcoversin(NUMBER *q, NUMBER *epsilon) NUMBER *coversin; long n; - if (qiszero(epsilon)) { - math_error("Zero epsilon value for %s", __func__); + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); not_reached(); } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate trig function value + */ n = -qilog2(epsilon); if (qiszero(q) || n < 0) return qlink(&_qzero_); @@ -2048,7 +2177,119 @@ qcoversin(NUMBER *q, NUMBER *epsilon) qfree(cos); coversin = qsub(&_qone_, sin); qfree(sin); + + /* + * round value to nearest epsilon + */ res = qmappr(coversin, epsilon, 24); qfree(coversin); + + /* + * return 1 - sin(x) + */ + return res; +} + + +/* + * qacoversin_or_NULL - inverse coversed sine for NUMBER values + * + * This uses the formula: + * + * acoversin(x) = asin(1 - x) + * + * given: + * q real value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * real value result of trig function on q with error epsilon + * + * returns: + * != NULL ==> real value result of trig function on q with error epsilon, + * NULL ==> trig function value cannot be expressed as a NUMBER + * + * NOTE: If this function returns NULL, consider calling the equivalent + * COMPLEX function from comfunc.c. See the help file for the + * related builtin for details. + */ +NUMBER * +qacoversin_or_NULL(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *x; /* argument to inverse trig function */ + + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate inverse trig function value + */ + x = qsub(&_qone_, q); + res = qasin(x, epsilon); + qfree(x); + if (res == NULL) { + return NULL; + } + + /* + * return asin(1 - x) + */ + return res; +} + + +/* + * qacoversin - inverse coversed sine for NUMBER values + * + * This uses the formula: + * + * acoversin(x) = asin(1 - x) + * + * given: + * q real value to pass to the trig function + * epsilon error tolerance / precision for trig calculation + * + * returns: + * real value result of trig function on q with error epsilon + */ +NUMBER * +qacoversin(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + + /* + * firewall + */ + if (q == NULL) { + math_error("q is NULL for %s", __func__); + not_reached(); + } + if (check_epsilon(epsilon) == false) { + math_error("Invalid epsilon arg for %s", __func__); + not_reached(); + } + + /* + * calculate inverse trig function value + */ + res = qacoversin_or_NULL(q, epsilon); + if (res == NULL) { + math_error("cannot compute inverse sin for acoversin"); + not_reached(); + } + + /* + * return asin(1 - x) + */ return res; } diff --git a/trailblank b/trailblank new file mode 100755 index 0000000..f79310a --- /dev/null +++ b/trailblank @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# +# trailblank - find trailing blanks and other file format picky issues +# +# This tools is used by "make prep". +# +# If all is well, this tool prints nothing and does an exit 0. +# If a problem is found, this tool prints messages and does a non-0 exit. +# +# Copyright (C) 2017,2018,2021-2023 Landon Curt Noll +# +# Calc is open software; you can redistribute it and/or modify it under +# the terms of version 2.1 of the GNU Lesser General Public License +# as published by the Free Software Foundation. +# +# Calc is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# A copy of version 2.1 of the GNU Lesser General Public License is +# distributed with calc under the filename COPYING-LGPL. You should have +# received a copy with calc; if not, write to Free Software Foundation, Inc. +# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +# +# Under source code control: 2017/05/22 03:28:20 +# File existed as early as: 2017 +# +# chongo /\oo/\ http://www.isthe.com/chongo/ +# Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ + +# exit code +# +export EXIT_CODE=0 + +# Look for leading whiitespace before a tab +# +# We exclude binary files, RCS source code history, intermediate +# compiled files, patch droppings and compiled binary libraries. +# +# Last, we have two files that have long lines that, for now, +# we cannot be as picky about without significant work. +# +LEADING_SPACES_BEFORE_TAB=$( + find . \( -path './NOTES' -o -path './calc' -o -path './ver_calc' -o \ + -name '*.o' -o -name '*.a' -o -name '*ptch*' -o -name 'core*' -o \ + -name '*.orig' -o -name '*.rej' -o -name '*.bak' -o \ + -name '*.ptch' -o -name 'core.*' -o \ + -name '*.so*' -o -name 'calc-static' -o -name 'libcalc.*' -o \ + -name 'sample_many' -o -name 'sample_rand' -o \ + -path './help/funclist' -o -path './have_stdvs' -o \ + -path './endian' -o -path './no_implicit' -o -name 'chk_c' -o \ + -path './longbits' -o -name '.*.swp' -o -name 'conf.h' -o \ + -path './help/errorcodes.sed' -o -path './cal/set8700.line' -o \ + -name '.git' -o -path './custom/libcustcalc*' -o -path './libcustcalc*' -o \ + -name 'sample_many-static' -o -name 'sample_rand-static' -o \ + -name 'codeql-analysis.yml' -o -name tags -o -name debug.out \ + \) -prune -o -type f -print0 | \ + xargs -0 egrep -l '^ * * ' +) +if [[ -n $LEADING_SPACES_BEFORE_TAB ]]; then + echo + echo '# files with leading spaces before a tab' + echo "$LEADING_SPACES_BEFORE_TAB" | sed -e 's/^\.\///' + EXIT_CODE=1 +fi + +# Look for trailing whitespace +# +# We exclude binary files, RCS source code history, intermediate +# compiled files, patch droppings and compiled binary libraries. +# +# Last, we have two files that have long lines that, for now, +# we cannot be as picky about without significant work. +# +TRAILING_WHITESPACE=$( + find . \( -path './NOTES' -o -path './calc' -o -path './ver_calc' -o \ + -name '*.o' -o -name '*.a' -o -name '*ptch*' -o -name 'core*' -o \ + -name '*.orig' -o -name '*.rej' -o -name '*.bak' -o \ + -name '*.ptch' -o -name 'core.*' -o \ + -name '*.so*' -o -name 'calc-static' -o -name 'libcalc.*' -o \ + -name 'sample_many' -o -name 'sample_rand' -o \ + -path './help/funclist' -o -path './have_stdvs' -o \ + -path './endian' -o -path './no_implicit' -o -name 'chk_c' -o \ + -path './longbits' -o -name '.*.swp' -o -name 'conf.h' -o \ + -path './help/errorcodes.sed' -o -path './cal/set8700.line' -o \ + -name '.git' -o -path './custom/libcustcalc*' -o -path './libcustcalc*' -o \ + -name 'sample_many-static' -o -name 'sample_rand-static' -o \ + -name 'codeql-analysis.yml' -o -name tags -o -name debug.out \ + \) -prune -o -type f -print0 | \ + xargs -0 egrep -l '[ ]$' +) +if [[ -n $TRAILING_WHITESPACE ]]; then + echo + echo '# files with trailing whitespace' + echo "$TRAILING_WHITESPACE" | sed -e 's/^\.\///' + EXIT_CODE=2 +fi + +# Perform special picky tool phase 0 processing +# +# Some of these files must have long lines. Some of these files may not exist. +# +if [[ -x /usr/local/bin/picky ]]; then + PICKY_PHASE_0A=$(/usr/local/bin/picky -w -s -v ./help/errorcodes.sed ./cal/set8700.line \ + .gitignore README.md .lldbinit 2>&1) + status="$?" + if [[ $status -ne 0 ]]; then + echo + echo '# picky failed on one of the files with long lines' + echo "$PICKY_PHASE_0A" | sed -e 's/\.\///' + EXIT_CODE=3 + fi + if [[ -e conf.h ]]; then + PICKY_PHASE_0B=$(/usr/local/bin/picky -w -s -v conf.h 2>&1) + status="$?" + if [[ $status -ne 0 ]]; then + echo + echo '# picky failed on conf.h' + echo "$PICKY_PHASE_0B" | sed -e 's/\.\///' + EXIT_CODE=4 + fi + fi + if [[ -e calcerr.h ]]; then + PICKY_PHASE_0C=$(/usr/local/bin/picky -w -s -v calcerr.h 2>&1) + status="$?" + if [[ $status -ne 0 ]]; then + echo + echo '# picky failed on calcerr.h' + echo "$PICKY_PHASE_0C" | sed -e 's/\.\///' + EXIT_CODE=5 + fi + fi +else + echo "# $0: WARNING: /usr/local/bin/picky not found: skipping picky phase 0 checks!" 1>&2 + echo "#" 1>&2 +fi + +# Picky tool processing phase 1 +# +# We exclude binary files, source code history, intermediate +# compiled files, patch droppings and compiled binary libraries. +# +# Last, we have files that have long lines that, for now, +# we cannot be as picky about without significant work. +# +PICKY_PHASE_1=$( + find . \( -path './NOTES' -o -path './calc' -o -path './ver_calc' -o \ + -name '*.o' -o -name '*.a' -o -name '*ptch*' -o -name 'core*' -o \ + -name '*.orig' -o -name '*.rej' -o -name '*.bak' -o \ + -name '*.ptch' -o -name 'core.*' -o \ + -name '*.so*' -o -name 'calc-static' -o -name 'libcalc.*' -o \ + -name 'sample_many' -o -name 'sample_rand' -o \ + -path './help/funclist' -o -path './have_stdvs' -o \ + -path './endian' -o -path './no_implicit' -o -name 'chk_c' -o \ + -path './longbits' -o -name '.*.swp' -o -name 'conf.h' -o \ + -path './help/errorcodes.sed' -o -path './cal/set8700.line' -o \ + -name '.git' -o -path './custom/libcustcalc*' -o -path './libcustcalc*' -o \ + -name 'sample_many-static' -o -name 'sample_rand-static' -o \ + -name 'codeql-analysis.yml' -o -name tags -o -name debug.out \ + -o \ + -path './help/errorcodes.sed' -o -path './help/errorcodes.sed' -o \ + -name '.gitignore' -o -name 'README.md' -o -name '.lldbinit' \ + \) -prune -o -type f -print0 | \ + if [[ -x /usr/local/bin/picky ]]; then + xargs -0 /usr/local/bin/picky -s -v -w132 + else + echo "# $0: WARNING: /usr/local/bin/picky not found: skipping picky phase 1 check!" 1>&2 + echo "#" 1>&2 + echo "# $0: NOTICE: The picky tool used is from the following GitHub repo:" 1>&2 + echo "#" 1>&2 + echo "# https://github.com/lcn2/picky for the picky tool GitHub repo." 1>&2 + echo "#" 1>&2 + fi +) +if [[ -n $PICKY_PHASE_1 ]]; then + echo + echo '# files flagged by picky' + echo "$PICKY_PHASE_1" | sed -e 's/^picky: \.\///' -e 's/ / - /' + EXIT_CODE=6 +fi + +# look for backup Makefiles +# +BACKUP_MAKEILES=$( + find . -name Makefile.bak -print +) +if [[ -n $BACKUP_MAKEILES ]]; then + echo + echo "# You need execute the following to remove backup Makefiles:" + echo + echo "$BACKUP_MAKEILES" | while read file; do + echo "rm -f $file" + done + EXIT_CODE=7 +fi + +# All Done!!! -- Jessica Noll, Age 2 +# +exit "$EXIT_CODE" diff --git a/update_ver b/update_ver new file mode 100755 index 0000000..50b1407 --- /dev/null +++ b/update_ver @@ -0,0 +1,189 @@ +#!/bin/bash +# +# update_ver - update version numbers in Makefile.config +# +# This tools is used by "make prep". +# +# The original name for this tool was verupdate. +# +# Copyright (C) 2021-2023 Landon Curt Noll +# +# Calc is open software; you can redistribute it and/or modify it under +# the terms of version 2.1 of the GNU Lesser General Public License +# as published by the Free Software Foundation. +# +# Calc is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# A copy of version 2.1 of the GNU Lesser General Public License is +# distributed with calc under the filename COPYING-LGPL. You should have +# received a copy with calc; if not, write to Free Software Foundation, Inc. +# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +# +# Under source code control: 2021/12/12 15:32:43 +# File existed as early as: 2021 +# +# chongo /\oo/\ http://www.isthe.com/chongo/ +# Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ + +# setup +# +MK_SET1="Makefile.config" + +##################### +# utility functions # +##################### + +# firewall - must have primary Makefiles +# +check_primary() { + echo "check for primary Makefiles: $MK_SET1" + for i in $MK_SET1; do + if [[ ! -f $i ]]; then + echo "$0: FATAL: Missing critical: $i" 1>&2 + fi + if [[ ! -s $i ]]; then + echo "$0: FATAL: empty: $i" 1>&2 + fi + done + for i in $MK_SET1; do + if [[ ! -f $i ]]; then + echo "$0: FATAL: exit 1" + exit 1 + fi + if [[ ! -s $i ]]; then + echo "$0: FATAL: exit 2" + exit 2 + fi + done +} + +# firewall - bak files must not pre-exist +# +no_bak() { + for i in $MK_SET1; do + if [[ -f $i.bak ]]; then + echo "$0: FATAL: bak copy found: $i.bak" 1>&2 + echo "$0: FATAL: try: diff -u $i.bak $i" 1>&2 + echo "$0: FATAL: consider: rm -f $i.bak" 1>&2 + fi + done + for i in $MK_SET1; do + if [[ -f $i.bak ]]; then + echo "$0: FATAL: exit 5" + exit 5 + fi + done +} + +# firewall +# +check_primary +no_bak + +# generate the version +# +echo "make ver_calc >/dev/null 2>&1" +make ver_calc >/dev/null 2>&1 +status="$?" +if [[ $status -ne 0 ]]; then + echo "$0: FATAL: make ver_calc non-zero exit code: $status" 1>&2 + echo "$0: FATAL: exit 4" + exit 4 +fi +if [[ ! -x ver_calc ]]; then + echo "$0: FATAL: cannot find / did not make ver_calc executable" 1>&2 + echo "$0: FATAL: exit 5" + exit 5 +fi +CALC_VERSION=$(./ver_calc) +export CALC_VERSION +if [[ -z $CALC_VERSION ]]; then + echo "$0: FATAL: unable to determine calc version" 1>&2 + echo "$0: FATAL: exit 6" + exit 6 +fi +CALC_VER=$(./ver_calc -V) +export CALC_VER +if [[ -z $CALC_VER ]]; then + echo "$0: FATAL: unable to determine calc major version" 1>&2 + echo "$0: FATAL: exit 7" + exit 7 +fi + +# re-firewall +# +# Just in case the 'make ver_calc' causes some Makefile.config +# to be reformed, and thus a bak file was created. +# +check_primary +no_bak + +# modify version lines +# +echo "about to modify: $MK_SET1" +echo "changing version line to use VERSION= $CALC_VERSION" +echo "changing major version line to use VER= $CALC_VER" +perl -p -i -e \ + 's/^VERSION= .*/VERSION= '"$CALC_VERSION"'/; s/^VER= .*/VER= '"$CALC_VER"'/' \ + $MK_SET1 +status="$?" +if [[ $status -ne 0 ]]; then + echo "$0: FATAL: perl version change for non-zero exit code: $status" 1>&2 + echo "$0: FATAL: exit 8" + exit 8 +fi + +# print calc version +# +echo +export VERSION_STRING= +export VERSION_ERR= +for i in $MK_SET1; do + VERSION_STRING=$(egrep '^VERSION= [1-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' "$i") + if [[ -z $VERSION_STRING ]]; then + echo "$0: FATAL: cannot find VERSION= in $i" + VERSION_ERR="$i" + else + echo "$i: $VERSION_STRING" + fi +done +if [[ -n $VERSION_ERR ]]; then + echo "$0: FATAL: error in finding calc version string" + echo "$0: FATAL: exit 9" + exit 9 +fi + +# print calc major version +# +export VER_STRING= +export VER_ERR= +for i in $MK_SET1; do + VER_STRING=$(egrep '^VER= [1-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' "$i") + if [[ -z $VER_STRING ]]; then + echo "$0: FATAL: cannot find VER= in $i" + VER_ERR="$i" + else + echo "$i: $VER_STRING" + fi +done +if [[ -n $VER_ERR ]]; then + echo "$0: FATAL: error in finding calc major version string" + echo "$0: FATAL: exit 10" + exit 10 +fi + +# print other useful calc strings +# +echo +echo "calc $(./ver_calc) release" +echo +echo "Release v$(./ver_calc)" + +# All Done!!! -- Jessica Noll, Age 2 +# +echo +echo "VERSION in Makefile.config is up to date" +exit 0