From c78a89386249916ac1dfad9bdad63d9790b64f02 Mon Sep 17 00:00:00 2001 From: Landon Curt Noll Date: Sun, 1 Oct 2023 23:12:21 -0700 Subject: [PATCH] add exterior trigonometric functions Added the following new trigonometric functions: exsec(x [,eps]) exterior trigonometric secant aexsec(x [,eps]) inverse exterior trigonometric secant excsc(x [,eps]) exterior trigonometric cosecant aexcsc(x [,eps]) inverse exterior trigonometric cosecant Added to test 95dd and test9500.trigeq.cal to the calc regression test suite to perform extensive test of trigonometric functions. Added to test 34dd, some if the missing inverse trigonometric tests. --- CHANGES | 8 +- cal/regress.cal | 650 ++++++++++++++++++++++++++-------------- cal/test9500.trigeq.cal | 120 ++++++++ cmath.h | 4 + comfunc.c | 192 ++++++++++++ errtbl.c | 15 +- func.c | 289 +++++++++++++++++- help/acos | 1 + help/acot | 1 + help/acovercos | 1 + help/acoversin | 1 + help/acsc | 1 + help/aexcsc | 84 ++++++ help/aexsec | 81 +++++ help/ahacovercos | 1 + help/ahacoversin | 1 + help/ahavercos | 1 + help/ahaversin | 1 + help/asec | 1 + help/asin | 1 + help/atan | 1 + help/avercos | 1 + help/aversin | 1 + help/cos | 1 + help/cot | 3 +- help/covercos | 1 + help/coversin | 1 + help/csc | 3 +- help/excsc | 74 +++++ help/exsec | 74 +++++ help/hacovercos | 1 + help/hacoversin | 1 + help/havercos | 1 + help/haversin | 1 + help/sec | 3 +- help/sin | 1 + help/tan | 3 +- help/vercos | 1 + help/versin | 1 + qmath.h | 6 + qtrans.c | 297 ++++++++++++++++++ 41 files changed, 1693 insertions(+), 237 deletions(-) create mode 100644 help/aexcsc create mode 100644 help/aexsec create mode 100644 help/excsc create mode 100644 help/exsec diff --git a/CHANGES b/CHANGES index 2178851..d97d6e3 100644 --- a/CHANGES +++ b/CHANGES @@ -354,12 +354,18 @@ The following are the changes from calc version 2.14.3.5 to date: ahacoversin(x [,eps]) inverse half coversed trigonometric sine ahavercos(x [,eps]) inverse half versed trigonometric cosine ahacovercos(x [,eps]) inverse half coversed trigonometric cosine + exsec(x [,eps]) exterior trigonometric secant + aexsec(x [,eps]) inverse exterior trigonometric secant + excsc(x [,eps]) exterior trigonometric cosecant + aexcsc(x [,eps]) inverse exterior trigonometric cosecant Fixed calc regression test 42dd to set the display value back to 20. - Added test 95dd and test9500.trigeq.cal to the calc regression test + Added to test 95dd and test9500.trigeq.cal to the calc regression test suite to perform extensive test of trigonometric functions. + Added to test 34dd, some if the missing inverse trigonometric tests. + The following are the changes from calc version 2.14.3.4 to 2.14.3.5: diff --git a/cal/regress.cal b/cal/regress.cal index 8c4523c..cbf872f 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -3904,6 +3904,22 @@ define test_trig() strcat(str(tnum++), ': round(haversin(2 + 3i, 1e-10), 10) == 2.5948128455+4.5546139469i')); + /* test inverse half versed trigonometric sine */ + vrfy(ahaversin(0, 1e-10) == 0, + strcat(str(tnum++), ': ahaversin(0, 1e-10) == 0')); + vrfy(round(ahaversin(0.5, 1e-10), 10) == 1.5707963268, + strcat(str(tnum++), + ': round(ahaversin(0.5, 1e-10), 10) == 1.5707963268')); + vrfy(round(ahaversin(1, 1e-10), 10) == 3.1415926536, + strcat(str(tnum++), + ': round(ahaversin(1, 1e-10), 10) == 3.1415926536')); + vrfy(round(ahaversin(-5, 1e-10), 10) == 3.0889699048i, + strcat(str(tnum++), + ': round(ahaversin(-5, 1e-10), 10) == 3.0889699048i')); + vrfy(round(ahaversin(2 + 3i, 1e-10), 10) == 2.03004373+2.5998241933i, + strcat(str(tnum++), + ': round(ahaversin(2 + 3i, 1e-10), 10) == 2.03004373+2.5998241933i')); + /* test half coversed trigonometric sine */ vrfy(hacoversin(0, 1e-10) == 0.5, strcat(str(tnum++), ': hacoversin(0, 1e-10) == 0.5')); @@ -3931,6 +3947,22 @@ define test_trig() strcat(str(tnum++), ': round(hacoversin(2 + 3i, 1e-10), 10) == -4.0772495734+2.08445348i')); + /* test inverse half coversed trigonometric sine */ + vrfy(ahacoversin(1, 1e-10) == 0, + strcat(str(tnum++), ': ahacoversin(1, 1e-10) == 0')); + vrfy(round(ahacoversin(0.5, 1e-10), 10) == 0.5235987756, + strcat(str(tnum++), + ': round(ahacoversin(0.5, 1e-10), 10) == 0.5235987756')); + vrfy(round(ahacoversin(0, 1e-10), 10) == 1.5707963268, + strcat(str(tnum++), + ': round(ahacoversin(0, 1e-10), 10) == 1.5707963268')); + vrfy(round(ahacoversin(-5, 1e-10), 10) == 1.5707963268-3.0889699048i, + strcat(str(tnum++), + ': round(ahacoversin(-5, 1e-10), 10) == 1.5707963268-3.0889699048i')); + vrfy(round(ahacoversin(2 + 3i, 1e-10), 10) == -0.4592474035-2.5998241938i, + strcat(str(tnum++), + ': round(ahacoversin(2 + 3i, 1e-10), 10) == -0.4592474035-2.5998241938i')); + /* test half versed trigonometric cosine */ vrfy(havercos(0, 1e-10) == 1, strcat(str(tnum++), ': havercos(0, 1e-10) == 1')); @@ -3958,6 +3990,22 @@ define test_trig() strcat(str(tnum++), ': round(havercos(2 + 3i, 1e-10), 10) == -1.5948128455-4.5546139469i')); + /* test inverse half versed trigonometric cosine */ + vrfy(ahavercos(0, 1e-10) == 0, + strcat(str(tnum++), ': ahavercos(0, 1e-10) == 0')); + vrfy(round(ahavercos(0.5, 1e-10), 10) == 1.5707963268, + strcat(str(tnum++), + ': round(ahavercos(0.5, 1e-10), 10) == 1.5707963268')); + vrfy(round(ahavercos(1, 1e-10), 10) == 3.1415926536, + strcat(str(tnum++), + ': round(ahavercos(1, 1e-10), 10) == 3.1415926536')); + vrfy(round(ahavercos(-5, 1e-10), 10) == 3.0889699048i, + strcat(str(tnum++), + ': round(ahavercos(-5, 1e-10), 10) == 3.0889699048i')); + vrfy(round(ahavercos(2 + 3i, 1e-10), 10) == 2.03004373+2.5998241933i, + strcat(str(tnum++), + ': round(ahavercos(2 + 3i, 1e-10), 10) == 2.03004373+2.5998241933i')); + /* test half coversed trigonometric cosine */ vrfy(hacovercos(0, 1e-10) == 0.5, strcat(str(tnum++), ': hacovercos(0, 1e-10) == 0.5')); @@ -3985,16 +4033,123 @@ define test_trig() strcat(str(tnum++), ': round(hacovercos(2 + 3i, 1e-10), 10) == 5.0772495734-2.08445348i')); + /* test inverse half coversed trigonometric cosine */ + vrfy(ahacovercos(0, 1e-10) == 0, + strcat(str(tnum++), ': ahacovercos(0, 1e-10) == 0')); + vrfy(round(ahacovercos(0.5, 1e-10), 10) == 1.0471975512, + strcat(str(tnum++), + ': round(ahacovercos(0.5, 1e-10), 10) == 1.0471975512')); + vrfy(round(ahacovercos(1, 1e-10), 10) == 1.5707963268, + strcat(str(tnum++), + ': round(ahacovercos(1, 1e-10), 10) == 1.5707963268')); + vrfy(round(ahacovercos(-5, 1e-10), 10) == 1.5707963268-3.0889699048i, + strcat(str(tnum++), + ': round(ahacovercos(-5, 1e-10), 10) == 1.5707963268-3.0889699048i')); + vrfy(round(ahacovercos(2 + 3i, 1e-10), 10) == -0.4592474035-2.5998241938i, + strcat(str(tnum++), + ': round(ahacovercos(2 + 3i, 1e-10), 10) == -0.4592474035-2.5998241938i')); + + /* test exterior trigonometric secant */ + vrfy(exsec(0, 1e-10) == 0, + strcat(str(tnum++), ': exsec(0, 1e-10) == 0')); + vrfy(round(exsec(0.2, 1e-10), 10) == 0.0203388449, + strcat(str(tnum++), + ': round(exsec(0.2, 1e-10), 10) == 0.0203388449')); + vrfy(round(exsec(3/7, 1e-10), 10) == 0.0994322676, + strcat(str(tnum++), + ': round(exsec(3/7, 1e-10), 10) == 0.0994322676')); + vrfy(round(exsec(-31, 1e-10), 10) == 0.0932039951, + strcat(str(tnum++), + ': round(exsec(-31, 1e-10), 10) == 0.0932039951')); + vrfy(exsec(pi/3, 1e-10) == 1, + strcat(str(tnum++), ': exsec(pi/3, 1e-10) == 1')); + vrfy(exsec(2*pi/3, 1e-10) == -3, + strcat(str(tnum++), ': exsec(2*pi/3, 1e-10) == -3')); + vrfy(exsec(pi, 1e-10) == -2, + strcat(str(tnum++), ': exsec(pi, 1e-10) == -2')); + vrfy(exsec(2*pi, 1e-10) == 0, + strcat(str(tnum++), ': exsec(2*pi, 1e-10) == 0')); + vrfy(round(exsec(1, 1e-10), 10) == 0.8508157177, + strcat(str(tnum++), + ': round(exsec(1, 1e-10), 10) == 0.8508157177')); + vrfy(round(exsec(2 + 3i, 1e-10), 10) == -1.0416749644+0.0906111372i, + strcat(str(tnum++), + ': round(exsec(2 + 3i, 1e-10), 10) == -1.0416749644+0.0906111372i')); + + /* test inverse exterior trigonometric secant */ + vrfy(aexsec(0, 1e-10) == 0, + strcat(str(tnum++), ': aexsec(0, 1e-10) == 0')); + vrfy(round(aexsec(0.2, 1e-10), 10) == 0.5856855435, + strcat(str(tnum++), + ': round(aexsec(0.2, 1e-10), 10) == 0.5856855435')); + vrfy(round(aexsec(3/7, 1e-10), 10) == 0.7953988302, + strcat(str(tnum++), + ': round(aexsec(3/7, 1e-10), 10) == 0.7953988302')); + vrfy(round(aexsec(-31, 1e-10), 10) == 1.6041358361, + strcat(str(tnum++), + ': round(aexsec(-31, 1e-10), 10) == 1.6041358361')); + vrfy(round(aexsec(1, 1e-10), 10) == 1.0471975512, + strcat(str(tnum++), + ': round(aexsec(1, 1e-10), 10) == 1.0471975512')); + vrfy(round(aexsec(2 + 3i, 1e-10), 10) == 1.4057101283+0.1681700706i, + strcat(str(tnum++), + ': round(aexsec(2 + 3i, 1e-10), 10) == 1.4057101283+0.1681700706i')); + + /* test exterior trigonometric cosecant */ + vrfy(round(excsc(0.2, 1e-10), 10) == 4.0334895477, + strcat(str(tnum++), + ': round(excsc(0.2, 1e-10), 10) == 4.0334895477')); + vrfy(round(excsc(3/7, 1e-10), 10) == 1.4063227285, + strcat(str(tnum++), + ': round(excsc(3/7, 1e-10), 10) == 1.4063227285')); + vrfy(round(excsc(-31, 1e-10), 10) == 1.475016899, + strcat(str(tnum++), + ': round(excsc(-31, 1e-10), 10) == 1.475016899')); + vrfy(excsc(pi/6, 1e-10) == 1, + strcat(str(tnum++), ': excsc(pi/6, 1e-10) == 1')); + vrfy(excsc(pi/2, 1e-10) == 0, + strcat(str(tnum++), ': excsc(pi/2, 1e-10) == 0')); + vrfy(excsc(3*pi/2, 1e-10) == -2, + strcat(str(tnum++), ': excsc(3*pi/2, 1e-10) == -2')); + vrfy(round(excsc(1, 1e-10), 10) == 0.1883951058, + strcat(str(tnum++), + ': round(excsc(1, 1e-10), 10) == 0.1883951058')); + vrfy(round(excsc(2 + 3i, 1e-10), 10) == -0.9095267902+0.0412009863i, + strcat(str(tnum++), + ': round(excsc(2 + 3i, 1e-10), 10) == -0.9095267902+0.0412009863i')); + + /* test inverse exterior trigonometric cosecant */ + vrfy(round(aexcsc(0, 1e-10), 10) == 1.5707963268, + strcat(str(tnum++), + ': round(aexcsc(0, 1e-10), 10) == 1.5707963268')); + vrfy(round(aexcsc(0.2, 1e-10), 10) == 0.9851107833, + strcat(str(tnum++), + ': round(aexcsc(0.2, 1e-10), 10) == 0.9851107833')); + vrfy(round(aexcsc(3/7, 1e-10), 10) == 0.7753974966, + strcat(str(tnum++), + ': round(aexcsc(3/7, 1e-10), 10) == 0.7753974966')); + vrfy(round(aexcsc(-31, 1e-10), 10) == -0.0333395093, + strcat(str(tnum++), + ': round(aexcsc(-31, 1e-10), 10) == -0.0333395093')); + vrfy(round(aexcsc(1, 1e-10), 10) == 0.5235987756, + strcat(str(tnum++), + ': round(aexcsc(1, 1e-10), 10) == 0.5235987756')); + vrfy(round(aexcsc(2 + 3i, 1e-10), 10) == 0.1650861985-0.1681700706i, + strcat(str(tnum++), + ': round(aexcsc(2 + 3i, 1e-10), 10) == 0.1650861985-0.1681700706i')); + print strcat(str(tnum++), ': Ending test_trig'); } print '051: parsed test_trig()'; /* - * test 052-052: define test_frem and read test9300.frem for test 93dd + * test 052-054: define test_frem and read test9300.frem for test 93dd * * This function tests of functions frem, fcnt, gcdrem. * + * After defining test_frem we print errcount() and ecnt. + * * NOTE: We moved test3500 to test9300. We parse this code here, * however we execute this code as a 9300 test. */ @@ -4012,225 +4167,7 @@ define test_frem() print tnum: ': Ending test_frem'; } print '053: parsed test_frem()'; - - -/* - * test 054: define test_error for test 36dd + 37dd - * - * This function tests the error builtin. - * - * This function is designed to trigger 148 errors, so we bump the - * errmax by 148 during this call. - */ -define test_error() -{ - local strx, e99, list1, e9999; - local a, b, c, n, x; /* used by newerror() */ - - print '3600: Beginning test_error'; - - /* bump ecnt up by 156 */ - ecnt += 156; - print '3601: ecnt += 156'; - - strx = "x"; - print '3602: strx = "x"'; - e99 = error(99); - print '3603: e99 = error(99)'; - vrfy(1/0 == error("E_DIVBYZERO"), '3604: 1/0 == error("E_DIVBYZERO")'); - vrfy(0/0 == error("E_ZERODIVZERO"), '3605: 0/0 == error("E_ZERODIVZERO")'); - vrfy(2 + "x" == error("E_ADD"), '3606: 2 + "x" == error("E_ADD")'); - vrfy("x" - 2 == error("E_SUB"), '3607: "x" - 2 == error("E_SUB")'); - vrfy("x" * "y" == error("E_MUL"), '3608: "x" * "y" == error("E_MUL")'); - vrfy("x" / "y" == error("E_DIV"), '3609: "x" / "y" == error("E_DIV")'); - vrfy(-list(1) == error("E_NEG"), '3610: -list(1) == error("E_NEG")'); - vrfy("x"^2 == error("E_SQUARE"), '3611: "x"^2 == error("E_SQUARE")'); - vrfy(inverse("x")==error("E_INV"), '3612: inverse("x") == error("E_INV")'); - vrfy(++strx == error("E_INCV"), '3613: ++strx == error("E_INCV")'); - vrfy(strx == error("E_INCV"), '3614: strx == error("E_INCV")'); - strx = "x"; - print '3615: strx = "x"'; - vrfy(strx++ == "x", '3616: strx++ == "x"'); - vrfy(strx == error("E_INCV"), '3617: strx == error("E_INCV")'); - strx = "x"; - print '3618: strx = "x"'; - vrfy(--strx == error("E_DECV"), '3619: strx == error("E_DECV")'); - vrfy(int("x") == error("E_INT"), '3620: int("x") == error("E_INT")'); - vrfy(frac("x") == error("E_FRAC"), '3621: frac("x") == error("E_FRAC")'); - vrfy(conj("x") == error("E_CONJ"), '3622: conj("x") == error("E_CONJ")'); - vrfy(appr("x",.1) == error("E_APPR_1"), - '3623: appr("x",.1) == error("E_APPR_1")'); - vrfy(appr(1.27,.1i) == error("E_APPR_2"), - '3624: appr(1.27,.1i) == error("E_APPR_2")'); - vrfy(appr(1.27,.1,.1) == error("E_APPR_3"), - '3625: appr(1.27,.1,.1) == error("E_APPR_3")'); - vrfy(round("x") == error("E_ROUND_1"), - '3626: round("x") == error("E_ROUND_1")'); - vrfy(round(1.25,.1) == error("E_ROUND_2"), - '3627: round(1.25,.1) == error("E_ROUND_2")'); - vrfy(round(1.25,"x") == error("E_ROUND_2"), - '3628: round(1.25,"x") == error("E_ROUND_2")'); - vrfy(round(1.25,1,.1) == error("E_ROUND_3"), - '3629: round(1.25,1,.1) == error("E_ROUND_3")'); - vrfy(bround("x") == error("E_BROUND_1"), - '3630: bround("x") == error("E_BROUND_1")'); - vrfy(bround(1.25,.1) == error("E_BROUND_2"), - '3631: bround(1.25,.1) == error("E_BROUND_2")'); - vrfy(bround(1.25,"x") == error("E_BROUND_2"), - '3632: bround(1.25,"x") == error("E_BROUND_2")'); - vrfy(bround(1.25,1,.1) == error("E_BROUND_3"), - '3633: bround(1.25,1,.1) == error("E_BROUND_3")'); - vrfy(sqrt("x") == error("E_SQRT_1"), - '3634: sqrt("x") == error("E_SQRT_1")'); - vrfy(sqrt(2,"x") == error("E_SQRT_2"), - '3635: sqrt(2,"x") == error("E_SQRT_2")'); - vrfy(sqrt(2,0) == error("E_SQRT_2"), - '3636: sqrt(2,0) == error("E_SQRT_2")'); - vrfy(sqrt(2,.1,.1) == error("E_SQRT_3"), - '3637: sqrt(2,.1,.1) == error("E_SQRT_3")'); - vrfy(root("x",3) == error("E_ROOT_1"), - '3638: root("x",3) == error("E_ROOT_1")'); - vrfy(root(3,"x") == error("E_ROOT_2"), - '3639: root(3,"x") == error("E_ROOT_2")'); - vrfy(root(3,-2) == error("E_ROOT_2"), - '3640: root(3,-2) == error("E_ROOT_2")'); - vrfy(root(3,0) == error("E_ROOT_2"), - '3641: root(3,0) == error("E_ROOT_2")'); - vrfy(root(3,.1) == error("E_ROOT_2"), - '3642: root(3,.1) == error("E_ROOT_2")'); - vrfy(root(3,2,"x") == error("E_ROOT_3"), - '3643: root(3,2,"x") == error("E_ROOT_3")'); - vrfy(root(3,2,0) == error("E_ROOT_3"), - '3644: root(3,2,0) == error("E_ROOT_3")'); - vrfy(norm("x") == error("E_NORM"), '3645: norm("x") == error("E_NORM")'); - vrfy(list() << 2 == error("E_SHIFT_1"), '3646: list() << 2 == error("E_SHIFT_1")'); - vrfy(1.5 << 2 == error("E_SHIFT_1"), '3647: 1.5 << 2 == error("E_SHIFT_1")'); - vrfy(3 << "x" == error("E_SHIFT_2"), '3648: 3 << "x" == error("E_SHIFT_2")'); - vrfy(3 << 1.5 == error("E_SHIFT_2"), '3649: 3 << 1.5 == error("E_SHIFT_2")'); - vrfy(3 << 2^31 == error("E_SHIFT_2"), '3650: 3 << 2^31 == error("E_SHIFT_2")'); - vrfy(scale("x",2) == error("E_SCALE_1"), - '3651: scale("x",2) == error("E_SCALE_1")'); - vrfy(scale(3,"x") == error("E_SCALE_2"), - '3652: scale(3,"x") == error("E_SCALE_2")'); - vrfy(scale(3,1.5) == error("E_SCALE_2"), - '3653: scale(3,1.5) == error("E_SCALE_2")'); - vrfy(scale(3,2^31) == error("E_SCALE_2"), - '3654: scale(3,2^31) == error("E_SCALE_2")'); - vrfy("x" ^ 3 == error("E_POWI_1"), '3655: "x" ^ 3 == error("E_POWI_1")'); - vrfy(2 ^ "x" == error("E_POWI_2"), '3656: 2 ^ "x" == error("E_POWI_2")'); - vrfy(2 ^ "2" == error("E_POWI_2"), '3657: 2 ^ "2" == error("E_POWI_2")'); - vrfy(power("x",2.1) == error("E_POWER_1"), - '3658: power("x",2.1) == error("E_POWER_1")'); - vrfy(power(2,"x") == error("E_POWER_2"), - '3659: power(2,"x") == error("E_POWER_2")'); - vrfy(power(2,2.1,"x") == error("E_POWER_3"), - '3660: power(2,2.1,"x") == error("E_POWER_3")'); - vrfy(quo("x",3) == error("E_QUO_1"), - '3661: quo("x",3) == error("E_QUO_1")'); - vrfy(quo(8,"x") == error("E_QUO_2"), - '3662: quo(8,"x") == error("E_QUO_2")'); - vrfy(quo(8,3,"x") == error("E_QUO_3"), - '3663: quo(8,3,"x") == error("E_QUO_3")'); - vrfy(quo(8,3,2.1) == error("E_QUO_3"), - '3664: quo(8,3,2.1) == error("E_QUO_3")'); - vrfy(mod("x",3) == error("E_MOD_1"), - '3665: mod("x",3) == error("E_MOD_1")'); - vrfy(mod(8,"x") == error("E_MOD_2"), - '3666: mod(8,"x") == error("E_MOD_2")'); - vrfy(mod(8,3,"x") == error("E_MOD_3"), - '3667: mod(8,3,"x") == error("E_MOD_3")'); - vrfy(mod(8,3,2.1) == error("E_MOD_3"), - '3668: mod(8,3,2.1) == error("E_MOD_3")'); - vrfy(sgn("x") == error("E_SGN"), - '3669: sgn("x") == error("E_SGN")'); - vrfy(abs("x") == error("E_ABS_1"), - '3670: abs("x") == error("E_ABS_1")'); - vrfy(abs(2+3i,"x") == error("E_ABS_2"), - '3671: abs(2+3i,"x") == error("E_ABS_2")'); - vrfy(abs(2+3i,0) == error("E_ABS_2"), - '3672: abs(2+3i,0) == error("E_ABS_2")'); - list1 = list(2,3,"x",4,5); - print '3673: list1 = list(2,3,"x",4,5)'; - vrfy(avg(list1) == error("E_ADD"), - '3674: avg(list1) == error("E_ADD")'); - - vrfy(iserror(e99)==99, '3675: iserror(e99) == 99'); - vrfy(e99 + 2 == e99, '3676: e99 + 2 == e99'); - vrfy(e99 - 2 == e99, '3677: e99 - 2 == e99'); - vrfy(e99 * 2 == e99, '3678: e99 * 2 == e99'); - vrfy(e99 / 2 == e99, '3679: e99 / 2 == e99'); - vrfy(e99 // 2 == e99, '3680: e99 // 2 == e99'); - vrfy(e99 % 2 == e99, '3681: e99 % 2 == e99'); - vrfy(e99 ^ 2 == e99, '3682: e99 ^ 2 == e99'); - vrfy(2 + e99 == e99, '3683: 2 + e99 == e99'); - vrfy(2 - e99 == e99, '3684: 2 - e99 == e99'); - vrfy(2 * e99 == e99, '3685: 2 * e99 == e99'); - vrfy(2 / e99 == e99, '3686: 2 / e99 == e99'); - vrfy(2 // e99 == e99, '3687: 2 // e99 == e99'); - vrfy(2 % e99 == e99, '3688: 2 % e99 == e99'); - vrfy(2 ^ e99 == e99, '3689: 2 ^ e99 == e99'); - vrfy(- e99 == e99, '3690: -e99 == e99'); - vrfy(inverse(e99) == e99, '3691: inverse(e99) == e99'); - vrfy(++e99 == e99, '3692: ++e99 == e99'); - vrfy(--e99 == e99, '3693: --e99 == e99'); - vrfy(int(e99) == e99, '3694: int(e99) == e99'); - vrfy(frac(e99) == e99, '3695: frac(e99) == e99'); - vrfy(conj(e99) == e99, '3696: conj(e99) == e99'); - vrfy(norm(e99) == e99, '3697: norm(e99) == e99'); - vrfy(sgn(e99) == e99, '3698: sgn(e99) == e99'); - vrfy(appr(e99,1,0) == e99, '3699: appr(e99,1,0) == e99'); - vrfy(round(e99) == e99, '3700: round(e99) == e99'); - vrfy(bround(e99) == e99, '3701: bround(e99) == e99'); - vrfy(sqrt(e99) == e99, '3702: sqrt(e99) == e99'); - print '3703: a = newerror("alpha")'; - a = newerror("alpha"); - print '3704: b = newerror("beta")'; - b = newerror("beta"); - print '3705: c = newerror("alpha")'; - c = newerror("alpha"); - vrfy(a == c, '3706: a == c'); - vrfy(strerror(a) == "alpha", '3707: strerror(a) == "alpha"'); - print '3708: n = iserror(a)'; - n = iserror(a); - vrfy(a == error(n), '3709: a == error(n)'); - vrfy(newerror() == newerror("???"), - '3710: newerror() == newerror("???")'); - vrfy(newerror("") == newerror(), - '3711: newerror("") == newerror()'); - e9999 = error("E_9999"); - print '3712: e9999 = error("E_9999")'; - vrfy(errno() == 9999, '3713: errno() == 9999'); - vrfy(error() == e9999, '3714: error() == e9999'); - /* test 3715 removed due to non-portable strerror() output */ - x = newerror("Alpha"); - print '3716: x = newerror("Alpha")'; - n = iserror(x); - print '3717: n = iserror(x)'; - vrfy(errno() == n, '3718: errno() == n'); - vrfy(error() == x, '3719: error() == x'); - vrfy(strerror() == "Alpha", '3720: strerror() == "Alpha"'); - vrfy(errno("E_9999") == n, '3721: errno("E_9999") == n'); - vrfy(errno() == 9999, '3722: errno() == 9999'); - vrfy(error() == e9999, '3723: error() == e9999'); - /* test 3724 removed due to non-portable strerror() output */ - a = 1/0; - print '3725: a = 1/0'; - vrfy(strerror() == "Division by zero", - '3726: strerror() == "Division by zero"'); - n = 8191; - print '3727: n = 8191'; - print '3728: test removed due to non-portable strerror() output'; - vrfy(tan(2e9i) == error("E_TAN_5"), '3729: tan(2e9i) == error("E_TAN_5")'); - vrfy(cot(2e9i) == error("E_COT_6"), '3730: cot(2e9i) == error("E_COT_6")'); - vrfy(sec(2e9i) == error("E_SEC_5"), '3731: sec(2e9i) == error("E_SEC_5")'); - vrfy(csc(2e9i) == error("E_CSC_6"), '3732: csc(2e9i) == error("E_CSC_6")'); - - /* errmax and errcount should be bumped up the 148 errors above */ - vrfy(errcount() == ecnt, '3733: errcount() == ecnt'); - - print '3734: Ending test_error'; -} -print '054: parsed test_error()'; +print '054: errcount():', errcount() : ', ecnt:', ecnt; /* @@ -8673,17 +8610,15 @@ return test_det(); /* - * test 34dd: test common trig functions + * test 34dd + 35dd + 36dd: test common trig functions */ print; return test_trig(); -/* - * test 36dd + 37dd: test the error builtin - */ -print; -return test_error(); +/* *********************************************** */ +/* NOTE: ==> Room for new tests 3700-3799 here <== */ +/* *********************************************** */ /* @@ -9898,8 +9833,10 @@ vrfy(verify_haversin(9511) == 0, '9511: verify_haversin(9511) == 0'); vrfy(verify_hacoversin(9512) == 0, '9512: verify_hacoversin(9512) == 0'); 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'); -print '9515: Ending trigonometric identities test set'; +print '9517: Ending trigonometric identities test set'; /* @@ -9923,9 +9860,231 @@ vrfy(config("dupvar_warn",1)==0, '9609: config("dupvar_warn",1)==0'); print '9610: Ending test of dupvar_warn and redecl_warn config parameters'; -/* *********************************************** */ -/* NOTE: ==> Room for new tests 9700-9899 here <== */ -/* *********************************************** */ +/* + * test 9699: define test_error for test 97dd + 98dd + * + * This function tests the error builtin. + * + * This function is designed to trigger 148 errors, so we bump the + * errmax by 148 during this call. + */ +define test_error() +{ + local strx, e99, list1, e9999; + local a, b, c, n, x; /* used by newerror() */ + + print '9700: Beginning test_error'; + + print '9701: ecnt:', ecnt; + + strx = "x"; + print '9702: strx = "x"'; + e99 = error(99); + print '9703: e99 = error(99)'; + vrfy(1/0 == error("E_DIVBYZERO"), '9704: 1/0 == error("E_DIVBYZERO")'); + vrfy(0/0 == error("E_ZERODIVZERO"), '9705: 0/0 == error("E_ZERODIVZERO")'); + vrfy(2 + "x" == error("E_ADD"), '9706: 2 + "x" == error("E_ADD")'); + vrfy("x" - 2 == error("E_SUB"), '9707: "x" - 2 == error("E_SUB")'); + vrfy("x" * "y" == error("E_MUL"), '9708: "x" * "y" == error("E_MUL")'); + vrfy("x" / "y" == error("E_DIV"), '9709: "x" / "y" == error("E_DIV")'); + vrfy(-list(1) == error("E_NEG"), '9710: -list(1) == error("E_NEG")'); + vrfy("x"^2 == error("E_SQUARE"), '9711: "x"^2 == error("E_SQUARE")'); + vrfy(inverse("x")==error("E_INV"), '9712: inverse("x") == error("E_INV")'); + vrfy(++strx == error("E_INCV"), '9713: ++strx == error("E_INCV")'); + vrfy(strx == error("E_INCV"), '9714: strx == error("E_INCV")'); + strx = "x"; + print '9715: strx = "x"'; + vrfy(strx++ == "x", '9716: strx++ == "x"'); + vrfy(strx == error("E_INCV"), '9717: strx == error("E_INCV")'); + strx = "x"; + print '9718: strx = "x"'; + vrfy(--strx == error("E_DECV"), '9719: strx == error("E_DECV")'); + vrfy(int("x") == error("E_INT"), '9720: int("x") == error("E_INT")'); + vrfy(frac("x") == error("E_FRAC"), '9721: frac("x") == error("E_FRAC")'); + vrfy(conj("x") == error("E_CONJ"), '9722: conj("x") == error("E_CONJ")'); + vrfy(appr("x",.1) == error("E_APPR_1"), + '9723: appr("x",.1) == error("E_APPR_1")'); + vrfy(appr(1.27,.1i) == error("E_APPR_2"), + '9724: appr(1.27,.1i) == error("E_APPR_2")'); + vrfy(appr(1.27,.1,.1) == error("E_APPR_3"), + '9725: appr(1.27,.1,.1) == error("E_APPR_3")'); + vrfy(round("x") == error("E_ROUND_1"), + '9726: round("x") == error("E_ROUND_1")'); + vrfy(round(1.25,.1) == error("E_ROUND_2"), + '9727: round(1.25,.1) == error("E_ROUND_2")'); + vrfy(round(1.25,"x") == error("E_ROUND_2"), + '9728: round(1.25,"x") == error("E_ROUND_2")'); + vrfy(round(1.25,1,.1) == error("E_ROUND_3"), + '9729: round(1.25,1,.1) == error("E_ROUND_3")'); + vrfy(bround("x") == error("E_BROUND_1"), + '9730: bround("x") == error("E_BROUND_1")'); + vrfy(bround(1.25,.1) == error("E_BROUND_2"), + '9731: bround(1.25,.1) == error("E_BROUND_2")'); + vrfy(bround(1.25,"x") == error("E_BROUND_2"), + '9732: bround(1.25,"x") == error("E_BROUND_2")'); + vrfy(bround(1.25,1,.1) == error("E_BROUND_3"), + '9733: bround(1.25,1,.1) == error("E_BROUND_3")'); + vrfy(sqrt("x") == error("E_SQRT_1"), + '9734: sqrt("x") == error("E_SQRT_1")'); + vrfy(sqrt(2,"x") == error("E_SQRT_2"), + '9735: sqrt(2,"x") == error("E_SQRT_2")'); + vrfy(sqrt(2,0) == error("E_SQRT_2"), + '9736: sqrt(2,0) == error("E_SQRT_2")'); + vrfy(sqrt(2,.1,.1) == error("E_SQRT_3"), + '9737: sqrt(2,.1,.1) == error("E_SQRT_3")'); + vrfy(root("x",3) == error("E_ROOT_1"), + '9738: root("x",3) == error("E_ROOT_1")'); + vrfy(root(3,"x") == error("E_ROOT_2"), + '9739: root(3,"x") == error("E_ROOT_2")'); + vrfy(root(3,-2) == error("E_ROOT_2"), + '9740: root(3,-2) == error("E_ROOT_2")'); + vrfy(root(3,0) == error("E_ROOT_2"), + '9741: root(3,0) == error("E_ROOT_2")'); + vrfy(root(3,.1) == error("E_ROOT_2"), + '9742: root(3,.1) == error("E_ROOT_2")'); + vrfy(root(3,2,"x") == error("E_ROOT_3"), + '9743: root(3,2,"x") == error("E_ROOT_3")'); + vrfy(root(3,2,0) == error("E_ROOT_3"), + '9744: root(3,2,0) == error("E_ROOT_3")'); + vrfy(norm("x") == error("E_NORM"), '9745: norm("x") == error("E_NORM")'); + vrfy(list() << 2 == error("E_SHIFT_1"), '9746: list() << 2 == error("E_SHIFT_1")'); + vrfy(1.5 << 2 == error("E_SHIFT_1"), '9747: 1.5 << 2 == error("E_SHIFT_1")'); + vrfy(3 << "x" == error("E_SHIFT_2"), '9748: 3 << "x" == error("E_SHIFT_2")'); + vrfy(3 << 1.5 == error("E_SHIFT_2"), '9749: 3 << 1.5 == error("E_SHIFT_2")'); + vrfy(3 << 2^31 == error("E_SHIFT_2"), '9750: 3 << 2^31 == error("E_SHIFT_2")'); + vrfy(scale("x",2) == error("E_SCALE_1"), + '9751: scale("x",2) == error("E_SCALE_1")'); + vrfy(scale(3,"x") == error("E_SCALE_2"), + '9752: scale(3,"x") == error("E_SCALE_2")'); + vrfy(scale(3,1.5) == error("E_SCALE_2"), + '9753: scale(3,1.5) == error("E_SCALE_2")'); + vrfy(scale(3,2^31) == error("E_SCALE_2"), + '9754: scale(3,2^31) == error("E_SCALE_2")'); + vrfy("x" ^ 3 == error("E_POWI_1"), '9755: "x" ^ 3 == error("E_POWI_1")'); + vrfy(2 ^ "x" == error("E_POWI_2"), '9756: 2 ^ "x" == error("E_POWI_2")'); + vrfy(2 ^ "2" == error("E_POWI_2"), '9757: 2 ^ "2" == error("E_POWI_2")'); + vrfy(power("x",2.1) == error("E_POWER_1"), + '9758: power("x",2.1) == error("E_POWER_1")'); + vrfy(power(2,"x") == error("E_POWER_2"), + '9759: power(2,"x") == error("E_POWER_2")'); + vrfy(power(2,2.1,"x") == error("E_POWER_3"), + '9760: power(2,2.1,"x") == error("E_POWER_3")'); + vrfy(quo("x",3) == error("E_QUO_1"), + '9761: quo("x",3) == error("E_QUO_1")'); + vrfy(quo(8,"x") == error("E_QUO_2"), + '9762: quo(8,"x") == error("E_QUO_2")'); + vrfy(quo(8,3,"x") == error("E_QUO_3"), + '9763: quo(8,3,"x") == error("E_QUO_3")'); + vrfy(quo(8,3,2.1) == error("E_QUO_3"), + '9764: quo(8,3,2.1) == error("E_QUO_3")'); + vrfy(mod("x",3) == error("E_MOD_1"), + '9765: mod("x",3) == error("E_MOD_1")'); + vrfy(mod(8,"x") == error("E_MOD_2"), + '9766: mod(8,"x") == error("E_MOD_2")'); + vrfy(mod(8,3,"x") == error("E_MOD_3"), + '9767: mod(8,3,"x") == error("E_MOD_3")'); + vrfy(mod(8,3,2.1) == error("E_MOD_3"), + '9768: mod(8,3,2.1) == error("E_MOD_3")'); + vrfy(sgn("x") == error("E_SGN"), + '9769: sgn("x") == error("E_SGN")'); + vrfy(abs("x") == error("E_ABS_1"), + '9770: abs("x") == error("E_ABS_1")'); + vrfy(abs(2+3i,"x") == error("E_ABS_2"), + '9771: abs(2+3i,"x") == error("E_ABS_2")'); + vrfy(abs(2+3i,0) == error("E_ABS_2"), + '9772: abs(2+3i,0) == error("E_ABS_2")'); + list1 = list(2,3,"x",4,5); + print '9773: list1 = list(2,3,"x",4,5)'; + vrfy(avg(list1) == error("E_ADD"), + '9774: avg(list1) == error("E_ADD")'); + + vrfy(iserror(e99)==99, '9775: iserror(e99) == 99'); + vrfy(e99 + 2 == e99, '9776: e99 + 2 == e99'); + vrfy(e99 - 2 == e99, '9777: e99 - 2 == e99'); + vrfy(e99 * 2 == e99, '9778: e99 * 2 == e99'); + vrfy(e99 / 2 == e99, '9779: e99 / 2 == e99'); + vrfy(e99 // 2 == e99, '9780: e99 // 2 == e99'); + vrfy(e99 % 2 == e99, '9781: e99 % 2 == e99'); + vrfy(e99 ^ 2 == e99, '9782: e99 ^ 2 == e99'); + vrfy(2 + e99 == e99, '9783: 2 + e99 == e99'); + vrfy(2 - e99 == e99, '9784: 2 - e99 == e99'); + vrfy(2 * e99 == e99, '9785: 2 * e99 == e99'); + vrfy(2 / e99 == e99, '9786: 2 / e99 == e99'); + vrfy(2 // e99 == e99, '9787: 2 // e99 == e99'); + vrfy(2 % e99 == e99, '9788: 2 % e99 == e99'); + vrfy(2 ^ e99 == e99, '9789: 2 ^ e99 == e99'); + vrfy(- e99 == e99, '9790: -e99 == e99'); + vrfy(inverse(e99) == e99, '9791: inverse(e99) == e99'); + vrfy(++e99 == e99, '9792: ++e99 == e99'); + vrfy(--e99 == e99, '9793: --e99 == e99'); + vrfy(int(e99) == e99, '9794: int(e99) == e99'); + vrfy(frac(e99) == e99, '9795: frac(e99) == e99'); + vrfy(conj(e99) == e99, '9796: conj(e99) == e99'); + vrfy(norm(e99) == e99, '9797: norm(e99) == e99'); + vrfy(sgn(e99) == e99, '9798: sgn(e99) == e99'); + vrfy(appr(e99,1,0) == e99, '9799: appr(e99,1,0) == e99'); + vrfy(round(e99) == e99, '9800: round(e99) == e99'); + vrfy(bround(e99) == e99, '9801: bround(e99) == e99'); + vrfy(sqrt(e99) == e99, '9802: sqrt(e99) == e99'); + print '9803: a = newerror("alpha")'; + a = newerror("alpha"); + print '9804: b = newerror("beta")'; + b = newerror("beta"); + print '9805: c = newerror("alpha")'; + c = newerror("alpha"); + vrfy(a == c, '9806: a == c'); + vrfy(strerror(a) == "alpha", '9807: strerror(a) == "alpha"'); + print '9808: n = iserror(a)'; + n = iserror(a); + vrfy(a == error(n), '9809: a == error(n)'); + vrfy(newerror() == newerror("???"), + '9810: newerror() == newerror("???")'); + vrfy(newerror("") == newerror(), + '9811: newerror("") == newerror()'); + e9999 = error("E_9999"); + print '9812: e9999 = error("E_9999")'; + vrfy(errno() == 9999, '9813: errno() == 9999'); + vrfy(error() == e9999, '9814: error() == e9999'); + /* test 3715 removed due to non-portable strerror() output */ + x = newerror("Alpha"); + print '9816: x = newerror("Alpha")'; + n = iserror(x); + print '9817: n = iserror(x)'; + vrfy(errno() == n, '9818: errno() == n'); + vrfy(error() == x, '9819: error() == x'); + vrfy(strerror() == "Alpha", '9820: strerror() == "Alpha"'); + vrfy(errno("E_9999") == n, '9821: errno("E_9999") == n'); + vrfy(errno() == 9999, '9822: errno() == 9999'); + vrfy(error() == e9999, '9823: error() == e9999'); + /* test 3724 removed due to non-portable strerror() output */ + a = 1/0; + print '9825: a = 1/0'; + vrfy(strerror() == "Division by zero", + '9826: strerror() == "Division by zero"'); + n = 8191; + print '9827: n = 8191'; + print '9828: test removed due to non-portable strerror() output'; + vrfy(tan(2e9i) == error("E_TAN_5"), '9829: tan(2e9i) == error("E_TAN_5")'); + vrfy(cot(2e9i) == error("E_COT_6"), '9830: cot(2e9i) == error("E_COT_6")'); + vrfy(sec(2e9i) == error("E_SEC_5"), '9831: sec(2e9i) == error("E_SEC_5")'); + vrfy(csc(2e9i) == error("E_CSC_6"), '9832: csc(2e9i) == error("E_CSC_6")'); + + /* errmax and errcount should be bumped up the 148 errors above */ + print '9833: errcount():', errcount(); + print '9833: ecnt:', ecnt; + vrfy(errcount() == ecnt, '9835: errcount() == ecnt'); + + print '9836: Ending test_error'; +} +print; +print '9699: parsed test_error()'; + + +/* + * test 97dd + 98dd: test the error builtin + */ +print; +return test_error(); /* @@ -10649,6 +10808,37 @@ vrfy_errsym(10559, 10559, "E_HAVERSIN_3"); vrfy_errsym(10560, 10560, "E_AHAVERSIN_1"); vrfy_errsym(10561, 10561, "E_AHAVERSIN_2"); vrfy_errsym(10562, 10562, "E_AHAVERSIN_3"); +vrfy_errsym(10563, 10563, "E_HACOVERSIN_1"); +vrfy_errsym(10564, 10564, "E_HACOVERSIN_2"); +vrfy_errsym(10565, 10565, "E_HACOVERSIN_3"); +vrfy_errsym(10566, 10566, "E_AHACOVERSIN_1"); +vrfy_errsym(10567, 10567, "E_AHACOVERSIN_2"); +vrfy_errsym(10568, 10568, "E_AHACOVERSIN_3"); +vrfy_errsym(10569, 10569, "E_HAVERCOS_1"); +vrfy_errsym(10570, 10570, "E_HAVERCOS_2"); +vrfy_errsym(10571, 10571, "E_HAVERCOS_3"); +vrfy_errsym(10572, 10572, "E_AHAVERCOS_1"); +vrfy_errsym(10573, 10573, "E_AHAVERCOS_2"); +vrfy_errsym(10574, 10574, "E_AHAVERCOS_3"); +vrfy_errsym(10575, 10575, "E_HACOVERCOS_1"); +vrfy_errsym(10576, 10576, "E_HACOVERCOS_2"); +vrfy_errsym(10577, 10577, "E_HACOVERCOS_3"); +vrfy_errsym(10578, 10578, "E_AHACOVERCOS_1"); +vrfy_errsym(10579, 10579, "E_AHACOVERCOS_2"); +vrfy_errsym(10580, 10580, "E_AHACOVERCOS_3"); +vrfy_errsym(10581, 10581, "E_EXSEC_1"); +vrfy_errsym(10582, 10582, "E_EXSEC_2"); +vrfy_errsym(10583, 10583, "E_EXSEC_3"); +vrfy_errsym(10584, 10584, "E_AEXSEC_1"); +vrfy_errsym(10585, 10585, "E_AEXSEC_2"); +vrfy_errsym(10586, 10586, "E_AEXSEC_3"); +vrfy_errsym(10587, 10587, "E_EXCSC_1"); +vrfy_errsym(10588, 10588, "E_EXCSC_2"); +vrfy_errsym(10589, 10589, "E_EXCSC_3"); +vrfy_errsym(10590, 10590, "E_EXCSC_4"); +vrfy_errsym(10591, 10591, "E_AEXCSC_1"); +vrfy_errsym(10592, 10592, "E_AEXCSC_2"); +vrfy_errsym(10593, 10593, "E_AEXCSC_3"); /* ************************************************************** */ /* NOTE: Reserve thru test 10998 for calc computation error codes */ diff --git a/cal/test9500.trigeq.cal b/cal/test9500.trigeq.cal index fef00d6..a6d336b 100644 --- a/cal/test9500.trigeq.cal +++ b/cal/test9500.trigeq.cal @@ -1124,3 +1124,123 @@ define verify_hacovercos(testnum) } return error_count; } + + +/* + * verify_exsec - exterior trigonometric secant + * + * We use the following trigonometric identity: + * + * exsec(x) = sec(x) - 1 = (1 / cos(x)) - 1 + * + * given: + * testnum regression test number being performed + * + * returns: + * number of tests that failed + */ +define verify_exsec(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(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) { + + /* skip test when cos(x) within epsilon of 0 */ + if (not_near_zero(cos_tval[i])) { + + /* compute trigonometric identity */ + ident_val = (1 / cos_tval[i]) - 1; + + /* compute trigonometric function */ + trig_val = exsec(tval[i]); + + /* compare trigonometric identity with trigonometric function value */ + if (compare(ident_val, trig_val, "exsec", i, testnum)) { + ++error_count; + } + } + } + + /* + * report test results + */ + if (error_count != 0) { + print '**** test', testnum : ': exsec test failure count:', error_count; + } + return error_count; +} + + +/* + * verify_excsc - verify trigonometric cosecant + * + * We use the following trigonometric identity: + * + * excsc(x) = csc(x) - 1 = (1 / sin(x)) - 1 + * + * given: + * testnum regression test number being performed + * + * returns: + * number of tests that failed + */ +define verify_excsc(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(); + } + + /* + * for each test value, verify the trigonometric identity within epsilon + */ + tval_len = size(tval); + for (i=0; i < tval_len; ++i) { + + /* skip test when sin(x) within epsilon of 0 */ + if (not_near_zero(sin_tval[i])) { + + /* compute trigonometric identity */ + ident_val = (1 / sin_tval[i]) - 1; + + /* compute trigonometric function */ + trig_val = excsc(tval[i]); + + /* compare trigonometric identity with trigonometric function value */ + if (compare(ident_val, trig_val, "excsc", i, testnum)) { + ++error_count; + } + } + } + + /* + * report test results + */ + if (error_count != 0) { + print '**** test', testnum : ': excsc test failure count:', error_count; + } + return error_count; +} diff --git a/cmath.h b/cmath.h index e069435..9417bbb 100644 --- a/cmath.h +++ b/cmath.h @@ -144,6 +144,10 @@ E_FUNC COMPLEX *c_havercos(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_ahavercos(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_hacovercos(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_ahacovercos(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_exsec(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_aexsec(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_excsc(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_aexcsc(COMPLEX *c, NUMBER *epsilon); diff --git a/comfunc.c b/comfunc.c index a709530..d2cbc27 100644 --- a/comfunc.c +++ b/comfunc.c @@ -2425,3 +2425,195 @@ c_ahacovercos(COMPLEX *c, NUMBER *epsilon) */ return r; } + + +/* + * c_exsec - COMPLEX valued exterior trigonometric secant + * + * This uses the formula: + * + * exsec(x) = sec(x) - 1 + * + * 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_exsec(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* return COMPLEX value */ + COMPLEX *ctmp; /* complex sec(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_sec(c, epsilon); + if (ctmp == NULL) { + math_error("Failed to compute complex cosine for complex exsec"); + not_reached(); + } + r = c_sub(ctmp, &_cone_); + comfree(ctmp); + + /* + * return trigonometric result + */ + return r; +} + + +/* + * c_aexsec - COMPLEX valued inverse exterior trigonometric secant + * + * This uses the formula: + * + * aexsec(x) = asec(x + 1) + * + * 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_aexsec(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* inverse trig value result */ + COMPLEX *ctmp; /* 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 + */ + ctmp = c_addq(c, &_qone_); + r = c_asec(ctmp, epsilon); + comfree(ctmp); + + /* + * return inverse trigonometric result + */ + return r; +} + + +/* + * c_excsc - COMPLEX valued exterior trigonometric cosecant + * + * This uses the formula: + * + * excsc(x) = csc(x) - 1 + * + * 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_excsc(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* return COMPLEX value */ + COMPLEX *ctmp; /* complex sin(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_csc(c, epsilon); + if (ctmp == NULL) { + math_error("Failed to compute complex sine for complex excsc"); + not_reached(); + } + r = c_sub(ctmp, &_cone_); + comfree(ctmp); + + /* + * return trigonometric result + */ + return r; +} + + +/* + * c_aexcsc - COMPLEX valued inverse exterior trigonometric cosecant + * + * This uses the formula: + * + * aexcsc(x) = acsc(x + 1) + * + * 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_aexcsc(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *r; /* inverse trig value result */ + COMPLEX *ctmp; /* 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 + */ + ctmp = c_addq(c, &_qone_); + r = c_acsc(ctmp, epsilon); + comfree(ctmp); + + /* + * return inverse trigonometric result + */ + return r; +} diff --git a/errtbl.c b/errtbl.c index 9ef2628..76b50c9 100644 --- a/errtbl.c +++ b/errtbl.c @@ -689,7 +689,7 @@ CONST struct errtbl error_table[] = { { 10538, "E_COT_5", "Invalid zero argument for cot" }, { 10539, "E_COT_6", "Invalid complex argument for cot" }, { 10540, "E_SEC_5", "Invalid complex argument for sec" }, - { 10541, "E_CSC_5", "Invalid zero argument for cot" }, + { 10541, "E_CSC_5", "Invalid zero argument for csc" }, { 10542, "E_CSC_6", "Invalid complex argument for csc" }, { 10543, "E_ERROR_3", "String argument is not a valid E_STRING for error" }, { 10544, "E_ERROR_4", "Numeric argument is not an integer for error" }, @@ -729,6 +729,19 @@ CONST struct errtbl error_table[] = { { 10578, "E_AHACOVERCOS_1", "Bad epsilon for ahacovercos" }, { 10579, "E_AHACOVERCOS_2", "Bad first argument for achaovercos" }, { 10580, "E_AHACOVERCOS_3", "Too-large im(argument) for ahacovercos" }, + { 10581, "E_EXSEC_1", "Bad epsilon for exsec" }, + { 10582, "E_EXSEC_2", "Bad argument for exsec" }, + { 10583, "E_EXSEC_3", "Invalid complex argument for exsec" }, + { 10584, "E_AEXSEC_1", "Bad epsilon for aexsec" }, + { 10585, "E_AEXSEC_2", "Bad argument for aexsec" }, + { 10586, "E_AEXSEC_3", "Invalid value for calculating aexsec" }, + { 10587, "E_EXCSC_1", "Bad epsilon for excsc" }, + { 10588, "E_EXCSC_2", "Bad argument for excsc" }, + { 10589, "E_EXCSC_3", "Invalid zero argument for excsc" }, + { 10590, "E_EXCSC_4", "Invalid complex argument for excsc" }, + { 10591, "E_AEXCSC_1", "Bad epsilon for aexcsc" }, + { 10592, "E_AEXCSC_2", "Bad argument for aexcsc" }, + { 10593, "E_AEXCSC_3", "Invalid value for calculating aexcsc" }, /* 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 4d7726e..48ccc7b 100644 --- a/func.c +++ b/func.c @@ -3209,6 +3209,7 @@ f_csc(int count, VALUE **vals) return result; } + S_FUNC VALUE f_sinh(int count, VALUE **vals) { @@ -11940,6 +11941,284 @@ f_ahacovercos(int count, VALUE **vals) } +/* + * f_exsec - exterior trigonometric secant + */ +S_FUNC VALUE +f_exsec(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_EXSEC_1); + } + err = vals[1]->v_num; + } + + /* + * compute exterior trigonometric secant to a given error tolerance + */ + switch (vals[0]->v_type) { + case V_NUM: + result.v_num = qexsec(vals[0]->v_num, err); + result.v_type = V_NUM; + break; + case V_COM: + c = c_exsec(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_EXSEC_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_EXSEC_2); + } + return result; +} + + +/* + * f_aexsec - inverse exterior trigonometric secant + */ +S_FUNC VALUE +f_aexsec(int count, VALUE **vals) +{ + VALUE arg1; /* 1st arg if it is a COMPLEX value */ + VALUE result; /* value to return */ + COMPLEX *c; /* COMPLEX trig result */ + NUMBER *eps; /* epsilon error tolerance */ + + /* 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_AEXSEC_1); + } + eps = vals[1]->v_num; + } + + /* + * compute inverse trig function to a given error tolerance + */ + arg1 = *vals[0]; + if (arg1.v_type == V_NUM) { + + /* try to compute result using real trig function */ + result.v_num = qaexsec_or_NULL(arg1.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 */ + arg1.v_com = qqtoc(arg1.v_num, &_qzero_); + arg1.v_type = V_COM; + } + } + if (arg1.v_type == V_COM) { + + /* + * case: argument was COMPLEX or + * trig function returned NULL and argument was converted to COMPLEX + */ + c = c_aexsec(arg1.v_com, eps); + if (c == NULL) { + return error_value(E_AEXSEC_3); + } + 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 = c_to_q(c, true); + result.v_type = V_NUM; + } + } + if (arg1.v_type != V_NUM && arg1.v_type != V_COM) { + + /* + * case: argument type is not valid for this function + */ + return error_value(E_AEXSEC_2); + } + return result; +} + + +/* + * f_excsc - exterior trigonometric cosecant + */ +S_FUNC VALUE +f_excsc(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_EXCSC_1); + } + err = vals[1]->v_num; + } + + /* + * compute cosecant to a given error tolerance + */ + switch (vals[0]->v_type) { + case V_NUM: + if (qiszero(vals[0]->v_num)) { + return error_value(E_EXCSC_3); + } + result.v_num = qexcsc(vals[0]->v_num, err); + result.v_type = V_NUM; + break; + case V_COM: + if (ciszero(vals[0]->v_com)) { + return error_value(E_EXCSC_3); + } + c = c_excsc(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_EXCSC_4); + } + 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_EXCSC_2); + } + return result; +} + + +/* + * f_aexcsc - exterior trigonometric cosecant + */ +S_FUNC VALUE +f_aexcsc(int count, VALUE **vals) +{ + VALUE arg1; /* 1st arg if it is a COMPLEX value */ + VALUE result; /* value to return */ + COMPLEX *c; /* COMPLEX trig result */ + NUMBER *eps; /* epsilon error tolerance */ + + /* 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_AEXCSC_1); + } + eps = vals[1]->v_num; + } + + /* + * compute inverse trig function to a given error tolerance + */ + arg1 = *vals[0]; + if (arg1.v_type == V_NUM) { + + /* try to compute result using real trig function */ + result.v_num = qaexcsc_or_NULL(arg1.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 */ + arg1.v_com = qqtoc(arg1.v_num, &_qzero_); + arg1.v_type = V_COM; + } + } + if (arg1.v_type == V_COM) { + + /* + * case: argument was COMPLEX or + * trig function returned NULL and argument was converted to COMPLEX + */ + c = c_aexcsc(arg1.v_com, eps); + if (c == NULL) { + return error_value(E_AEXCSC_3); + } + 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 = c_to_q(c, true); + result.v_type = V_NUM; + } + } + if (arg1.v_type != V_NUM && arg1.v_type != V_COM) { + + /* + * case: argument type is not valid for this function + */ + return error_value(E_AEXCSC_2); + } + return result; +} + + #endif /* !FUNCLIST */ @@ -12000,6 +12279,10 @@ STATIC CONST struct builtin builtins[] = { "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"}, + {"aexcsc", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_aexcsc}, + "inverse exterior cosecant of a within accuracy b"}, + {"aexsec", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_aexsec}, + "inverse exterior secant of a within accuracy b"}, {"agd", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_agd}, "inverse Gudermannian function"}, {"ahacovercos", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_ahacovercos}, @@ -12157,8 +12440,12 @@ STATIC CONST struct builtin builtins[] = { "Euler number"}, {"eval", 1, 1, 0, OP_NOP, {.null = NULL}, {.valfunc_1 = f_eval}, "evaluate expression from string to value"}, + {"excsc", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_excsc}, + "exterior cosecant of a within accuracy b"}, {"exp", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_exp}, "exponential of value a within accuracy b"}, + {"exsec", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_exsec}, + "exterior secant of a within accuracy b"}, {"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}, @@ -12575,7 +12862,7 @@ STATIC CONST struct builtin builtins[] = { "search matrix or list for value b starting\n" "\t\t\tat index c"}, {"sec", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_sec}, - "sec of a within accuracy b"}, + "secant of a within accuracy b"}, {"sech", 1, 2, 0, OP_NOP, {.null = NULL}, {.valfunc_cnt = f_sech}, "hyperbolic secant of a within accuracy b"}, {"seed", 0, 0, 0, OP_NOP, {.numfunc_0 = f_seed}, {.null = NULL}, diff --git a/help/acos b/help/acos index eb770ca..9e81eda 100644 --- a/help/acos +++ b/help/acos @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2023 Landon Curt Noll diff --git a/help/acot b/help/acot index 664bacc..473ffdd 100644 --- a/help/acot +++ b/help/acot @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/acovercos b/help/acovercos index f97540c..bc35eab 100644 --- a/help/acovercos +++ b/help/acovercos @@ -52,6 +52,7 @@ SEE ALSO aversin, acoversin, avercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/acoversin b/help/acoversin index 63db895..8ba749f 100644 --- a/help/acoversin +++ b/help/acoversin @@ -52,6 +52,7 @@ SEE ALSO aversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/acsc b/help/acsc index 50fb12d..7fd99c8 100644 --- a/help/acsc +++ b/help/acsc @@ -56,6 +56,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/aexcsc b/help/aexcsc new file mode 100644 index 0000000..d5811ac --- /dev/null +++ b/help/aexcsc @@ -0,0 +1,84 @@ +NAME + aexcsc - inverse exterior trigonometric cosecant + +SYNOPSIS + aexcsc(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return real + +DESCRIPTION + Returns the inverse exterior trigonometric cscant of x to a multiple of eps with error less in + absolute value than .75 * eps. + + This function is sometimes called arcexcsc, is equivalent to: + + aexcsc(x) = acsc(x + 1) + +EXAMPLE + ; print aexcsc(0), aexcsc(0.5), aexcsc(1) + 1.57079632679489661923 0.72972765622696636345 0.52359877559829887308 + + ; print aexcsc(-0.5), aexcsc(-1) + 1.57079632679489661923-1.31695789692481670863i Error 10454 + + ; print aexcsc(.5, 1e-5), aexcsc(.5, 1e-10), aexcsc(.5, 1e-15) + 0.72973 0.7297276562 0.729727656226966 + + ; print aexcsc(.5, 1e-20) + 0.72972765622696636345 + + ; print aexcsc(5), aexcsc(5i) + 0.16744807921968933055 0.03777750167037411869-0.19127650074191792629i + + ; print aexcsc(5+5i) + 0.09818639956668015454-0.08227107131216428877i + + ; pi = pi(1e-20) + ; print aexcsc(pi/6), aexcsc(pi/3) + 0.7159583700300961063 0.51033850088317613655 + + ; print aexcsc(4*pi/3) + 0.19393657131001704582 + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qaexcsc(NUMBER *x, NUMBER *eps) + COMPLEX *c_aexcsc(COMPLEX *c, NUMBER *epsilon) + +SEE ALSO + sin, 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 + 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/30 23:22:21 +## 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/aexsec b/help/aexsec new file mode 100644 index 0000000..7756fab --- /dev/null +++ b/help/aexsec @@ -0,0 +1,81 @@ +NAME + aexsec - inverse exterior trigonometric secant + +SYNOPSIS + aexsec(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return real + +DESCRIPTION + Returns the inverse trigonometric secant of x to a multiple of eps with error less in + absolute value than .75 * eps. + + This function is sometimes called arcexsec, is equivalent to: + + aexsec(x) = asec(x + 1) + +EXAMPLE + ; print aexsec(0), aexsec(0.5), aexsec(1) + 0 0.84106867056793025578 1.04719755119659774615 + + ; print aexsec(-0.5), aexsec(-1) + 1.31695789692481670863i Error 10453 + + ; print aexsec(.5, 1e-5), aexsec(.5, 1e-10), aexsec(.5, 1e-15), aexsec(.5, 1e-20) + 0.84107 0.8410686706 0.84106867056793 0.84106867056793025578 + + ; print aexsec(5), aexsec(5i) + 1.40334824757520728868 1.53301882512452250055+0.1912765007419179263i + + ; print aexsec(5+5i) + 1.4726099272282164647+0.08227107131216428876i + + ; pi = pi(1e-20) + ; print aexsec(pi/6), aexsec(pi/3) + 0.85483795676480051293 1.06045782591172048268 + + ; print aexsec(4*pi/3) + 1.37685975548487957341 + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qaexsec(NUMBER *x, NUMBER *eps) + COMPLEX *c_aexsec(COMPLEX *c, NUMBER *epsilon) + +SEE ALSO + sin, 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, excsc, aexcsc + 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/10/01 00:20:20 +## 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/ahacovercos b/help/ahacovercos index d42184c..0fe52b4 100644 --- a/help/ahacovercos +++ b/help/ahacovercos @@ -55,6 +55,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/ahacoversin b/help/ahacoversin index 7440f20..2977ed3 100644 --- a/help/ahacoversin +++ b/help/ahacoversin @@ -55,6 +55,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/ahavercos b/help/ahavercos index 61cc821..d1293b8 100644 --- a/help/ahavercos +++ b/help/ahavercos @@ -56,6 +56,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/ahaversin b/help/ahaversin index 6a129a4..43af234 100644 --- a/help/ahaversin +++ b/help/ahaversin @@ -56,6 +56,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/asec b/help/asec index 0b5f210..45532e8 100644 --- a/help/asec +++ b/help/asec @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/asin b/help/asin index a19946c..1de8bf1 100644 --- a/help/asin +++ b/help/asin @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/atan b/help/atan index ed0399d..1dd338d 100644 --- a/help/atan +++ b/help/atan @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2023 Landon Curt Noll diff --git a/help/avercos b/help/avercos index 4b01396..31163d4 100644 --- a/help/avercos +++ b/help/avercos @@ -53,6 +53,7 @@ SEE ALSO aversin, acoversin, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/aversin b/help/aversin index 11d78ac..5fc626c 100644 --- a/help/aversin +++ b/help/aversin @@ -53,6 +53,7 @@ SEE ALSO acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/cos b/help/cos index 4ddff01..c7ad9ed 100644 --- a/help/cos +++ b/help/cos @@ -42,6 +42,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/cot b/help/cot index f40e104..903e834 100644 --- a/help/cot +++ b/help/cot @@ -32,7 +32,7 @@ EXAMPLE ; print cot(pi/6), cot(pi/2), cot(pi) 1.73205080756887729353 0 -378303066284076833726.92240766640467212978 - ; # NOTE: The huge value for cot(pi) is due to the fact that pi is not exact. + ; # NOTE: The huge value for cot(pi) is because the pi variable is not exactly pi. LIMITS 0 < eps < 1 @@ -48,6 +48,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/covercos b/help/covercos index 547c165..ea0d0e1 100644 --- a/help/covercos +++ b/help/covercos @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/coversin b/help/coversin index f639c11..a86a7e4 100644 --- a/help/coversin +++ b/help/coversin @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/csc b/help/csc index c0ae382..7461b65 100644 --- a/help/csc +++ b/help/csc @@ -32,7 +32,7 @@ EXAMPLE ; print csc(pi/6), csc(pi/2), csc(pi) 2 1 378303066284076833726.92240766640467212978 - ; # NOTE: The huge value for csc(pi) is because pi, as calculated, is not exact. + ; # NOTE: The huge value for csc(pi) is because the pi variable is not exactly pi. LIMITS 0 < eps < 1 @@ -48,6 +48,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2023 Landon Curt Noll diff --git a/help/excsc b/help/excsc new file mode 100644 index 0000000..e217e8f --- /dev/null +++ b/help/excsc @@ -0,0 +1,74 @@ +NAME + excsc - exterior trigonometric secant + +SYNOPSIS + excsc(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return real + +DESCRIPTION + Calculate the exterior trigonometric secant of x to a multiple of eps, with error less + in absolute value than .75 * eps. + + This function is equivalent to: + + excsc(x) = csc(x) - 1 + +EXAMPLE + ; print excsc(1/2), excsc(5/7), excsc(42/7) + 1.08582964293348818577 0.52653601091884339347 -4.57889954725440563736 + + ; print excsc(1, 1e-5), excsc(1, 1e-10), excsc(1, 1e-15), excsc(1, 1e-20) + 0.1884 0.1883951058 0.188395105778121 0.18839510577812121626 + + ; print excsc(2 + 3i, 1e-5), excsc(2 + 3i, 1e-10) + ~-0.90952681844549563690+~0.04120099965201690801i ~-0.90952679024696767497+~0.04120098628887626238i + + ; pi = pi(1e-20) + ; print excsc(pi/6), excsc(pi/2), excsc(pi) + 1 0 378303066284076833725.92240766640467212978 + + ; # NOTE: The huge value for excsc(pi) is because the pi variable is not exactly pi. + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qexcsc(NUMBER *x, NUMBER *eps) + COMPLEX *c_excsc(COMPLEX *c, NUMBER *eps) + +SEE ALSO + sin, 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, aexcsc + 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/30 23:19:00 +## 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/exsec b/help/exsec new file mode 100644 index 0000000..41fac6a --- /dev/null +++ b/help/exsec @@ -0,0 +1,74 @@ +NAME + exsec - exterior trigonometric secant + +SYNOPSIS + exsec(x [,eps]) + +TYPES + x number (real or complex) + eps 0 < real < 1, defaults to epsilon() + + return real + +DESCRIPTION + Calculate the exterior trigonometric secant of x to a multiple of eps, with error less + in absolute value than .75 * eps. + + This function is equivalent to: + + exsec(x) = sec(x) - 1 + +EXAMPLE + ; print exsec(1/2), exsec(5/7), exsec(42/7) + 0.13949392732454912231 0.3235192673191814545 0.04148192659510767648 + + ; print exsec(1, 1e-5), exsec(1, 1e-10), exsec(1, 1e-15), exsec(1, 1e-20) + 0.85082 0.8508157177 0.850815717680926 0.85081571768092561791 + + ; print exsec(2 + 3i, 1e-5), exsec(2 + 3i, 1e-10) + ~-1.04167497639869547021+~0.09061109101765280898i ~-1.04167496441100888150+~0.09061113719571288336i + + ; pi = pi(1e-20) + ; print exsec(pi/6), exsec(pi/2), exsec(pi) + 0.15470053837925152902 756606132568153667452.84481533280934425956 -2 + + ; # NOTE: The huge value for exsec(pi/2) is because the pi variable is not exactly pi. + +LIMITS + 0 < eps < 1 + +LINK LIBRARY + NUMBER *qexsec(NUMBER *x, NUMBER *eps) + COMPLEX *c_exsec(COMPLEX *c, NUMBER *eps) + +SEE ALSO + sin, 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 + aexsec, excsc, aexcsc + 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/10/01 00:19:00 +## 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/hacovercos b/help/hacovercos index 1bed198..79c6e4d 100644 --- a/help/hacovercos +++ b/help/hacovercos @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/hacoversin b/help/hacoversin index 7826a44..8c9a151 100644 --- a/help/hacoversin +++ b/help/hacoversin @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/havercos b/help/havercos index d007618..558ff48 100644 --- a/help/havercos +++ b/help/havercos @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/haversin b/help/haversin index fc93772..5812cc2 100644 --- a/help/haversin +++ b/help/haversin @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/sec b/help/sec index 3953cbc..108dd58 100644 --- a/help/sec +++ b/help/sec @@ -32,7 +32,7 @@ EXAMPLE ; print sec(pi/6), sec(pi/2), sec(pi) 1.15470053837925152902 756606132568153667453.84481533280934425956 -1 - ; # NOTE: The huge value for sec(pi/2) is because pi, as calculated, is not exact. + ; # NOTE: The huge value for sec(pi/2) is because the pi variable is not exactly pi. LIMITS 0 < eps < 1 @@ -48,6 +48,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2023 Landon Curt Noll diff --git a/help/sin b/help/sin index 216ad63..a15ff22 100644 --- a/help/sin +++ b/help/sin @@ -42,6 +42,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2021,2023 Landon Curt Noll diff --git a/help/tan b/help/tan index 65b72d7..6d40e73 100644 --- a/help/tan +++ b/help/tan @@ -32,7 +32,7 @@ EXAMPLE ; print tan(pi/6), tan(pi/2), tan(pi) 0.57735026918962576451 756606132568153667453.84481533280934425956 0 - ; # NOTE: The huge value for tan(pi/2) is due to the fact that pi is not exact. + ; # NOTE: The huge value for tan(pi/2) is because the pi variable is not exactly pi. LIMITS 0 < eps < 1 @@ -48,6 +48,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 1999,2023 Landon Curt Noll diff --git a/help/vercos b/help/vercos index 35a7adf..333bfbb 100644 --- a/help/vercos +++ b/help/vercos @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/help/versin b/help/versin index dcfd027..7742871 100644 --- a/help/versin +++ b/help/versin @@ -46,6 +46,7 @@ SEE ALSO aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos + exsec, aexsec, excsc, aexcsc epsilon ## Copyright (C) 2023 Landon Curt Noll diff --git a/qmath.h b/qmath.h index 7c8e369..acdbc4f 100644 --- a/qmath.h +++ b/qmath.h @@ -250,6 +250,12 @@ E_FUNC NUMBER *qahavercos(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qhacovercos(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qahacovercos_or_NULL(NUMBER *q, NUMBER *epsilon); E_FUNC NUMBER *qahacovercos(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qexsec(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaexsec_or_NULL(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaexsec(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qexcsc(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaexcsc_or_NULL(NUMBER *q, NUMBER *epsilon); +E_FUNC NUMBER *qaexcsc(NUMBER *q, NUMBER *epsilon); /* * pseudo-seed generator diff --git a/qtrans.c b/qtrans.c index fb73bad..21cd3c2 100644 --- a/qtrans.c +++ b/qtrans.c @@ -3170,3 +3170,300 @@ qahacovercos(NUMBER *q, NUMBER *epsilon) */ return res; } + + +/* + * qexsec - exterior trigonometric secant + * + * This uses the formula: + * + * exsec(x) = sec(x) - 1 + * + * 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 * +qexsec(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *qtmp; /* 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 trig function value + */ + qtmp = qsec(q, epsilon); + res = qsub(qtmp, &_qone_); + qfree(qtmp); + + /* + * return trigonometric result + */ + return res; +} + + +/* + * qaexsec_or_NULL - return NULL or non-complex inverse versed trigonometric sine + * + * This uses the formula: + * + * aexsec(x) = asec(x + 1) + * + * 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 * +qaexsec_or_NULL(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *qtmp; /* 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 + */ + qtmp = qaddi(q, 1); + res = qasec(qtmp, epsilon); + qfree(qtmp); + if (res == NULL) { + return NULL; + } + + /* + * return inverse trigonometric result + */ + return res; +} + + +/* + * qaexsec - non-complex inverse versed trigonometric sine + * + * This uses the formula: + * + * aexsec(x) = asec(x + 1) + * + * 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 * +qaexsec(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 = qaexsec_or_NULL(q, epsilon); + if (res == NULL) { + math_error("cannot compute inverse cosine for aexsec"); + not_reached(); + } + + /* + * return inverse trigonometric result + */ + return res; +} + + +/* + * qexcsc - coversed trigonometric sine + * + * This uses the formula: + * + * excsc(x) = csc(x) - 1 + * + * 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 * +qexcsc(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *qtmp; /* 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 trig function value + */ + qtmp = qcsc(q, epsilon); + res = qsub(qtmp, &_qone_); + qfree(qtmp); + + /* + * return trigonometric result + */ + return res; +} + + +/* + * qaexcsc_or_NULL - return NULL or non-complex inverse coversed trigonometric sine + * + * This uses the formula: + * + * aexcsc(x) = acsc(x + 1) + * + * 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 * +qaexcsc_or_NULL(NUMBER *q, NUMBER *epsilon) +{ + NUMBER *res; /* inverse trig value result */ + NUMBER *qtmp; /* 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 + */ + qtmp = qaddi(q, 1); + res = qacsc(qtmp, epsilon); + qfree(qtmp); + if (res == NULL) { + return NULL; + } + + /* + * return inverse trigonometric result + */ + return res; +} + + +/* + * qaexcsc - non-complex inverse coversed trigonometric sine + * + * This uses the formula: + * + * aexcsc(x) = acsc(x + 1) + * + * 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 * +qaexcsc(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 = qaexcsc_or_NULL(q, epsilon); + if (res == NULL) { + math_error("cannot compute inverse sine for aexcsc"); + not_reached(); + } + + /* + * return inverse trigonometric result + */ + return res; +}