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