mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
add cmappr() and missing complex tan, cot, sec, csc in liblcac
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 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);
This commit is contained in:
28
CHANGES
28
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
|
Expanded the calc regression test suite test 34dd to test various
|
||||||
real and complex values for sin, cos, tan, cot, sec, csc.
|
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:
|
The following are the changes from calc version 2.14.3.4 to 2.14.3.5:
|
||||||
|
|
||||||
|
@@ -4112,10 +4112,10 @@ define test_error()
|
|||||||
n = 8191;
|
n = 8191;
|
||||||
print '3727: n = 8191';
|
print '3727: n = 8191';
|
||||||
/* test 3728 removed due to non-portable strerror() output */
|
/* test 3728 removed due to non-portable strerror() output */
|
||||||
vrfy(tan(2e9i) == error(10435), '3729: tan(2e9i) == error(10435)');
|
vrfy(tan(2e9i) == error(10537), '3729: tan(2e9i) == error(10537)');
|
||||||
vrfy(cot(2e9i) == error(10437), '3730: cot(2e9i) == error(10437)');
|
vrfy(cot(2e9i) == error(10539), '3730: cot(2e9i) == error(10539)');
|
||||||
vrfy(sec(2e9i) == error(10439), '3731: sec(2e9i) == error(10439)');
|
vrfy(sec(2e9i) == error(10540), '3731: sec(2e9i) == error(10540)');
|
||||||
vrfy(csc(2e9i) == error(10440), '3732: csc(2e9i) == error(10440)');
|
vrfy(csc(2e9i) == error(10542), '3732: csc(2e9i) == error(10542)');
|
||||||
|
|
||||||
/* errmax and errcount should be bumped up the 148 errors above */
|
/* errmax and errcount should be bumped up the 148 errors above */
|
||||||
vrfy(errcount() == ecnt, '3733: errcount() == ecnt');
|
vrfy(errcount() == ecnt, '3733: errcount() == ecnt');
|
||||||
|
18
calcerr.tbl
18
calcerr.tbl
@@ -472,12 +472,12 @@ E_ISSPACE Bad argument for isspace
|
|||||||
E_ISXDIGIT Bad argument for isxdigit
|
E_ISXDIGIT Bad argument for isxdigit
|
||||||
E_STRTOUPPER Bad argument type for strtoupper
|
E_STRTOUPPER Bad argument type for strtoupper
|
||||||
E_STRTOLOWER Bad argument type for strtolower
|
E_STRTOLOWER Bad argument type for strtolower
|
||||||
E_TAN3 Invalid value for calculating the sin numerator for tan
|
E_TAN3 UNUSED ERROR: Invalid value for calculating the sin numerator for tan
|
||||||
E_TAN4 Invalid value for calculating the cos denominator for tan
|
E_TAN4 UNUSED ERROR: Invalid value for calculating the cos denominator for tan
|
||||||
E_COT3 Invalid value for calculating the sin numerator for cot
|
E_COT3 UNUSED ERROR: Invalid value for calculating the sin numerator for cot
|
||||||
E_COT4 Invalid value for calculating the cos denominator for cot
|
E_COT4 UNUSED ERROR: Invalid value for calculating the cos denominator for cot
|
||||||
E_SEC3 Invalid value for calculating the cos reciprocal for sec
|
E_SEC3 UNUSED ERROR: Invalid value for calculating the cos reciprocal for sec
|
||||||
E_CSC3 Invalid value for calculating the sin reciprocal for csc
|
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_TANH3 Invalid value for calculating the sinh numerator for tanh
|
||||||
E_TANH4 Invalid value for calculating the cosh denominator for tanh
|
E_TANH4 Invalid value for calculating the cosh denominator for tanh
|
||||||
E_COTH3 Invalid value for calculating the sinh numerator for coth
|
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_ACOVERCOS1 Bad epsilon for acovercos
|
||||||
E_ACOVERCOS2 Bad first argument for acovercos
|
E_ACOVERCOS2 Bad first argument for acovercos
|
||||||
E_ACOVERCOS3 Too-large im(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
|
||||||
|
5
cmath.h
5
cmath.h
@@ -48,6 +48,7 @@ typedef struct {
|
|||||||
/*
|
/*
|
||||||
* Input, output, and conversion routines.
|
* 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 *comalloc(void);
|
||||||
E_FUNC COMPLEX *qqtoc(NUMBER *q1, NUMBER *q2);
|
E_FUNC COMPLEX *qqtoc(NUMBER *q1, NUMBER *q2);
|
||||||
E_FUNC void comfree(COMPLEX *c);
|
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_rel(COMPLEX *c1, COMPLEX *c2);
|
||||||
E_FUNC COMPLEX *c_asin(COMPLEX *c, NUMBER *epsilon);
|
E_FUNC COMPLEX *c_asin(COMPLEX *c, NUMBER *epsilon);
|
||||||
E_FUNC COMPLEX *c_acos(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_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_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_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_acsc(COMPLEX *c, NUMBER *epsilon);
|
||||||
E_FUNC COMPLEX *c_asinh(COMPLEX *c, NUMBER *epsilon);
|
E_FUNC COMPLEX *c_asinh(COMPLEX *c, NUMBER *epsilon);
|
||||||
E_FUNC COMPLEX *c_acosh(COMPLEX *c, NUMBER *epsilon);
|
E_FUNC COMPLEX *c_acosh(COMPLEX *c, NUMBER *epsilon);
|
||||||
|
320
comfunc.c
320
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 *
|
COMPLEX *
|
||||||
c_atan(COMPLEX *c, NUMBER *epsilon)
|
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 *
|
COMPLEX *
|
||||||
c_acot(COMPLEX *c, NUMBER *epsilon)
|
c_acot(COMPLEX *c, NUMBER *epsilon)
|
||||||
{
|
{
|
||||||
@@ -921,6 +1101,75 @@ c_acot(COMPLEX *c, NUMBER *epsilon)
|
|||||||
return tmp1;
|
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 *
|
COMPLEX *
|
||||||
c_asec(COMPLEX *c, NUMBER *epsilon)
|
c_asec(COMPLEX *c, NUMBER *epsilon)
|
||||||
{
|
{
|
||||||
@@ -932,6 +1181,75 @@ c_asec(COMPLEX *c, NUMBER *epsilon)
|
|||||||
return tmp2;
|
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 *
|
COMPLEX *
|
||||||
c_acsc(COMPLEX *c, NUMBER *epsilon)
|
c_acsc(COMPLEX *c, NUMBER *epsilon)
|
||||||
{
|
{
|
||||||
@@ -983,6 +1301,7 @@ c_acoth(COMPLEX *c, NUMBER *epsilon)
|
|||||||
return tmp2;
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
COMPLEX *
|
COMPLEX *
|
||||||
c_asech(COMPLEX *c, NUMBER *epsilon)
|
c_asech(COMPLEX *c, NUMBER *epsilon)
|
||||||
{
|
{
|
||||||
@@ -994,6 +1313,7 @@ c_asech(COMPLEX *c, NUMBER *epsilon)
|
|||||||
return tmp2;
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
COMPLEX *
|
COMPLEX *
|
||||||
c_acsch(COMPLEX *c, NUMBER *epsilon)
|
c_acsch(COMPLEX *c, NUMBER *epsilon)
|
||||||
{
|
{
|
||||||
|
71
commath.c
71
commath.c
@@ -38,6 +38,77 @@ COMPLEX _conei_ = { &_qzero_, &_qone_, 1 };
|
|||||||
STATIC COMPLEX _cnegone_ = { &_qnegone_, &_qzero_, 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.
|
* Add two complex numbers.
|
||||||
*/
|
*/
|
||||||
|
195
func.c
195
func.c
@@ -2927,8 +2927,9 @@ f_sin(int count, VALUE **vals)
|
|||||||
break;
|
break;
|
||||||
case V_COM:
|
case V_COM:
|
||||||
c = c_sin(vals[0]->v_com, eps);
|
c = c_sin(vals[0]->v_com, eps);
|
||||||
if (c == NULL)
|
if (c == NULL) {
|
||||||
return error_value(E_SIN3);
|
return error_value(E_SIN3);
|
||||||
|
}
|
||||||
result.v_com = c;
|
result.v_com = c;
|
||||||
result.v_type = V_COM;
|
result.v_type = V_COM;
|
||||||
if (cisreal(c)) {
|
if (cisreal(c)) {
|
||||||
@@ -2947,18 +2948,16 @@ S_FUNC VALUE
|
|||||||
f_tan(int count, VALUE **vals)
|
f_tan(int count, VALUE **vals)
|
||||||
{
|
{
|
||||||
VALUE result;
|
VALUE result;
|
||||||
VALUE tmp1, tmp2;
|
COMPLEX *c;
|
||||||
NUMBER *err;
|
NUMBER *err;
|
||||||
|
|
||||||
/* initialize VALUEs */
|
/* initialize VALUEs */
|
||||||
result.v_subtype = V_NOSUBTYPE;
|
result.v_subtype = V_NOSUBTYPE;
|
||||||
tmp1.v_subtype = V_NOSUBTYPE;
|
|
||||||
tmp2.v_subtype = V_NOSUBTYPE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set error tolerance for builtin function
|
* 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;
|
err = conf->epsilon;
|
||||||
if (count == 2) {
|
if (count == 2) {
|
||||||
@@ -2967,6 +2966,7 @@ f_tan(int count, VALUE **vals)
|
|||||||
}
|
}
|
||||||
err = vals[1]->v_num;
|
err = vals[1]->v_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* compute tangent to a given error tolerance
|
* compute tangent to a given error tolerance
|
||||||
*/
|
*/
|
||||||
@@ -2976,20 +2976,16 @@ f_tan(int count, VALUE **vals)
|
|||||||
result.v_type = V_NUM;
|
result.v_type = V_NUM;
|
||||||
break;
|
break;
|
||||||
case V_COM:
|
case V_COM:
|
||||||
tmp1.v_type = V_COM;
|
c = c_tan(vals[0]->v_com, err);
|
||||||
tmp1.v_com = c_sin(vals[0]->v_com, err);
|
if (c == NULL) {
|
||||||
if (tmp1.v_com == NULL) {
|
return error_value(E_TAN5);
|
||||||
return error_value(E_TAN3);
|
|
||||||
}
|
}
|
||||||
tmp2.v_type = V_COM;
|
result.v_com = c;
|
||||||
tmp2.v_com = c_cos(vals[0]->v_com, err);
|
result.v_type = V_COM;
|
||||||
if (tmp2.v_com == NULL) {
|
if (cisreal(c)) {
|
||||||
comfree(tmp1.v_com);
|
result.v_num = c_to_q(c, true);
|
||||||
return error_value(E_TAN4);
|
result.v_type = V_NUM;
|
||||||
}
|
}
|
||||||
divvalue(&tmp1, &tmp2, &result);
|
|
||||||
comfree(tmp1.v_com);
|
|
||||||
comfree(tmp2.v_com);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return error_value(E_TAN2);
|
return error_value(E_TAN2);
|
||||||
@@ -2997,21 +2993,77 @@ f_tan(int count, VALUE **vals)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
S_FUNC VALUE
|
S_FUNC VALUE
|
||||||
f_sec(int count, VALUE **vals)
|
f_cot(int count, VALUE **vals)
|
||||||
{
|
{
|
||||||
VALUE result;
|
VALUE result;
|
||||||
VALUE tmp;
|
COMPLEX *c;
|
||||||
NUMBER *err;
|
NUMBER *err;
|
||||||
|
|
||||||
/* initialize VALUEs */
|
/* initialize VALUEs */
|
||||||
result.v_subtype = V_NOSUBTYPE;
|
result.v_subtype = V_NOSUBTYPE;
|
||||||
tmp.v_subtype = V_NOSUBTYPE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set error tolerance for builtin function
|
* 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;
|
err = conf->epsilon;
|
||||||
if (count == 2) {
|
if (count == 2) {
|
||||||
@@ -3030,13 +3082,16 @@ f_sec(int count, VALUE **vals)
|
|||||||
result.v_type = V_NUM;
|
result.v_type = V_NUM;
|
||||||
break;
|
break;
|
||||||
case V_COM:
|
case V_COM:
|
||||||
tmp.v_type = V_COM;
|
c = c_sec(vals[0]->v_com, err);
|
||||||
tmp.v_com = c_cos(vals[0]->v_com, err);
|
if (c == NULL) {
|
||||||
if (tmp.v_com == NULL) {
|
return error_value(E_SEC5);
|
||||||
return error_value(E_SEC3);
|
}
|
||||||
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return error_value(E_SEC2);
|
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
|
S_FUNC VALUE
|
||||||
f_csc(int count, VALUE **vals)
|
f_csc(int count, VALUE **vals)
|
||||||
{
|
{
|
||||||
VALUE result;
|
VALUE result;
|
||||||
VALUE tmp;
|
COMPLEX *c;
|
||||||
NUMBER *err;
|
NUMBER *err;
|
||||||
|
|
||||||
/* initialize VALUEs */
|
/* initialize VALUEs */
|
||||||
result.v_subtype = V_NOSUBTYPE;
|
result.v_subtype = V_NOSUBTYPE;
|
||||||
tmp.v_subtype = V_NOSUBTYPE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set error tolerance for builtin function
|
* 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;
|
err = conf->epsilon;
|
||||||
if (count == 2) {
|
if (count == 2) {
|
||||||
@@ -3132,19 +3128,26 @@ f_csc(int count, VALUE **vals)
|
|||||||
*/
|
*/
|
||||||
switch (vals[0]->v_type) {
|
switch (vals[0]->v_type) {
|
||||||
case V_NUM:
|
case V_NUM:
|
||||||
if (qiszero(vals[0]->v_num))
|
if (qiszero(vals[0]->v_num)) {
|
||||||
return error_value(E_1OVER0);
|
return error_value(E_CSC5);
|
||||||
|
}
|
||||||
result.v_num = qcsc(vals[0]->v_num, err);
|
result.v_num = qcsc(vals[0]->v_num, err);
|
||||||
result.v_type = V_NUM;
|
result.v_type = V_NUM;
|
||||||
break;
|
break;
|
||||||
case V_COM:
|
case V_COM:
|
||||||
tmp.v_type = V_COM;
|
if (ciszero(vals[0]->v_com)) {
|
||||||
tmp.v_com = c_sin(vals[0]->v_com, err);
|
return error_value(E_CSC5);
|
||||||
if (tmp.v_com == NULL) {
|
}
|
||||||
return error_value(E_CSC3);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return error_value(E_CSC2);
|
return error_value(E_CSC2);
|
||||||
|
5
help/cot
5
help/cot
@@ -14,6 +14,10 @@ DESCRIPTION
|
|||||||
Calculate the cotangent of x to a multiple of eps, with error less
|
Calculate the cotangent of x to a multiple of eps, with error less
|
||||||
in absolute value than .75 * eps.
|
in absolute value than .75 * eps.
|
||||||
|
|
||||||
|
This function is equivalent to:
|
||||||
|
|
||||||
|
cot(x) = cos(x) / sin(x)
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
; print cot(1, 1e-5), cot(1, 1e-10), cot(1, 1e-15), cot(1, 1e-20)
|
; 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
|
0.64209 0.6420926159 0.642092615934331 0.64209261593433070301
|
||||||
@@ -33,6 +37,7 @@ LIMITS
|
|||||||
|
|
||||||
LINK LIBRARY
|
LINK LIBRARY
|
||||||
NUMBER *qcot(NUMBER *x, NUMBER *eps)
|
NUMBER *qcot(NUMBER *x, NUMBER *eps)
|
||||||
|
COMPLEX *c_cot(COMPLEX *c, NUMBER *eps)
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
sin, cos, tan, sec, csc
|
sin, cos, tan, sec, csc
|
||||||
|
5
help/csc
5
help/csc
@@ -14,6 +14,10 @@ DESCRIPTION
|
|||||||
Calculate the cosecant of x to a multiple of eps, with error less
|
Calculate the cosecant of x to a multiple of eps, with error less
|
||||||
in absolute value than .75 * eps.
|
in absolute value than .75 * eps.
|
||||||
|
|
||||||
|
This function is equivalent to:
|
||||||
|
|
||||||
|
csc(x) = 1 / sin(x)
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
; print csc(1, 1e-5), csc(1, 1e-10), csc(1, 1e-15), csc(1, 1e-20)
|
; 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
|
1.1884 1.1883951058 1.188395105778121 1.18839510577812121626
|
||||||
@@ -33,6 +37,7 @@ LIMITS
|
|||||||
|
|
||||||
LINK LIBRARY
|
LINK LIBRARY
|
||||||
NUMBER *qcsc(NUMBER *x, NUMBER *eps)
|
NUMBER *qcsc(NUMBER *x, NUMBER *eps)
|
||||||
|
COMPLEX *c_csc(COMPLEX *c, NUMBER *eps)
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
sin, cos, tan, cot, sec
|
sin, cos, tan, cot, sec
|
||||||
|
5
help/sec
5
help/sec
@@ -14,6 +14,10 @@ DESCRIPTION
|
|||||||
Calculate the secant of x to a multiple of eps, with error less
|
Calculate the secant of x to a multiple of eps, with error less
|
||||||
in absolute value than .75 * eps.
|
in absolute value than .75 * eps.
|
||||||
|
|
||||||
|
This function is equivalent to:
|
||||||
|
|
||||||
|
sec(x) = 1 / cos(x)
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
; print sec(1, 1e-5), sec(1, 1e-10), sec(1, 1e-15), sec(1, 1e-20)
|
; 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
|
1.85082 1.8508157177 1.850815717680926 1.85081571768092561791
|
||||||
@@ -33,6 +37,7 @@ LIMITS
|
|||||||
|
|
||||||
LINK LIBRARY
|
LINK LIBRARY
|
||||||
NUMBER *qsec(NUMBER *x, NUMBER *eps)
|
NUMBER *qsec(NUMBER *x, NUMBER *eps)
|
||||||
|
COMPLEX *c_sec(COMPLEX *c, NUMBER *eps)
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
sin, cos, tan, cot, csc
|
sin, cos, tan, cot, csc
|
||||||
|
5
help/tan
5
help/tan
@@ -14,6 +14,10 @@ DESCRIPTION
|
|||||||
Calculate the tangent of x to a multiple of eps, with error less
|
Calculate the tangent of x to a multiple of eps, with error less
|
||||||
in absolute value than .75 * eps.
|
in absolute value than .75 * eps.
|
||||||
|
|
||||||
|
This function is equivalent to:
|
||||||
|
|
||||||
|
tan(x) = sin(x) / cos(x)
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
; print tan(1, 1e-5), tan(1, 1e-10), tan(1, 1e-15), tan(1, 1e-20)
|
; 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
|
1.55741 1.5574077247 1.557407724654902 1.55740772465490223051
|
||||||
@@ -33,6 +37,7 @@ LIMITS
|
|||||||
|
|
||||||
LINK LIBRARY
|
LINK LIBRARY
|
||||||
NUMBER *qtan(NUMBER *x, NUMBER *eps)
|
NUMBER *qtan(NUMBER *x, NUMBER *eps)
|
||||||
|
COMPLEX *c_tan(COMPLEX *c, NUMBER *eps)
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
sin, cos, cot, sec, csc
|
sin, cos, cot, sec, csc
|
||||||
|
Reference in New Issue
Block a user