diff --git a/CHANGES b/CHANGES index cd5f1d2..068fa9f 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,8 @@ The following are the changes from calc version 2.14.3.5 to date: aexcsc(x [,eps]) inverse exterior trigonometric cosecant crd(x [,eps]) trigonometric chord of a unit circle acrd(x [,eps]) inverse trigonometric chord of a unit circle + cas(x [,eps]) trigonometric cosine plus sine + cis(x [,eps]) Euler's formula As Msys2 is a fork of Cygwin, if the OSNAME is Msys, the Cygwin target will be used. Thanks to GitHub user @iahung2 for the diff --git a/cal/regress.cal b/cal/regress.cal index 72f5a43..18a7ecb 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -4182,6 +4182,52 @@ define test_trig() strcat(str(tnum++), ': round(acrd(2 + 3i, 1e-10), 10) == 1.0471975512+2.6339157938i')); + /* test cosine plus sine */ + vrfy(cas(0, 1e-10) == 1, + strcat(str(tnum++), ': cas(0, 1e-10) == 1')); + vrfy(round(cas(0.2, 1e-10), 10) == 1.1787359086, + strcat(str(tnum++), + ': round(cas(0.2, 1e-10), 10) == 1.1787359086')); + vrfy(round(cas(3/7, 1e-10), 10) == 1.3251322067, + strcat(str(tnum++), + ': round(cas(3/7, 1e-10), 10) == 1.3251322067')); + vrfy(round(cas(-31, 1e-10), 10) == 1.3187800031, + strcat(str(tnum++), + ': round(cas(-31, 1e-10), 10) == 1.3187800031')); + vrfy(cas(pi/2, 1e-10) == 1, + strcat(str(tnum++), ': cas(pi/2, 1e-10) == 1')); + vrfy(cas(pi, 1e-10) == -1, + strcat(str(tnum++), ': cas(pi, 1e-10) == -1')); + vrfy(cas(3*pi/2, 1e-10) == -1, + strcat(str(tnum++), ': cas(3*pi/2, 1e-10) == -1')); + vrfy(round(cas(1, 1e-10), 10) == 1.3817732907, + strcat(str(tnum++), + ': round(cas(1, 1e-10), 10) == 1.3817732907')); + vrfy(round(cas(2 + 3i, 1e-10), 10) == 4.9648734559-13.2781348538i, + strcat(str(tnum++), + ': round(cas(2 + 3i, 1e-10), 10) == 4.9648734559-13.2781348538i')); + + /* test Euler's formula */ + vrfy(cis(0, 1e-10) == 1, + strcat(str(tnum++), ': cis(0, 1e-10) == 1')); + vrfy(cis(pi/2, 1e-10) == 1i, + strcat(str(tnum++), ': cis(pi/2, 1e-10) == 1i')); + vrfy(round(cis(0.2, 1e-10), 10) == 0.9800665778+0.1986693308i, + strcat(str(tnum++), + ': round(cis(0.2, 1e-10), 10) == 0.9800665778+0.1986693308i')); + vrfy(round(cis(3/7, 1e-10), 10) == 0.9095603517+0.415571855i, + strcat(str(tnum++), + ': round(cis(3/7, 1e-10), 10) == 0.9095603517+0.415571855i')); + vrfy(round(cis(-31, 1e-10), 10) == 0.9147423578+0.4040376453i, + strcat(str(tnum++), + ': round(cis(-31, 1e-10), 10) == 0.9147423578+0.4040376453i')); + vrfy(round(cis(1, 1e-10), 10) == 0.5403023059+0.8414709848i, + strcat(str(tnum++), + ': round(cis(1, 1e-10), 10) == 0.5403023059+0.8414709848i')); + vrfy(round(cis(2 + 3i, 1e-10), 10) == -0.020718731+0.0452712532i, + strcat(str(tnum++), + ': round(cis(2 + 3i, 1e-10), 10) == -0.020718731+0.0452712532i')); + print strcat(str(tnum++), ': Ending test_trig'); } print '051: parsed test_trig()'; @@ -9879,9 +9925,11 @@ vrfy(verify_havercos(9513) == 0, '9513: verify_havercos(9513) == 0'); vrfy(verify_hacovercos(9514) == 0, '9514: verify_hacovercos(9514) == 0'); vrfy(verify_exsec(9515) == 0, '9515: verify_exsec(9515) == 0'); vrfy(verify_excsc(9516) == 0, '9516: verify_excsc(9516) == 0'); -vrfy(verify_crd(9517) == 0, '9516: verify_excsc(9517) == 0'); +vrfy(verify_crd(9517) == 0, '9517: verify_crd(9517) == 0'); +vrfy(verify_cas(9518) == 0, '9518: verify_cas(9518) == 0'); +vrfy(verify_cis(9519) == 0, '9519: verify_cis(9519) == 0'); -print '9518: Ending trigonometric identities test set'; +print '9520: Ending trigonometric identities test set'; /* @@ -10890,6 +10938,12 @@ vrfy_errsym(10596, 10596, "E_CRD_3"); vrfy_errsym(10597, 10597, "E_ACRD_1"); vrfy_errsym(10598, 10598, "E_ACRD_2"); vrfy_errsym(10599, 10599, "E_ACRD_3"); +vrfy_errsym(10600, 10600, "E_CAS_1"); +vrfy_errsym(10601, 10601, "E_CAS_2"); +vrfy_errsym(10602, 10602, "E_CAS_3"); +vrfy_errsym(10603, 10603, "E_CIS_1"); +vrfy_errsym(10604, 10604, "E_CIS_2"); +vrfy_errsym(10605, 10605, "E_CIS_3"); /* ************************************************************** */ /* NOTE: Reserve thru test 10998 for calc computation error codes */ diff --git a/cal/test9500.trigeq.cal b/cal/test9500.trigeq.cal index 7ab180c..381ad88 100644 --- a/cal/test9500.trigeq.cal +++ b/cal/test9500.trigeq.cal @@ -1312,3 +1312,122 @@ define verify_crd(testnum) } return error_count; } + + +/* + * verify_cas - verify cosine plus sine + * + * We use the following trigonometric identity: + * + * cas(x) = cos(x) + sin(x) + * + * given: + * testnum regression test number being performed + * + * returns: + * number of tests that failed + */ +define verify_cas(testnum) +{ + local tval_len; /* current length of the tval[] array */ + local ident_val; /* computed trig value trigonometric identity */ + local trig_val; /* computed value from the trigonometric function */ + local error_count; /* number of compare errors detected */ + local i; + + /* + * firewall + */ + if (size(sin_tval) <= 0) { + precompute_trig(); + } + if (size(cos_tval) <= 0) { + precompute_trig(); + } + + /* + * for each test value, verify the trigonometric identity within epsilon + */ + tval_len = size(tval); + for (i=0; i < tval_len; ++i) { + + /* compute trigonometric identity */ + ident_val = cos_tval[i] + sin_tval[i]; + + /* compute trigonometric function */ + trig_val = cas(tval[i]); + + /* compare trigonometric identity with trigonometric function value */ + if (compare(ident_val, trig_val, "cas", i, testnum)) { + ++error_count; + } + } + + /* + * report test results + */ + if (error_count != 0) { + print '**** test', testnum : ': cas test failure count:', error_count; + } + return error_count; +} + + +/* + * verify_cis - verify Euler's formula + * + * We use the following trigonometric identity: + * + * cis(x) = cos(x) + i*sin(x) + * cis(x) = exp(1i * x) + * + * given: + * testnum regression test number being performed + * + * returns: + * number of tests that failed + */ +define verify_cis(testnum) +{ + local tval_len; /* current length of the tval[] array */ + local ident_val; /* computed trig value trigonometric identity */ + local trig_val; /* computed value from the trigonometric function */ + local error_count; /* number of compare errors detected */ + local i; + + /* + * firewall + */ + if (size(sin_tval) <= 0) { + precompute_trig(); + } + if (size(cos_tval) <= 0) { + precompute_trig(); + } + + /* + * for each test value, verify the trigonometric identity within epsilon + */ + tval_len = size(tval); + for (i=0; i < tval_len; ++i) { + + /* compute trigonometric identity */ + ident_val = cos_tval[i] + 1i*sin_tval[i]; + + /* compute trigonometric function */ + trig_val = cis(tval[i]); + + /* compare trigonometric identity with trigonometric function value */ + if (compare(ident_val, trig_val, "cis", i, testnum)) { + ++error_count; + } + } + + /* + * report test results + */ + if (error_count != 0) { + print '**** test', testnum : ': cis test failure count:', error_count; + } + return error_count; +} diff --git a/cmath.h b/cmath.h index bbc4ef5..737d42a 100644 --- a/cmath.h +++ b/cmath.h @@ -74,6 +74,7 @@ E_FUNC COMPLEX *c_square(COMPLEX *c); E_FUNC COMPLEX *c_conj(COMPLEX *c); E_FUNC COMPLEX *c_real(COMPLEX *c); E_FUNC NUMBER *c_to_q(COMPLEX *c, bool cfree); +E_FUNC COMPLEX *q_to_c(NUMBER *q); E_FUNC COMPLEX *c_imag(COMPLEX *c); E_FUNC COMPLEX *c_neg(COMPLEX *c); E_FUNC COMPLEX *c_inv(COMPLEX *c); @@ -150,6 +151,8 @@ E_FUNC COMPLEX *c_excsc(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_aexcsc(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_crd(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_acrd(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_cas(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_cis(COMPLEX *c, NUMBER *epsilon); diff --git a/comfunc.c b/comfunc.c index 2035374..81e8e9b 100644 --- a/comfunc.c +++ b/comfunc.c @@ -2719,3 +2719,112 @@ c_acrd(COMPLEX *c, NUMBER *epsilon) */ return r; } + + +/* + * c_cas - COMPLEX valued cosine plus sine + * + * This uses the formula: + * + * cas(x) = cos(x) + sin(x) + * + * given: + * c 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_cas(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* return COMPLEX value */ + COMPLEX *csin; /* complex sin(c) */ + COMPLEX *ccos; /* complex cos(c) */ + + /* + * 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 trig function value + */ + csin = c_sin(c, epsilon); + if (csin == NULL) { + math_error("Failed to compute complex sine for complex cas"); + not_reached(); + } + ccos = c_cos(c, epsilon); + if (ccos == NULL) { + comfree(csin); + math_error("Failed to compute complex cosine for complex cas"); + not_reached(); + } + r = c_add(csin, ccos); + comfree(csin); + comfree(ccos); + + /* + * return trigonometric result + */ + return r; +} + + +/* + * c_cis - COMPLEX valued Euler's formula + * + * This uses the formula: + * + * cis(x) = cos(x) + 1i*sin(x) + * cis(x) = exp(1i * x) + * + * given: + * c 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_cis(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* return COMPLEX value */ + COMPLEX *ctmp; /* 1i * c */ + + /* + * 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 trig function value + */ + ctmp = c_mul(c, &_conei_); + r = c_exp(ctmp, epsilon); + comfree(ctmp); + if (r == NULL) { + math_error("Failed to compute complex exp for complex cis"); + not_reached(); + } + + /* + * return trigonometric result + */ + return r; +} diff --git a/commath.c b/commath.c index d0e7ad1..2425d6d 100644 --- a/commath.c +++ b/commath.c @@ -526,6 +526,38 @@ c_to_q(COMPLEX *c, bool cfree) } +/* + * q_to_c - convert a NUMBER into an allocated COMPLEX + * + * given: + * q NUMBER to be converted + * + * returns: + * allocated COMPLEX number whose real part is NUMBER and imag part is 0 + */ +COMPLEX * +q_to_c(NUMBER *q) +{ + COMPLEX *res; /* COMPLEX number to return */ + + /* + * allocate complex number + */ + res = comalloc(); + + /* + * assign NUMBER to real part + */ + qfree(res->real); + res->real = qlink(q); + + /* + * return the allocated equivalent COMPLEX + */ + return res; +} + + /* * Return the imaginary part of a complex number as a real. */ diff --git a/errtbl.c b/errtbl.c index 18322a0..3ba9a76 100644 --- a/errtbl.c +++ b/errtbl.c @@ -749,6 +749,12 @@ CONST struct errtbl error_table[] = { 10597, "E_ACRD_1", "Bad epsilon for acrd" }, { 10598, "E_ACRD_2", "Bad argument for acrd" }, { 10599, "E_ACRD_3", "Invalid value for calculating acrd" }, + { 10600, "E_CAS_1", "Bad epsilon for cas" }, + { 10601, "E_CAS_2", "Bad argument for cas" }, + { 10602, "E_CAS_3", "Invalid complex argument for cas" }, + { 10603, "E_CIS_1", "Non-real epsilon for cis" }, + { 10604, "E_CIS_2", "Bad first argument for cis" }, + { 10605, "E_CIS_3", "Too-large re(argument) for cis" }, /* IMPORTANT NOTE: add new entries above here and be sure their errnum numeric value is consecutive! */ /* The next NULL entry must be last */ diff --git a/func.c b/func.c index 31f8412..0aae2a8 100644 --- a/func.c +++ b/func.c @@ -2661,7 +2661,7 @@ f_cos(int count, VALUE **vals) } /* - * compute cosinr to a given error tolerance + * compute cosine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -10848,7 +10848,7 @@ f_versin(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute versed trigonometric sine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -10906,7 +10906,7 @@ f_aversin(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse versed trigonometric sine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -10988,7 +10988,7 @@ f_coversin(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute coversed trigonometric sine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11046,7 +11046,7 @@ f_acoversin(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse coversed trigonometric sine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11128,7 +11128,7 @@ f_vercos(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute versed trigonometric cosine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11186,7 +11186,7 @@ f_avercos(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse versed trigonometric cosine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11268,7 +11268,7 @@ f_covercos(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute coversed trigonometric cosine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11326,7 +11326,7 @@ f_acovercos(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse coversed trigonometric cosine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11408,7 +11408,7 @@ f_haversin(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute half versed trigonometric sine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11466,7 +11466,7 @@ f_ahaversin(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse half versed trigonometric sine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11548,7 +11548,7 @@ f_hacoversin(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute half coversed trigonometric sine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11606,7 +11606,7 @@ f_ahacoversin(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse half coversed trigonometric sine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11688,7 +11688,7 @@ f_havercos(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute half versed trigonometric cosine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11746,7 +11746,7 @@ f_ahavercos(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse half versed trigonometric cosine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -11828,7 +11828,7 @@ f_hacovercos(int count, VALUE **vals) } /* - * compute trig function to a given error tolerance + * compute half coversed trigonometric cosine to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -11886,7 +11886,7 @@ f_ahacovercos(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse half coversed trigonometric cosine to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -12022,7 +12022,7 @@ f_aexsec(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse exterior trigonometric secant to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -12104,7 +12104,7 @@ f_excsc(int count, VALUE **vals) } /* - * compute cosecant to a given error tolerance + * compute exterior trigonometric cosecant to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -12164,7 +12164,7 @@ f_aexcsc(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse exterior trigonometric cosecant to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -12220,7 +12220,7 @@ f_aexcsc(int count, VALUE **vals) /* - * f_crd - exterior trigonometric cosecant + * f_crd - trigonometric chord of a unit circle */ S_FUNC VALUE f_crd(int count, VALUE **vals) @@ -12246,7 +12246,7 @@ f_crd(int count, VALUE **vals) } /* - * compute cosecant to a given error tolerance + * compute chord of a unit circle to a given error tolerance */ switch (vals[0]->v_type) { case V_NUM: @@ -12273,7 +12273,7 @@ f_crd(int count, VALUE **vals) /* - * f_acrd - exterior trigonometric cosecant + * f_acrd - inverse trigonometric chord of a unit circle */ S_FUNC VALUE f_acrd(int count, VALUE **vals) @@ -12300,7 +12300,7 @@ f_acrd(int count, VALUE **vals) } /* - * compute inverse trig function to a given error tolerance + * compute inverse trigonometric chord of a unit circle to a given error tolerance */ arg1 = *vals[0]; if (arg1.v_type == V_NUM) { @@ -12355,6 +12355,137 @@ f_acrd(int count, VALUE **vals) } +/* + * f_cas - trigonometric chord of a unit circle + */ +S_FUNC VALUE +f_cas(int count, VALUE **vals) +{ + VALUE result; + COMPLEX *c; + NUMBER *err; + + /* initialize VALUEs */ + result.v_subtype = V_NOSUBTYPE; + + /* + * set error tolerance for builtin function + * + * Use err VALUE arg if given and value is in a valid range. + */ + err = conf->epsilon; + if (count == 2) { + if (verify_eps(vals[1]) == false) { + return error_value(E_CAS_1); + } + err = vals[1]->v_num; + } + + /* + * compute chord of a unit circle to a given error tolerance + */ + switch (vals[0]->v_type) { + case V_NUM: + result.v_num = qcas(vals[0]->v_num, err); + result.v_type = V_NUM; + break; + case V_COM: + c = c_cas(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_CAS_3); + } + result.v_com = c; + result.v_type = V_COM; + if (cisreal(c)) { + result.v_num = c_to_q(c, true); + result.v_type = V_NUM; + } + break; + default: + return error_value(E_CAS_2); + } + return result; +} + + +/* + * f_cis - Euler's formula + */ +S_FUNC VALUE +f_cis(int count, VALUE **vals) +{ + VALUE result; + NUMBER *eps; + COMPLEX *c; + COMPLEX *ctmp; + + /* 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_CIS_1); + } + eps = vals[1]->v_num; + } + + /* + * compute Euler's formula to a given error tolerance + */ + switch (vals[0]->v_type) { + case V_NUM: + /* + * convert arg to COMPLEX + */ + ctmp = q_to_c(vals[0]->v_num); + + /* + * compute cis of argument + */ + c = c_cis(ctmp, eps); + comfree(ctmp); + if (c == NULL) { + return error_value(E_CIS_3); + } + break; + case V_COM: + + /* + * compute cis of argument + */ + c = c_cis(vals[0]->v_com, eps); + if (c == NULL) { + return error_value(E_CIS_3); + } + break; + default: + return error_value(E_CIS_2); + } + + /* + * case: return NUMBER value + */ + if (cisreal(c)) { + result.v_num = c_to_q(c, true); + result.v_type = V_NUM; + return result; + } + + /* + * case: return COMPLEX value + */ + result.v_com = c; + result.v_type = V_COM; + return result; +} + + #endif /* !FUNCLIST */ @@ -12487,6 +12618,8 @@ STATIC CONST struct builtin builtins[] = { "current CALCPATH search path value"}, {"calc_tty", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_calc_tty}, "set tty for interactivity"}, + {"cas", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_cas}, + "cosine plus sine, within accuracy b"}, {"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}, @@ -12498,6 +12631,8 @@ STATIC CONST struct builtin builtins[] = { "simplify number using continued fractions"}, {"char", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_char}, "character corresponding to integer value"}, + {"cis", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_cis}, + "Euler's formula, within accuracy b"}, {"cmdbuf", 0, 0, 0, OP_NOP, {.null = NULL}, {.valfunc_0 = f_cmdbuf}, "command buffer"}, {"cmp", 2, 2, 0, OP_CMP, {.null = NULL}, {.null = NULL}, diff --git a/help/Makefile b/help/Makefile index 3711507..89af044 100644 --- a/help/Makefile +++ b/help/Makefile @@ -204,9 +204,9 @@ DETAIL_HELP= abs access acos acosh acot acoth acovercos acoversin \ ahavercos ahaversin append appr arg argv arrow asec asech asin asinh \ assign atan atan2 atanh avercos 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 covercos coversin cp crd csc csch ctime d2dm d2dms d2g d2r \ - delete den dereference det digit digits display dms2d dp epsilon \ + cas catalan ceil cfappr cfsim char cis cmdbuf cmp comb conj cos cosh \ + cot coth count covercos coversin cp crd csc csch ctime d2dm d2dms d2g \ + d2r delete den dereference det digit digits display dms2d dp epsilon \ errcount errmax errno error errsym estr euler eval excsc exp exsec \ fact factor fclose fcnt feof ferror fflush fgetc fgetfield fgetfile \ fgetline fgets fgetstr fib files floor fopen forall fpathopen fprintf \ diff --git a/help/acos b/help/acos index 645a36f..3e87e7d 100644 --- a/help/acos +++ b/help/acos @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/acot b/help/acot index 2fa09bf..873c41c 100644 --- a/help/acot +++ b/help/acot @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/acovercos b/help/acovercos index 50a3601..2d4ebbf 100644 --- a/help/acovercos +++ b/help/acovercos @@ -54,6 +54,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/acoversin b/help/acoversin index 09bd00c..4d7dd4c 100644 --- a/help/acoversin +++ b/help/acoversin @@ -54,6 +54,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/acrd b/help/acrd index af56a50..a61c637 100644 --- a/help/acrd +++ b/help/acrd @@ -51,6 +51,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/acsc b/help/acsc index 3399699..d1fe6e8 100644 --- a/help/acsc +++ b/help/acsc @@ -58,6 +58,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/aexcsc b/help/aexcsc index 115e7e6..8cb8918 100644 --- a/help/aexcsc +++ b/help/aexcsc @@ -60,6 +60,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/aexsec b/help/aexsec index 8e024ce..de3679c 100644 --- a/help/aexsec +++ b/help/aexsec @@ -57,6 +57,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/ahacovercos b/help/ahacovercos index 1ea7c4e..9262dba 100644 --- a/help/ahacovercos +++ b/help/ahacovercos @@ -57,6 +57,7 @@ SEE ALSO ahaversin, hacoversin, havercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/ahacoversin b/help/ahacoversin index e8de0ba..2229935 100644 --- a/help/ahacoversin +++ b/help/ahacoversin @@ -57,6 +57,7 @@ SEE ALSO ahaversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/ahavercos b/help/ahavercos index c228da8..9f6e4af 100644 --- a/help/ahavercos +++ b/help/ahavercos @@ -58,6 +58,7 @@ SEE ALSO ahaversin, hacoversin, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/ahaversin b/help/ahaversin index 1c262a5..eb23265 100644 --- a/help/ahaversin +++ b/help/ahaversin @@ -58,6 +58,7 @@ SEE ALSO hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/asec b/help/asec index e8e4302..a6d202a 100644 --- a/help/asec +++ b/help/asec @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/asin b/help/asin index 1dbfd4d..429b28a 100644 --- a/help/asin +++ b/help/asin @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/atan b/help/atan index b387ed8..5b89eef 100644 --- a/help/atan +++ b/help/atan @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/avercos b/help/avercos index 4491734..1f87699 100644 --- a/help/avercos +++ b/help/avercos @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/aversin b/help/aversin index 9d92e1e..2bdc808 100644 --- a/help/aversin +++ b/help/aversin @@ -55,6 +55,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/cas b/help/cas new file mode 100644 index 0000000..deb81c4 --- /dev/null +++ b/help/cas @@ -0,0 +1,86 @@ +NAME + cas - trigonometric cosine plus sine + +SYNOPSIS + cas(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return number + +DESCRIPTION + Calculate the trigonometric cosine plus sine of x to a multiple of eps with error less in + absolute value than .75 * eps. + + This function is sometimes called cosine and sine, is equivalent to: + + cas(x) = cos(x) + sin(x) + +EXAMPLE + ; print cas(1/2), cas(5/7), cas(42/7) + 1.35700810049457571639 1.41063924387921517267 0.68075478845144014774 + + ; print cas(1, 1e-5), cas(1, 1e-10), cas(1, 1e-15), cas(1, 1e-20) + 1.38177 1.3817732907 1.381773290676036 1.38177329067603622405 + + ; print cas(2 + 3i, 1e-5), cas(2 + 3i, 1e-10) + 4.96487-13.27814i 4.9648734559-13.2781348538i + + ; pi = pi(1e-20) + ; print cas(pi/6), cas(pi/2), cas(pi) + 1.36602540378443864676 1 -1 + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qcas(NUMBER *x, NUMBER *eps) + COMPLEX *c_cas(COMPLEX *x, NUMBER *eps) + +SEE ALSO + cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc + versin, coversin, vercos, covercos + aversin, acoversin, avercos, acovercos + haversin, hacoversin, havercos, hacovercos + ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc + crd, acrd + cis + epsilon + +EXTERNAL RESOURCES + For general information on trigonometric functions, see: + + https://en.wikipedia.org/wiki/Trigonometric_functions#Unit-circle_definitions + https://en.wikipedia.org/wiki/Versine + https://en.wikipedia.org/wiki/Exsecant + https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + https://en.wikipedia.org/wiki/Chord_(geometry) + https://en.wikipedia.org/wiki/Secant_line + https://en.wikipedia.org/wiki/Hartley_transform#cas + https://en.wikipedia.org/wiki/Cis_(mathematics) + +## 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/10/02 23:11:18 +## 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/cis b/help/cis new file mode 100644 index 0000000..c66cd65 --- /dev/null +++ b/help/cis @@ -0,0 +1,92 @@ +NAME + cis - Euler's formula + +SYNOPSIS + cis(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return number + +DESCRIPTION + Calculate the Euler's formula value of x to a multiple of eps with error less in + absolute value than .75 * eps. + + This function is sometimes called cosine and sine, is equivalent to: + + cis(x) = cos(x) + 1i*sin(x) + cis(x) = exp(1i * x) + +EXAMPLE + ; print cis(1/2), cis(5/7) + 0.87758256189037271612+0.47942553860420300027i 0.75556134670069659847+0.6550778971785185742i + + ; print cis(42/7) + 0.96017028665036602055-0.27941549819892587281i + + ; print cis(1, 1e-5), cis(1, 1e-10), cis(1, 1e-15) + 0.5403+0.84147i 0.5403023059+0.8414709848i 0.54030230586814+0.841470984807896i + + ; print cis(1, 1e-20) + 0.5403023058681397174+0.84147098480789650665i + + ; print cis(2 + 3i, 1e-5), cis(2 + 3i, 1e-10) + -0.02072+0.04527i -0.020718731+0.0452712531i + + ; pi = pi(1e-20) + ; print cis(pi/6), cis(pi/2), cis(pi) + 0.86602540378443864676+0.5i 1i -1 + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + COMPLEX *c_cis(COMPLEX *x, NUMBER *eps) + +SEE ALSO + cos, tan, cot, sec, csc + asin, acos, atan, acot, asec, acsc + versin, coversin, vercos, covercos + aversin, acoversin, avercos, acovercos + haversin, hacoversin, havercos, hacovercos + ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc + crd, acrd + cis + epsilon + +EXTERNAL RESOURCES + For general information on trigonometric functions, see: + + https://en.wikipedia.org/wiki/Trigonometric_functions#Unit-circle_definitions + https://en.wikipedia.org/wiki/Versine + https://en.wikipedia.org/wiki/Exsecant + https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + https://en.wikipedia.org/wiki/Chord_(geometry) + https://en.wikipedia.org/wiki/Secant_line + https://en.wikipedia.org/wiki/Hartley_transform#cas + https://en.wikipedia.org/wiki/Cis_(mathematics) + +## 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/10/02 23:11:18 +## 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 9b707fc..f579e33 100644 --- a/help/cos +++ b/help/cos @@ -44,6 +44,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/cot b/help/cot index 75ab174..df75cc4 100644 --- a/help/cot +++ b/help/cot @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/covercos b/help/covercos index 9432c36..7bbd9a9 100644 --- a/help/covercos +++ b/help/covercos @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/coversin b/help/coversin index 79f81c6..bb79769 100644 --- a/help/coversin +++ b/help/coversin @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/crd b/help/crd index 0b9d5f6..3e4ae5f 100644 --- a/help/crd +++ b/help/crd @@ -51,6 +51,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/csc b/help/csc index d79000e..1b8a7c4 100644 --- a/help/csc +++ b/help/csc @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/excsc b/help/excsc index d791a36..4fc4b2e 100644 --- a/help/excsc +++ b/help/excsc @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/exp b/help/exp index 6d12322..38f4f38 100644 --- a/help/exp +++ b/help/exp @@ -39,7 +39,7 @@ LINK LIBRARY COMPLEX *c_exp(COMPLEX *x, NUMBER *eps) SEE ALSO - ln, cosh, sinh, tanh + ln, log, log2, logn, cosh, sinh, tanh ## Copyright (C) 1999,2021,2023 Landon Curt Noll ## diff --git a/help/exsec b/help/exsec index 6ab1648..ea23222 100644 --- a/help/exsec +++ b/help/exsec @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/hacovercos b/help/hacovercos index e397f0f..8e5a6a2 100644 --- a/help/hacovercos +++ b/help/hacovercos @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/hacoversin b/help/hacoversin index c5c2d5d..be7f833 100644 --- a/help/hacoversin +++ b/help/hacoversin @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/havercos b/help/havercos index 5fadde6..a1d9c3e 100644 --- a/help/havercos +++ b/help/havercos @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/haversin b/help/haversin index 1e8ca58..2389efa 100644 --- a/help/haversin +++ b/help/haversin @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/sec b/help/sec index ce26eae..7d93cb3 100644 --- a/help/sec +++ b/help/sec @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/sin b/help/sin index c31e895..6445a04 100644 --- a/help/sin +++ b/help/sin @@ -44,6 +44,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/tan b/help/tan index 343c70f..a4051ab 100644 --- a/help/tan +++ b/help/tan @@ -50,6 +50,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/vercos b/help/vercos index 739c8ff..72d83ad 100644 --- a/help/vercos +++ b/help/vercos @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/help/versin b/help/versin index 2b86613..9fafa2a 100644 --- a/help/versin +++ b/help/versin @@ -48,6 +48,7 @@ SEE ALSO ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd + cas, cis epsilon EXTERNAL RESOURCES diff --git a/qmath.h b/qmath.h index f17b0a3..4aacff3 100644 --- a/qmath.h +++ b/qmath.h @@ -259,13 +259,13 @@ E_FUNC NUMBER *qaexcsc(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qcrd(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qacrd_or_NULL(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qacrd(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qcas(NUMBER *q, NUMBER *epsilon); /* * pseudo-seed generator */ E_FUNC NUMBER *pseudo_seed(void); - /* * external swap functions */ diff --git a/qtrans.c b/qtrans.c index 28d0fb2..9034731 100644 --- a/qtrans.c +++ b/qtrans.c @@ -202,6 +202,7 @@ qsincos(NUMBER *q, long bitnum, NUMBER **vs, NUMBER **vc) return; } + /* * Calculate the cosine of a number to a near multiple of epsilon. * This calls qsincos() and discards the value of sin. @@ -3623,3 +3624,69 @@ qacrd(NUMBER *q, NUMBER *epsilon) */ return res; } + + +/* + * qcas - trigonometric chord of a unit circle + * + * This uses the formula: + * + * cas(x) = cos(x) + sin(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 * +qcas(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *sin; /* sin(x) */ + NUMBER *tsin; /* sin(x) rounded to nearest epsilon multiple */ + NUMBER *cos; /* cos(x) */ + NUMBER *tcos; /* cos(x) rounded to nearest epsilon multiple */ + NUMBER *res; + long n; + + /* + * firewall + */ + if (qiszero(epsilon)) { + math_error("Zero epsilon value for cosine"); + not_reached(); + } + + /* + * case 0: quick return 1 + */ + if (qiszero(q)) { + return qlink(&_qone_); + } + + /* + * case epsilon > 1: quick return 0 + */ + n = -qilog2(epsilon); + if (n < 0) { + return qlink(&_qzero_); + } + + /* + * compute cosine and sine + */ + qsincos(q, n + 2, &sin, &cos); + tcos = qmappr(cos, epsilon, 24); + qfree(cos); + tsin = qmappr(sin, epsilon, 24); + qfree(sin); + res = qqadd(tcos, tsin); + qfree(tcos); + qfree(tsin); + + /* + * return trigonometric result + */ + return res; +}