diff --git a/CHANGES b/CHANGES index 322ba0d..2942097 100644 --- a/CHANGES +++ b/CHANGES @@ -185,6 +185,34 @@ The following are the changes from calc version 2.14.3.5 to date: Expanded the calc regression test suite test 34dd to test various real and complex values for sin, cos, tan, cot, sec, csc. + Added complex multiple approximation function to commath.c so + that users of libcalc may directly round complex number to + nearest multiple of a given real number: + + E_FUNC COMPLEX *cmappr(COMPLEX *c, NUMBER *e, long rnd, bool cfree); + + For example: + + COMPLEX *c; /* complex number to round to nearest epsilon */ + NUMBER *eps; /* epsilon rounding precision */ + COMPLEX *res; /* c rounded to nearest epsilon */ + long rnd = 24L; /* a common rounding mode */ + bool ok_to_free; /* true ==> free c, false ==> do not free c */ + + ... + + res = cmappr(c, eps, ok_to_free); + + The complex trigonometric functions tan, cot, sec, csc were + implemented in func.c as calls to complex sin and complex cos. + We added the following direct calls to comfunc.c so that users + of libcalc may call them directly: + + E_FUNC COMPLEX *c_tan(COMPLEX *c, NUMBER *eps); + E_FUNC COMPLEX *c_cot(COMPLEX *c, NUMBER *eps); + E_FUNC COMPLEX *c_sec(COMPLEX *c, NUMBER *eps); + E_FUNC COMPLEX *c_cot(COMPLEX *c, NUMBER *eps); + 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 2b94b7f..a6e2f33 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -4112,10 +4112,10 @@ define test_error() n = 8191; print '3727: n = 8191'; /* test 3728 removed due to non-portable strerror() output */ - vrfy(tan(2e9i) == error(10435), '3729: tan(2e9i) == error(10435)'); - vrfy(cot(2e9i) == error(10437), '3730: cot(2e9i) == error(10437)'); - vrfy(sec(2e9i) == error(10439), '3731: sec(2e9i) == error(10439)'); - vrfy(csc(2e9i) == error(10440), '3732: csc(2e9i) == error(10440)'); + vrfy(tan(2e9i) == error(10537), '3729: tan(2e9i) == error(10537)'); + vrfy(cot(2e9i) == error(10539), '3730: cot(2e9i) == error(10539)'); + vrfy(sec(2e9i) == error(10540), '3731: sec(2e9i) == error(10540)'); + vrfy(csc(2e9i) == error(10542), '3732: csc(2e9i) == error(10542)'); /* errmax and errcount should be bumped up the 148 errors above */ vrfy(errcount() == ecnt, '3733: errcount() == ecnt'); diff --git a/calcerr.tbl b/calcerr.tbl index 43de54e..3940f87 100644 --- a/calcerr.tbl +++ b/calcerr.tbl @@ -472,12 +472,12 @@ E_ISSPACE Bad argument for isspace E_ISXDIGIT Bad argument for isxdigit E_STRTOUPPER Bad argument type for strtoupper E_STRTOLOWER Bad argument type for strtolower -E_TAN3 Invalid value for calculating the sin numerator for tan -E_TAN4 Invalid value for calculating the cos denominator for tan -E_COT3 Invalid value for calculating the sin numerator for cot -E_COT4 Invalid value for calculating the cos denominator for cot -E_SEC3 Invalid value for calculating the cos reciprocal for sec -E_CSC3 Invalid value for calculating the sin reciprocal for csc +E_TAN3 UNUSED ERROR: Invalid value for calculating the sin numerator for tan +E_TAN4 UNUSED ERROR: Invalid value for calculating the cos denominator for tan +E_COT3 UNUSED ERROR: Invalid value for calculating the sin numerator for cot +E_COT4 UNUSED ERROR: Invalid value for calculating the cos denominator for cot +E_SEC3 UNUSED ERROR: Invalid value for calculating the cos reciprocal for sec +E_CSC3 UNUSED ERROR: Invalid value for calculating the sin reciprocal for csc E_TANH3 Invalid value for calculating the sinh numerator for tanh E_TANH4 Invalid value for calculating the cosh denominator for tanh E_COTH3 Invalid value for calculating the sinh numerator for coth @@ -574,3 +574,9 @@ E_COVERCOS3 Too-large im(argument) for covercos E_ACOVERCOS1 Bad epsilon for acovercos E_ACOVERCOS2 Bad first argument for acovercos E_ACOVERCOS3 Too-large im(argument) for acovercos +E_TAN5 Invalid complex argument for tan +E_COT5 Invalid zero argument for cot +E_COT6 Invalid complex argument for cot +E_SEC5 Invalid complex argument for sec +E_CSC5 Invalid zero argument for cot +E_CSC6 Invalid complex argument for csc diff --git a/cmath.h b/cmath.h index 3660428..a1829f6 100644 --- a/cmath.h +++ b/cmath.h @@ -48,6 +48,7 @@ typedef struct { /* * Input, output, and conversion routines. */ +E_FUNC COMPLEX *cmappr(COMPLEX *c, NUMBER *e, long rnd, bool cfree); E_FUNC COMPLEX *comalloc(void); E_FUNC COMPLEX *qqtoc(NUMBER *q1, NUMBER *q2); E_FUNC void comfree(COMPLEX *c); @@ -107,9 +108,13 @@ E_FUNC COMPLEX *c_polar(NUMBER *q1, NUMBER *q2, NUMBER *epsilon); E_FUNC COMPLEX *c_rel(COMPLEX *c1, COMPLEX *c2); E_FUNC COMPLEX *c_asin(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_acos(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_tan(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_atan(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_cot(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_acot(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_sec(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_asec(COMPLEX *c, NUMBER *epsilon); +E_FUNC COMPLEX *c_csc(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_acsc(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_asinh(COMPLEX *c, NUMBER *epsilon); E_FUNC COMPLEX *c_acosh(COMPLEX *c, NUMBER *epsilon); diff --git a/comfunc.c b/comfunc.c index 8a7e9a3..9f587cc 100644 --- a/comfunc.c +++ b/comfunc.c @@ -878,6 +878,96 @@ c_acosh(COMPLEX *c, NUMBER *epsilon) } +/* + * c_tan - complex trigonometric tangent + * + * This uses the formula: + * + * tan(x) = sin(x) / cos(x) + * + * given: + * c argument to the trigonometric function + * epsilon precision of the trigonometric calculation + * + * returns: + * != NULL ==> allocated pointer to COMPLEX result + * NULL ==> invalid trigonometric argument + * + * NOTE: When the trigonometric result is returned as non-NULL result, + * the value may be a real value. The caller may wish to: + * + * COMPLEX *c; (* return result of this function *) + * NUMBER *q; (* COMPLEX result when c is a real number *) + * + * if (c == NULL) { + * math_error("... some error message"); + * not_reached(); + * } + * if (cisreal(c)) { + * q = c_to_q(c, ok_to_free); + * } + */ +COMPLEX * +c_tan(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *denom; /* trigonometric identity numerator */ + COMPLEX *numer; /* trigonometric identity denominator */ + COMPLEX *res; /* trigonometric result */ + + /* + * firewall - check args + */ + if (c == NULL) { + return NULL; + } + if (check_epsilon(epsilon) == false) { + return NULL; + } + + /* + * evaluate the cos(x) denominator + * + * Return NULL if cos(x) failed or we otherwise divide by zero. + */ + denom = c_cos(c, epsilon); + if (denom == NULL || ciszero(denom)) { + return NULL; + } + + /* + * evaluate the sin(x) numerator + * + * Return NULL if sin(x) failed. + */ + numer = c_sin(c, epsilon); + if (numer == NULL) { + comfree(denom); + return NULL; + } + + /* + * catch the special case of numerator of 0 + */ + if (ciszero(numer)) { + comfree(denom); + comfree(numer); + return clink(&_czero_); + } + + /* + * compute the trigonometric function value + */ + res = c_div(numer, denom); + comfree(denom); + comfree(numer); + + /* + * return the trigonometric result + */ + return res; +} + + COMPLEX * c_atan(COMPLEX *c, NUMBER *epsilon) { @@ -900,6 +990,96 @@ c_atan(COMPLEX *c, NUMBER *epsilon) } +/* + * c_cot - complex trigonometric cotangent + * + * This uses the formula: + * + * cot(x) = cos(x) / sin(x) + * + * given: + * c argument to the trigonometric function + * epsilon precision of the trigonometric calculation + * + * returns: + * != NULL ==> allocated pointer to COMPLEX result + * NULL ==> invalid trigonometric argument + * + * NOTE: When the trigonometric result is returned as non-NULL result, + * the value may be a real value. The caller may wish to: + * + * COMPLEX *c; (* return result of this function *) + * NUMBER *q; (* COMPLEX result when c is a real number *) + * + * if (c == NULL) { + * math_error("... some error message"); + * not_reached(); + * } + * if (cisreal(c)) { + * q = c_to_q(c, ok_to_free); + * } + */ +COMPLEX * +c_cot(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *denom; /* trigonometric identity numerator */ + COMPLEX *numer; /* trigonometric identity denominator */ + COMPLEX *res; /* trigonometric result */ + + /* + * firewall - check args + */ + if (c == NULL) { + return NULL; + } + if (check_epsilon(epsilon) == false) { + return NULL; + } + + /* + * evaluate the sin(x) denominator + * + * Return NULL if sin(x) failed or we otherwise divide by zero. + */ + denom = c_sin(c, epsilon); + if (denom == NULL || ciszero(denom)) { + return NULL; + } + + /* + * evaluate the cos(x) numerator + * + * Return NULL if cos(x) failed. + */ + numer = c_cos(c, epsilon); + if (numer == NULL) { + comfree(denom); + return NULL; + } + + /* + * catch the special case of numerator of 0 + */ + if (ciszero(numer)) { + comfree(denom); + comfree(numer); + return clink(&_czero_); + } + + /* + * compute the trigonometric function value + */ + res = c_div(numer, denom); + comfree(denom); + comfree(numer); + + /* + * return the trigonometric result + */ + return res; +} + + COMPLEX * c_acot(COMPLEX *c, NUMBER *epsilon) { @@ -921,6 +1101,75 @@ c_acot(COMPLEX *c, NUMBER *epsilon) return tmp1; } + +/* + * c_sec - complex trigonometric tangent + * + * This uses the formula: + * + * sec(x) = 1 / cos(x) + * + * given: + * c argument to the trigonometric function + * epsilon precision of the trigonometric calculation + * + * returns: + * != NULL ==> allocated pointer to COMPLEX result + * NULL ==> invalid trigonometric argument + * + * NOTE: When the trigonometric result is returned as non-NULL result, + * the value may be a real value. The caller may wish to: + * + * COMPLEX *c; (* return result of this function *) + * NUMBER *q; (* COMPLEX result when c is a real number *) + * + * if (c == NULL) { + * math_error("... some error message"); + * not_reached(); + * } + * if (cisreal(c)) { + * q = c_to_q(c, ok_to_free); + * } + */ +COMPLEX * +c_sec(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *denom; /* trigonometric identity numerator */ + COMPLEX *res; /* trigonometric result */ + + /* + * firewall - check args + */ + if (c == NULL) { + return NULL; + } + if (check_epsilon(epsilon) == false) { + return NULL; + } + + /* + * evaluate the cos(x) denominator + * + * Return NULL if cos(x) failed or we otherwise divide by zero. + */ + denom = c_cos(c, epsilon); + if (denom == NULL || ciszero(denom)) { + return NULL; + } + + /* + * compute the trigonometric function value + */ + res = c_div(&_cone_, denom); + comfree(denom); + + /* + * return the trigonometric result + */ + return res; +} + + COMPLEX * c_asec(COMPLEX *c, NUMBER *epsilon) { @@ -932,6 +1181,75 @@ c_asec(COMPLEX *c, NUMBER *epsilon) return tmp2; } + +/* + * c_sec - complex trigonometric cosecant + * + * This uses the formula: + * + * csc(x) = 1 / sin(x) + * + * given: + * c argument to the trigonometric function + * epsilon precision of the trigonometric calculation + * + * returns: + * != NULL ==> allocated pointer to COMPLEX result + * NULL ==> invalid trigonometric argument + * + * NOTE: When the trigonometric result is returned as non-NULL result, + * the value may be a real value. The caller may wish to: + * + * COMPLEX *c; (* return result of this function *) + * NUMBER *q; (* COMPLEX result when c is a real number *) + * + * if (c == NULL) { + * math_error("... some error message"); + * not_reached(); + * } + * if (cisreal(c)) { + * q = c_to_q(c, ok_to_free); + * } + */ +COMPLEX * +c_csc(COMPLEX *c, NUMBER *epsilon) +{ + COMPLEX *denom; /* trigonometric identity numerator */ + COMPLEX *res; /* trigonometric result */ + + /* + * firewall - check args + */ + if (c == NULL) { + return NULL; + } + if (check_epsilon(epsilon) == false) { + return NULL; + } + + /* + * evaluate the sin(x) denominator + * + * Return NULL if sin(x) failed or we otherwise divide by zero. + */ + denom = c_sin(c, epsilon); + if (denom == NULL || ciszero(denom)) { + return NULL; + } + + /* + * compute the trigonometric function value + */ + res = c_div(&_cone_, denom); + comfree(denom); + + /* + * return the trigonometric result + */ + return res; +} + + COMPLEX * c_acsc(COMPLEX *c, NUMBER *epsilon) { @@ -983,6 +1301,7 @@ c_acoth(COMPLEX *c, NUMBER *epsilon) return tmp2; } + COMPLEX * c_asech(COMPLEX *c, NUMBER *epsilon) { @@ -994,6 +1313,7 @@ c_asech(COMPLEX *c, NUMBER *epsilon) return tmp2; } + COMPLEX * c_acsch(COMPLEX *c, NUMBER *epsilon) { diff --git a/commath.c b/commath.c index 5fa9f02..c1400c5 100644 --- a/commath.c +++ b/commath.c @@ -38,6 +38,77 @@ COMPLEX _conei_ = { &_qzero_, &_qone_, 1 }; STATIC COMPLEX _cnegone_ = { &_qnegone_, &_qzero_, 1 }; +/* + * cmappr - complex multiple approximation + * + * Approximate a number to nearest multiple of a given real number. Whether + * rounding is down, up, etc. is determined by rnd. + * + * This function is useful to round a result to the nearest epsilon: + * + * COMPLEX *c; (* complex number to round to nearest epsilon *) + * NUMBER *eps; (* epsilon rounding precision *) + * COMPLEX *res; (* c rounded to nearest epsilon *) + * long rnd = 24L; (* a common rounding mode *) + * bool ok_to_free; (* true ==> free c, false ==> do not free c *) + * + * ... + * + * res = cmappr(c, eps, ok_to_free); + * + * given: + * c pointer to COMPLEX value to round + * e pointer to NUMBER multiple + * rnd rounding mode + * cfree true ==> free c, false ==> do not free c + * + * returns: + * allocated pointer to COMPLEX multiple of e approximation of c + */ +COMPLEX * +cmappr(COMPLEX *c, NUMBER *e, long rnd, bool cfree) +{ + COMPLEX *r; /* COMPLEX multiple of e approximation of c */ + + /* + * firewall + */ + if (c == NULL) { + math_error("%s: c is NULL", __func__); + not_reached(); + } + if (e == NULL) { + math_error("%s: e is NULL", __func__); + not_reached(); + } + + /* + * allocate return result + */ + r = comalloc(); + + /* + * round c to multiple of e + */ + qfree(r->real); + r->real = qmappr(c->real, e, rnd); + qfree(r->imag); + r->imag = qmappr(c->imag, e, rnd); + + /* + * free c if requested + */ + if (cfree == true) { + comfree(c); + } + + /* + * return the allocated multiple of e approximation of c + */ + return r; +} + + /* * Add two complex numbers. */ diff --git a/func.c b/func.c index 9c7e5e5..369703b 100644 --- a/func.c +++ b/func.c @@ -2927,8 +2927,9 @@ f_sin(int count, VALUE **vals) break; case V_COM: c = c_sin(vals[0]->v_com, eps); - if (c == NULL) + if (c == NULL) { return error_value(E_SIN3); + } result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { @@ -2947,18 +2948,16 @@ S_FUNC VALUE f_tan(int count, VALUE **vals) { VALUE result; - VALUE tmp1, tmp2; + COMPLEX *c; NUMBER *err; /* initialize VALUEs */ result.v_subtype = V_NOSUBTYPE; - tmp1.v_subtype = V_NOSUBTYPE; - tmp2.v_subtype = V_NOSUBTYPE; /* * set error tolerance for builtin function * - * Use eps VALUE arg if given and value is in a valid range. + * Use err VALUE arg if given and value is in a valid range. */ err = conf->epsilon; if (count == 2) { @@ -2967,6 +2966,7 @@ f_tan(int count, VALUE **vals) } err = vals[1]->v_num; } + /* * compute tangent to a given error tolerance */ @@ -2976,20 +2976,16 @@ f_tan(int count, VALUE **vals) result.v_type = V_NUM; break; case V_COM: - tmp1.v_type = V_COM; - tmp1.v_com = c_sin(vals[0]->v_com, err); - if (tmp1.v_com == NULL) { - return error_value(E_TAN3); + c = c_tan(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_TAN5); } - tmp2.v_type = V_COM; - tmp2.v_com = c_cos(vals[0]->v_com, err); - if (tmp2.v_com == NULL) { - comfree(tmp1.v_com); - return error_value(E_TAN4); + 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; } - divvalue(&tmp1, &tmp2, &result); - comfree(tmp1.v_com); - comfree(tmp2.v_com); break; default: return error_value(E_TAN2); @@ -2997,21 +2993,77 @@ f_tan(int count, VALUE **vals) return result; } + S_FUNC VALUE -f_sec(int count, VALUE **vals) +f_cot(int count, VALUE **vals) { VALUE result; - VALUE tmp; + COMPLEX *c; NUMBER *err; /* initialize VALUEs */ result.v_subtype = V_NOSUBTYPE; - tmp.v_subtype = V_NOSUBTYPE; /* * set error tolerance for builtin function * - * Use eps VALUE arg if given and value is in a valid range. + * 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_COT1); + } + err = vals[1]->v_num; + } + + /* + * compute cotangent to a given error tolerance + */ + switch (vals[0]->v_type) { + case V_NUM: + if (qiszero(vals[0]->v_num)) { + return error_value(E_COT5); + } + result.v_num = qcot(vals[0]->v_num, err); + result.v_type = V_NUM; + break; + case V_COM: + if (ciszero(vals[0]->v_com)) { + return error_value(E_COT5); + } + c = c_cot(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_COT6); + } + 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_COT2); + } + return result; +} + + +S_FUNC VALUE +f_sec(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) { @@ -3030,13 +3082,16 @@ f_sec(int count, VALUE **vals) result.v_type = V_NUM; break; case V_COM: - tmp.v_type = V_COM; - tmp.v_com = c_cos(vals[0]->v_com, err); - if (tmp.v_com == NULL) { - return error_value(E_SEC3); + c = c_sec(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_SEC5); + } + 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; } - invertvalue(&tmp, &result); - comfree(tmp.v_com); break; default: return error_value(E_SEC2); @@ -3045,79 +3100,20 @@ f_sec(int count, VALUE **vals) } -S_FUNC VALUE -f_cot(int count, VALUE **vals) -{ - VALUE result; - VALUE tmp1, tmp2; - NUMBER *err; - - /* initialize VALUEs */ - result.v_subtype = V_NOSUBTYPE; - tmp1.v_subtype = V_NOSUBTYPE; - tmp2.v_subtype = V_NOSUBTYPE; - - /* - * set error tolerance for builtin function - * - * Use eps 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_COT1); - } - err = vals[1]->v_num; - } - - /* - * compute cotangent to a given error tolerance - */ - switch (vals[0]->v_type) { - case V_NUM: - if (qiszero(vals[0]->v_num)) - return error_value(E_1OVER0); - result.v_num = qcot(vals[0]->v_num, err); - result.v_type = V_NUM; - break; - case V_COM: - tmp1.v_type = V_COM; - tmp1.v_com = c_cos(vals[0]->v_com, err); - if (tmp1.v_com == NULL) { - return error_value(E_COT3); - } - tmp2.v_type = V_COM; - tmp2.v_com = c_sin(vals[0]->v_com, err); - if (tmp2.v_com == NULL) { - comfree(tmp1.v_com); - return error_value(E_COT4); - } - divvalue(&tmp1, &tmp2, &result); - comfree(tmp1.v_com); - comfree(tmp2.v_com); - break; - default: - return error_value(E_COT2); - } - return result; -} - - S_FUNC VALUE f_csc(int count, VALUE **vals) { VALUE result; - VALUE tmp; + COMPLEX *c; NUMBER *err; /* initialize VALUEs */ result.v_subtype = V_NOSUBTYPE; - tmp.v_subtype = V_NOSUBTYPE; /* * set error tolerance for builtin function * - * Use eps VALUE arg if given and value is in a valid range. + * Use err VALUE arg if given and value is in a valid range. */ err = conf->epsilon; if (count == 2) { @@ -3132,19 +3128,26 @@ f_csc(int count, VALUE **vals) */ switch (vals[0]->v_type) { case V_NUM: - if (qiszero(vals[0]->v_num)) - return error_value(E_1OVER0); + if (qiszero(vals[0]->v_num)) { + return error_value(E_CSC5); + } result.v_num = qcsc(vals[0]->v_num, err); result.v_type = V_NUM; break; case V_COM: - tmp.v_type = V_COM; - tmp.v_com = c_sin(vals[0]->v_com, err); - if (tmp.v_com == NULL) { - return error_value(E_CSC3); + if (ciszero(vals[0]->v_com)) { + return error_value(E_CSC5); + } + c = c_csc(vals[0]->v_com, err); + if (c == NULL) { + return error_value(E_CSC6); + } + 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; } - invertvalue(&tmp, &result); - comfree(tmp.v_com); break; default: return error_value(E_CSC2); diff --git a/help/cot b/help/cot index 234d800..793267b 100644 --- a/help/cot +++ b/help/cot @@ -14,6 +14,10 @@ DESCRIPTION Calculate the cotangent of x to a multiple of eps, with error less in absolute value than .75 * eps. + This function is equivalent to: + + cot(x) = cos(x) / sin(x) + EXAMPLE ; print cot(1, 1e-5), cot(1, 1e-10), cot(1, 1e-15), cot(1, 1e-20) 0.64209 0.6420926159 0.642092615934331 0.64209261593433070301 @@ -33,6 +37,7 @@ LIMITS LINK LIBRARY NUMBER *qcot(NUMBER *x, NUMBER *eps) + COMPLEX *c_cot(COMPLEX *c, NUMBER *eps) SEE ALSO sin, cos, tan, sec, csc diff --git a/help/csc b/help/csc index 2371ec3..a90b21d 100644 --- a/help/csc +++ b/help/csc @@ -14,6 +14,10 @@ DESCRIPTION Calculate the cosecant of x to a multiple of eps, with error less in absolute value than .75 * eps. + This function is equivalent to: + + csc(x) = 1 / sin(x) + EXAMPLE ; print csc(1, 1e-5), csc(1, 1e-10), csc(1, 1e-15), csc(1, 1e-20) 1.1884 1.1883951058 1.188395105778121 1.18839510577812121626 @@ -33,6 +37,7 @@ LIMITS LINK LIBRARY NUMBER *qcsc(NUMBER *x, NUMBER *eps) + COMPLEX *c_csc(COMPLEX *c, NUMBER *eps) SEE ALSO sin, cos, tan, cot, sec diff --git a/help/sec b/help/sec index 68627ed..4726bb3 100644 --- a/help/sec +++ b/help/sec @@ -14,6 +14,10 @@ DESCRIPTION Calculate the secant of x to a multiple of eps, with error less in absolute value than .75 * eps. + This function is equivalent to: + + sec(x) = 1 / cos(x) + EXAMPLE ; print sec(1, 1e-5), sec(1, 1e-10), sec(1, 1e-15), sec(1, 1e-20) 1.85082 1.8508157177 1.850815717680926 1.85081571768092561791 @@ -33,6 +37,7 @@ LIMITS LINK LIBRARY NUMBER *qsec(NUMBER *x, NUMBER *eps) + COMPLEX *c_sec(COMPLEX *c, NUMBER *eps) SEE ALSO sin, cos, tan, cot, csc diff --git a/help/tan b/help/tan index 7d2d709..44afa55 100644 --- a/help/tan +++ b/help/tan @@ -14,6 +14,10 @@ DESCRIPTION Calculate the tangent of x to a multiple of eps, with error less in absolute value than .75 * eps. + This function is equivalent to: + + tan(x) = sin(x) / cos(x) + EXAMPLE ; print tan(1, 1e-5), tan(1, 1e-10), tan(1, 1e-15), tan(1, 1e-20) 1.55741 1.5574077247 1.557407724654902 1.55740772465490223051 @@ -33,6 +37,7 @@ LIMITS LINK LIBRARY NUMBER *qtan(NUMBER *x, NUMBER *eps) + COMPLEX *c_tan(COMPLEX *c, NUMBER *eps) SEE ALSO sin, cos, cot, sec, csc