You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.4 KiB
94 lines
2.4 KiB
// cosh_sinh().
|
|
|
|
// General includes.
|
|
#include "cl_sysdep.h"
|
|
|
|
// Specification.
|
|
#include "cln/float.h"
|
|
|
|
|
|
// Implementation.
|
|
|
|
#include "cl_F_tran.h"
|
|
#include "cl_F.h"
|
|
#include "cln/lfloat.h"
|
|
#include "cl_LF.h"
|
|
|
|
namespace cln {
|
|
|
|
const cosh_sinh_t cosh_sinh (const cl_F& x)
|
|
{
|
|
// Methode:
|
|
// Genauigkeit erhöhen,
|
|
// e := Exponent aus (decode-float x), d := (float-digits x)
|
|
// falls x=0.0 oder e<=(1-d)/2 liefere (1.0,x)
|
|
// (denn bei e<=(1-d)/2 ist
|
|
// 1 <= sinh(x)/x < cosh(x) = 1+x^2/2+... < 1+2^(-d),
|
|
// also ist cosh(x), auf d Bits gerundet, gleich 1.0
|
|
// und sinh(x), auf d Bits gerundet, gleich x).
|
|
// falls e<0:
|
|
// y:=(sinh(x)/x)^2 errechnen,
|
|
// cosh(x) = sqrt(1+x^2*y) und sinh(x) = x*sqrt(y) errechnen.
|
|
// falls e>=0: y:=exp(x) errechnen,
|
|
// (scale-float (+ y (/ y)) -1) und (scale-float (- y (/ y)) -1) bilden.
|
|
// Genauigkeit wieder verringern.
|
|
|
|
var sintE e = float_exponent(x);
|
|
if (e < 0) { // Exponent e abtesten
|
|
// e<0
|
|
if (zerop(x) || (e <= (1-(sintC)float_digits(x))>>1))
|
|
// e <= (1-d)/2 <==> e <= -ceiling((d-1)/2)
|
|
return cosh_sinh_t(cl_float(1,x),x);
|
|
// Rechengenauigkeit erhöhen
|
|
if (longfloatp(x)) {
|
|
DeclareType(cl_LF,x);
|
|
#if 0
|
|
if (TheLfloat(x)->len >= infty) {
|
|
var cl_LF xx = extend(x,TheLfloat(x)->len+1);
|
|
var cl_LF_cosh_sinh_t hyp = cl_coshsinh_ratseries(xx);
|
|
return cosh_sinh_t(
|
|
cln/float.hyp.cosh,x),
|
|
cln/float.hyp.sinh,x)
|
|
);
|
|
} else
|
|
#endif
|
|
if (TheLfloat(x)->len >= 585) {
|
|
// verwende exp(x), schneller als cl_coshsinh_ratseries
|
|
var cl_LF xx = extend(x,TheLfloat(x)->len+ceiling((uintE)(-e),intDsize));
|
|
var cl_F y = exp(xx);
|
|
var cl_F y_inv = recip(y);
|
|
return cosh_sinh_t(
|
|
cl_float(scale_float(y + y_inv, -1), x),
|
|
cl_float(scale_float(y - y_inv, -1), x)
|
|
);
|
|
} else {
|
|
var cl_LF xx = The(cl_LF)(cl_F_extendsqrt(x));
|
|
var cl_LF y = sinhx_naive(xx);
|
|
var cl_LF z = sqrt(y);
|
|
if (minusp(xx))
|
|
z = -z;
|
|
return cosh_sinh_t(
|
|
cl_float(sqrt(1+y),x), // sqrt(1+y)
|
|
cl_float(z,x)
|
|
);
|
|
}
|
|
} else {
|
|
var cl_F xx = cl_F_extendsqrt(x);
|
|
var cl_F y = sinhxbyx_naive(xx);
|
|
return cosh_sinh_t(
|
|
cl_float(sqrt(1+square(xx)*y),x), // sqrt(1+x^2*y)
|
|
cl_float(xx*sqrt(y),x)
|
|
);
|
|
}
|
|
} else {
|
|
// e>=0 -> verwende exp(x)
|
|
var cl_F y = exp(x);
|
|
var cl_F y_inv = recip(y);
|
|
return cosh_sinh_t(
|
|
scale_float(y+y_inv,-1),
|
|
scale_float(y-y_inv,-1)
|
|
);
|
|
}
|
|
}
|
|
|
|
} // namespace cln
|