/* * test9500.trigeq - test of trigonometric identities for test 95dd * * We test over a wide variety of real (NUMBER) and complex (COMPLEX) * values, that various trigonometric identities hold for all calc * builtin trigonometric functions. * * We assume that the value produced by sin() (trigonometric sine) * and cos() (trigonometric cosine) are correct. We can reasonably * assume this because of the calc regression test suite: * * (such as test 34dd and in particular cal/test3400.trig.cal and * such as test 89dd and in particular cal/test8900.special.cal) * * will test such those function beforehand. * * We use various trigonometric identity to verify the non-inverse * trigonometric functions other than sin() and cos(). * * we verify that it is true within the error tolerance of the eps * (epsilon) argument. * * Copyright (C) 2023 Landon Curt Noll * * Primary author: 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/10 14:33:06 * File existed as early as: 2023 * * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */ /* * base_tval - base set of test values * * Our 16 base test values must be > 0 and <= 1. * We use these fractions because, when multiplied * by pi() will give values that are commonly used. * * NOTE: There is no reason to sort these values other than ascetics. :-) */ static base_tval = list( 1/12, /* ~ 0.08333333333333333333 */ 1/8, /* 0.12500000000000000000 */ 1/6, /* ~ 0.16666666666666666667 */ 1/5, /* 0.20000000000000000000 */ 1/4, /* 0.25000000000000000000 */ 1/3, /* ~ 0.33333333333333333333 */ 3/8, /* 0.37500000000000000000 */ 5/12, /* ~ 0.41666666666666666667 */ 1/2, /* 0.50000000000000000000 */ 2/3, /* ~ 0.66666666666666666667 */ 3/4, /* 0.75000000000000000000 */ 4/5, /* 0.80000000000000000000 */ 5/6, /* ~ 0.83333333333333333333 */ 7/8, /* 0.87500000000000000000 */ 11/12, /* ~ 0.91666666666666666667 */ 1 /* 1.00000000000000000000 */ ); /* * tval - full test list * * This long list is formed via the form_tval() function from the base_tval list. * * When the form_tval() function forms the full test test values * we will have 1025 values of various real and complex * values that also include random values added or subtracted. * * See the form_tval() function for details. */ tval = list(); /* * Lists that hold precomputed trigonometric functions on the tval full test list * * The precompute_trig() function will fill out these lists. * They will be the same size as size as the full test list. */ sin_tval = list(); /* trigonometric sine of each test test value */ cos_tval = list(); /* trigonometric cosine of each test test value */ /* * seed_rand - seed the subtractive 100 shuffle pseudo-random number generator * * We want to seed the subtractive 100 shuffle pseudo-random number generator * with a constant so that the result of this test set will be deterministic. * * We seed the subtractive 100 shuffle pseudo-random number generator with * a 128-bit seed value. The 128-bit seed value was produced when a * Blum-Blum-Shub pseudo-random number generator was seeded with the * following 160-bit SHA1 hash of 3 calls to seed(): * * sha1(sha1(seed(), seed()<<64, seed()<<128)) == 0x732fda50b1bf6e34b604b7c75b993e5c37a4ad97 * * This produced the following 160-bit value that was used to seed * the Blum-Blum-Shub pseudo-random number: * * srandom(0x732fda50b1bf6e34b604b7c75b993e5c37a4ad97) * * The seeded Blum-Blum-Shub pseudo-random number generator was then * used to generate a 128-bit value: * * randombit(128) == 0x37301cf47204f7fababc2f32e39ab338 * * We seed the subtractive 100 shuffle pseudo-random number generator * with the above mentioned 128-bit value: * * srand(0x37301cf47204f7fababc2f32e39ab338) */ define seed_rand() { return srand(0x37301cf47204f7fababc2f32e39ab338); } /* * epsilon_bits - number of bits in epsilon() */ static epsilon_bits = highbit(1/epsilon()) + 1; /* * epsilon_norm - norm of a epsilon() */ static epsilon_norm = norm(epsilon()); /* * random_rational_value - compute a random rational value > 0 and < 1 * * We compute a pseudo-random value in the range (0,1) with a prevision of epsilon(). * * We compute two distinct non-zero pseudo-random integers (i.e., > 0), a and b, * that are epsilon_bits (see above) long and produced by the seeded * subtractive 100 shuffle pseudo-random number generator (see seed_rand()). * * Return the smaller of a,b divided by the larger of a,b. */ define random_rational_value() { local a; /* epsilon_bits pseudo-random integer > 0 */ local b; /* epsilon_bits pseudo-random integer > 0 */ /* * compute 1st non-zero pseudo-random epsilon_bits integer */ do { a = randbit(epsilon_bits); } while (a == 0); /* * compute 2nd non-zero pseudo-random epsilon_bits integer also != a */ do { b = randbit(epsilon_bits); } while (b == 0 || a == b); /* * return the min(a,b) / max(a,b): a value > 0 and < 1 */ return min(a,b) / max(a,b); } /* * form_tval - form a full list of test values * * Given an initial list of 16 values, we form 1025 test values. * * From the test set starts with 16 values from the base_tval[] list: * * tval = base_tval; * * We form a list of 32 values by appending all of the above with: * * tval[i] + 1 * * We form a list of 64 values by appending all of the above with: * * -tval[i] * * We form a list of 128 values by appending all of the above with: * * For values >= 0: tval[i] + random_rational_value * For values < 0: tval[i] - random_rational_value * * We form a list of 256 values by appending all of the above with: * * tval[i] * pi() * * We form a list of 512 values by appending all of the above with: * * tval[i] * 1i * * We for a list of 1024 values by appending new complex values where the * real part is a randomly selected real value (from the first 256 list values), and the * imaginary part is a randomly selected complex value (from the last 256 list values). * * Finally we append 0 to the list to form the full 1025 value list. */ define form_tval() { local tval_len; /* current length of the tval[] array */ local real_cnt; /* number of real values in tval[] array */ local imag_cnt; /* number of imaginary values in tval[] array */ local i; /* * seed the subtractive 100 shuffle pseudo-random number generator */ seed_rand(); /* * load base_tval[] array into tval[] array */ tval = base_tval; /* * expand all tval with tval+1 */ tval_len = size(tval); for (i=0; i < tval_len; ++i) { append(tval, tval[i] + 1); } /* * expand all tval with -tval */ tval_len = size(tval); for (i=0; i < tval_len; ++i) { append(tval, -tval[i]); } /* * expand all tval with tval +/- random_rational_value * * For values we add random_rational_value if > 0 * or we subtract crandom_rational_value if < 0. */ tval_len = size(tval); for (i=0; i < tval_len; ++i) { /* use the sign to determine if we add or subtract */ if (tval[i] >= 0) { append(tval, tval[i] + random_rational_value()); } else { append(tval, tval[i] - random_rational_value()); } } /* * expand all tval with tval * pi() */ tval_len = size(tval); for (i=0; i < tval_len; ++i) { append(tval, tval[i] * pi()); } /* * expand all tval with tval * 1i */ tval_len = size(tval); /* tval[0] thru tval[real_cnt-1] are real values */ real_cnt = tval_len; for (i=0; i < tval_len; ++i) { append(tval, tval[i] * 1i); } /* * expand tval with randomly selected real value * plus randomly selected complex value. */ tval_len = size(tval); /* tval[real_cnt] thru tval[real_cnt+imag_cnt-1] are complex values */ imag_cnt = tval_len - real_cnt; for (i=0; i < tval_len; ++i) { append(tval, tval[rand(0,real_cnt)] + tval[real_cnt + rand(0,imag_cnt)]); } /* * last, append our final 0 value */ append(tval, 0); } /* * compute - form precomputed trigonometric value lists */ define precompute_trig() { local tval_len; /* current length of the tval[] array */ local i; /* * firewall - be sure tval list is setup */ if (size(tval) <= 0) { form_tval(); } tval_len = size(tval); if (tval_len <= 0) { quit "FATAL: tval_len is empty"; } /* * compute trigonometric sine of the tval full test list */ for (i=0; i < tval_len; ++i) { append(sin_tval, sin(tval[i])); } if (size(tval) != size(sin_tval)) { print "****: size(tval):", size(tval), "!= size(sin_tval)", size(sin_tval); quit "FATAL: sin_tval not same size as tval_len"; } /* * compute trigonometric cosine of the tval full test list */ for (i=0; i < tval_len; ++i) { append(cos_tval, cos(tval[i])); } if (size(tval) != size(cos_tval)) { print "****: size(tval):", size(tval), "!= size(cos_tval)", size(cos_tval); quit "FATAL: cos_tval not same size as tval_len"; } } /* * compare - compare the trigonometric identity and the trigonometric function value * * given: * ident_val computed trig value trigonometric identity * trig_val computed value from the trigonometric function * name trig function name * index test index value * testnum regression test number being performed * * returns: * 0 ==> trigonometric identity and the trigonometric function value match * 1 ==> trigonometric identity and the trigonometric function value do NOT match */ define compare(ident_val, trig_val, name, index, testnum) { local abs_diff; /* absolute difference between ident_val and trig_val */ /* * firewall */ if (!isnum(trig_val)) { printf("**** trig test %d-%d failed: %s(tval[%d]): ", testnum, index, name, index); printf("%d returned a non-numeric value\n", trig_val); return 1; } /* * compute absolute difference */ abs_diff = abs(ident_val - trig_val); /* * determine if ident_val within epsilon of trig_val */ if (near(norm(abs_diff), epsilon_norm) > 0) { printf("**** trig test %d-%d failed: %s(tval[%d]): ", testnum, index, name, index); printf("%d is not near trig identity value: %d\n", trig_val, ident_val); return 1; } return 0; } /* * not_near_zero - determine if a value is within epsilon() of 0 * * given: * value real or complex value * * returns: * 1 ==> value is farther from 0 than epsilon (not near zero) * 0 ==> value is within epsilon of 0 (near zero) */ define not_near_zero(value) { if (near(norm(value), epsilon_norm) > 0) { /* value is farther from 0 than epsilon */ return 1; } /* value is within epsilon of 0 */ return 0; } /* * verify_tan - verify trigonometric tangent * * We use the following trigonometric identity: * * tan(x) = sin(x) / cos(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_tan(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 || size(cos_tval) <= 0) { precompute_trig(); } /* * for each test value, verify the trigonometric identity within epsilon */ error_count = 0; 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 = sin_tval[i] / cos_tval[i]; /* compute trigonometric function */ trig_val = tan(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "tan", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': tan test failure count:', error_count; } return error_count; } /* * verify_cot - verify trigonometric cotangent * * We use the following trigonometric identity: * * cot(x) = cos(x) / sin(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_cot(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 || 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 sin(x) within epsilon of 0 */ if (not_near_zero(sin_tval[i])) { /* compute trigonometric identity */ ident_val = cos_tval[i] / sin_tval[i]; /* compute trigonometric function */ trig_val = cot(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "cot", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': cot test failure count:', error_count; } return error_count; } /* * verify_sec - verify trigonometric secant * * We use the following trigonometric identity: * * sec(x) = 1 / cos(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_sec(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]; /* compute trigonometric function */ trig_val = sec(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "sec", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': sec test failure count:', error_count; } return error_count; } /* * verify_csc - verify trigonometric cosecant * * We use the following trigonometric identity: * * csc(x) = 1 / sin(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_csc(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]; /* compute trigonometric function */ trig_val = csc(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "csc", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': csc test failure count:', error_count; } return error_count; } /* * verify_versin - verify versed trigonometric sine * * We use the following trigonometric identity: * * versin(x) = 1 - cos(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_versin(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]; /* compute trigonometric function */ trig_val = versin(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "versin", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': versin test failure count:', error_count; } return error_count; } /* * verify_coversin - verify coversed trigonometric sine * * We use the following trigonometric identity: * * coversin(x) = 1 - sin(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_coversin(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]; /* compute trigonometric function */ trig_val = coversin(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "coversin", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': coversin test failure count:', error_count; } return error_count; } /* * verify_vercos - verify versed trigonometric cosine * * We use the following trigonometric identity: * * vercos(x) = 1 + cos(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_vercos(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]; /* compute trigonometric function */ trig_val = vercos(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "vercos", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': vercos test failure count:', error_count; } return error_count; } /* * verify_covercos - verify coversed trigonometric cosine * * We use the following trigonometric identity: * * covercos(x) = 1 + sin(x) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_covercos(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]; /* compute trigonometric function */ trig_val = covercos(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "covercos", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': covercos test failure count:', error_count; } return error_count; } /* * verify_haversin - verify half versed trigonometric sine * * We use the following trigonometric identity: * * haversin(x) = versin(x) / 2 = (1 - cos(x)) / 2 * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_haversin(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]) / 2; /* compute trigonometric function */ trig_val = haversin(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "haversin", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': haversin test failure count:', error_count; } return error_count; } /* * verify_hacoversin - verify half versed trigonometric cosine * * We use the following trigonometric identity: * * hacoversin(x) = coversin(x) / 2 = (1 - sin(x)) / 2 * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_hacoversin(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 cos(x) within epsilon of 0 */ if (not_near_zero(sin_tval[i])) { /* compute trigonometric identity */ ident_val = (1 - sin_tval[i]) / 2; /* compute trigonometric function */ trig_val = hacoversin(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "hacoversin", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': hacoversin test failure count:', error_count; } return error_count; } /* * verify_havercos - verify half versed trigonometric cosine * * We use the following trigonometric identity: * * havercos(x) = vercos(x) / 2 = (1 + cos(x)) / 2 * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_havercos(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]) / 2; /* compute trigonometric function */ trig_val = havercos(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "havercos", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': havercos test failure count:', error_count; } return error_count; } /* * verify_hacovercos - verify half coversed trigonometric cosine * * We use the following trigonometric identity: * * hacovercos(x) = covercos(x) / 2 = (1 + sin(x)) / 2 * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_hacovercos(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]) / 2; /* compute trigonometric function */ trig_val = hacovercos(tval[i]); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "hacovercos", i, testnum)) { ++error_count; } } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': hacovercos test failure count:', error_count; } 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; } /* * verify_crd - verify trigonometric chord of a unit circle * * We use the following trigonometric identity: * * crd(x) = 2 * sin(x / 2) * * given: * testnum regression test number being performed * * returns: * number of tests that failed */ define verify_crd(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) { /* NOTE: We actually check the identity: crd(x*2) = 2 * sin(x) */ /* compute trigonometric identity */ ident_val = 2 * sin_tval[i]; /* compute trigonometric function */ trig_val = crd(tval[i] * 2); /* compare trigonometric identity with trigonometric function value */ if (compare(ident_val, trig_val, "crd", i, testnum)) { ++error_count; } } /* * report test results */ if (error_count != 0) { print '**** test', testnum : ': crd test failure count:', error_count; } 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; }