/* -*-C-*- sinh.c */

#include "elefunt.h"

/*
	sinh(arg) returns the hyperbolic sine of its floating-
	point argument.

	The exponential function is called for arguments
	greater in magnitude than 0.5.

	A series is used for arguments smaller in magnitude than 0.5.
	The coefficients are #2029 from Hart & Cheney. (20.36D)

	cosh(arg) is computed from the exponential function for
	all arguments.
*/

static dp_t p0 = -0.6307673640497716991184787251e+6;
static dp_t p1 = -0.8991272022039509355398013511e+5;
static dp_t p2 = -0.2894211355989563807284660366e+4;
static dp_t p3 = -0.2630563213397497062819489e+2;
static dp_t q0 = -0.6307673640497716991212077277e+6;
static dp_t q1 = 0.1521517378790019070696485176e+5;
static dp_t q2 = -0.173678953558233699533450911e+3;

#if STDC
dp_t
sinh(dp_t arg)
#else /* NOT STDC */
dp_t
sinh(arg)
dp_t arg;
#endif /* STDC */
{
    dp_t temp,
        argsq;
    register int sign;

    sign = 1;
    if (arg < 0)
    {
	arg = -arg;
	sign = -1;
    }

    if (arg > 21.0)
    {
	temp = exp(arg) / 2;
	if (sign > 0)
	    return (temp);
	else
	    return (-temp);
    }

    if (arg > 0.5)
    {
	dp_t z;
	z = exp(arg);
	return (sign * (z - 1.0/z) / 2);
    }

    argsq = arg * arg;
    temp = (((p3 * argsq + p2) * argsq + p1) * argsq + p0) * arg;
    temp /= (((argsq + q2) * argsq + q1) * argsq + q0);
    return (sign * temp);
}

#if STDC
dp_t
cosh(dp_t arg)
#else /* NOT STDC */
dp_t
cosh(arg)
dp_t arg;
#endif /* STDC */
{
    dp_t z;

    if (arg < 0)
	arg = -arg;
    if (arg > 21.0)
    {
	return (exp(arg) / 2);
    }

    z = exp(arg);
    return ((z + 1.0/z) / 2);
}
