12 #include "cl_F_tran.h"
14 #include "cln/lfloat.h"
19 const cl_F cosh (const cl_F& x)
22 // Genauigkeit erhöhen,
23 // e := Exponent aus (decode-float x), d := (float-digits x)
24 // falls x=0.0 oder e<=(1-d)/2 liefere 1.0
25 // (denn bei e<=(1-d)/2 ist 1 <= cosh(x) = 1+x^2/2+... < 1+2^(-d),
26 // also ist cosh(x), auf d Bits gerundet, gleich 1.0).
28 // y := x/2 = (scale-float x -1), (sinh(y)/y)^2 errechnen,
29 // cosh(x) = 1+x*y*(sinh(y)/y)^2 errechnen.
30 // falls e>=0: y:=exp(x) errechnen, (scale-float (+ y (/ y)) -1) bilden.
32 var sintL e = float_exponent(x);
33 if (e < 0) { // Exponent e abtesten
37 var uintL d = float_digits(x);
38 if (e <= (1-(sintL)d)>>1) // e <= (1-d)/2 <==> e <= -ceiling((d-1)/2) ?
39 return cl_float(1,x); // ja -> 1.0 als Ergebnis
40 // Rechengenauigkeit erhöhen
44 if (TheLfloat(x)->len >= infty) {
45 var cl_LF xx = extend(x,TheLfloat(x)->len+1);
46 var cl_LF_cosh_sinh_t hyp = cl_coshsinh_ratseries(xx);
47 return cln/float.hyp.cosh,x);
50 if (TheLfloat(x)->len >= 600) {
51 // verwende exp(x), schneller als cl_coshsinh_ratseries
52 var cl_LF xx = extend(x,TheLfloat(x)->len+1);
54 var cl_F z = scale_float(y + recip(y), -1); // (/ (+ y (/ y)) 2)
57 var cl_LF xx = The(cl_LF)(cl_F_extendsqrt(x));
58 var cl_LF y = scale_float(xx,-1);
59 // 1 + 2*sinh(y)^2, und wieder runden
60 return cl_float(1 + scale_float(sinhx_naive(y),1), x);
63 var cl_F xx = cl_F_extendsqrt(x);
64 var cl_F y = scale_float(xx,-1);
65 // 1 + 2*y^2*(sinh(y)/y)^2, und wieder runden
66 return cl_float(1 + scale_float(square(y) * sinhxbyx_naive(y),1), x);
69 // e>=0 -> verwende exp(x)
71 return scale_float(y + recip(y), -1); // (/ (+ y (/ y)) 2)
75 // Timings of the three algorithms, on an i486 33 MHz, running Linux,
76 // applied to x = sqrt(2)-1 = 0.414...
77 // N naive ratseries exp&recip
78 // 10 0.008 0.037 0.012
79 // 25 0.032 0.117 0.047
86 // ==> exp&recip fastest for N >= 600.