12 #include "cln/float.h"
15 #include "cln/lfloat.h"
17 #include "cln/integer.h"
20 #define MAYBE_INLINE inline
21 #include "cl_LF_zerop.cc"
22 #include "cl_LF_minusp.cc"
23 #include "cl_LF_exponent.cc"
27 // cl_F atanx_naive (const cl_F& x)
28 // cl_LF atanx_naive (const cl_LF& x)
31 // e := Exponent aus (decode-float x), d := (float-digits x)
32 // Bei x=0.0 oder e<=-d/2 liefere x
33 // (denn bei e<=-d/2 ist x^2/3 < x^2/2 < 2^(-d)/2 = 2^(-d-1), also
34 // 1 >= atan(x)/x > 1-x^2/3 > 1-2^(-d-1),
35 // also ist atan(x)/x, auf d Bits gerundet, gleich 1.0).
36 // Bei e<=-sqrt(d) verwende die Potenzreihe
37 // atan(x)/x = sum(j=0..inf,(-x^2)^j/(2j+1)):
38 // a:=-x^2, b:=1, i:=1, sum:=0,
39 // while (/= sum (setq sum (+ sum (/ b i)))) do i:=i+2, b:=b*a.
41 // Sonst setze y := x/(1+sqrt(1+x^2)), berechne rekursiv z:=atan(y)
42 // und liefere 2*z = (scale-float z 1).
43 // Diese Rekursion wird entrekursiviert. Statt k mal hintereinander
44 // x := x/(1+sqrt(1+x^2)) zu bilden, arbeitet man lieber mit den Kehrwerten,
45 // setzt also x := 1/|x|, dann k mal x := x+sqrt(x^2+1), dann x := +- 1/x.
46 // Aufwand: asymptotisch d^2.5 .
48 static const cl_LF atanx_naive (const cl_LF& x)
52 var uintC actuallen = TheLfloat(x)->len;
53 var uintC d = float_digits(x);
54 var sintE e = float_exponent(x);
55 if (e <= (sintC)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2)
56 return x; // ja -> x als Ergebnis
57 var uintL k = 0; // Rekursionszähler k:=0
58 // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe
59 // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 20% zu
60 // schlecht). Ein guter Wert ist:
61 // Für naive1: limit_scope = 0.5.
62 // Für naive2: limit_scope = 0.375 (ca. 0.5 für kleine len, 0.35 für
64 var uintL sqrt_d = floor(isqrtC(d)*3,8); // limit_slope*floor(sqrt(d))
66 if (e >= (sintL)(-sqrt_d)) {
67 // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern.
68 var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d))
69 xx = recip(abs(xx)); // 1/|x|
71 // nächstes x nach der Formel x := x+sqrt(x^2 + 1) berechnen:
72 xx = sqrt(square(xx) + cl_float(1,xx)) + xx;
74 } until (float_exponent(xx) > e_limit);
75 // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)),
76 // also x >= 2^(1+limit_slope*floor(sqrt(d))),
77 // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))).
78 // Nun kann die Potenzreihe auf 1/x angewandt werden.
81 xx = - xx; // Vorzeichen wieder rein
83 // Potenzreihe anwenden:
85 var cl_LF a = - square(xx); // a = - x^2
86 var cl_LF b = cl_float(1,xx); // b := (float 1 x)
87 var cl_LF sum = cl_float(0,xx); // sum := (float 0 x)
90 // floating-point representation
92 var cl_LF new_sum = sum + b / (cl_I)i; // (+ sum (/ b i))
93 if (new_sum == sum) // = sum ?
94 break; // ja -> Potenzreihe abbrechen
101 // floating-point representation with smooth precision reduction
102 var cl_LF eps = scale_float(b,-(sintC)d-10);
104 var cl_LF new_sum = sum + LF_to_LF(b/(cl_I)i,actuallen); // (+ sum (/ b i))
105 if (new_sum == sum) // = sum ?
106 break; // ja -> Potenzreihe abbrechen
108 b = cl_LF_shortenwith(b,eps);
113 var cl_LF erg = sum*xx; // sum*x als Ergebnis
114 return scale_float(erg,k); // wegen Rekursion noch mal 2^k
116 // Bit complexity (N = length(x)): O(N^(1/2)*M(N)).
118 static const cl_F atanx_naive (const cl_F& x)
122 var uintC d = float_digits(x);
123 var sintE e = float_exponent(x);
124 if (e <= (sintC)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2)
125 return x; // ja -> x als Ergebnis
126 var uintL k = 0; // Rekursionszähler k:=0
127 var uintL sqrt_d = floor(isqrtC(d),2); // limit_slope*floor(sqrt(d))
128 // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe
129 // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 20% zu
130 // schlecht). Ein guter Wert ist limit_scope = 0.5.
132 if (e >= (sintL)(-sqrt_d)) {
133 // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern.
134 var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d))
135 xx = recip(abs(xx)); // 1/|x|
137 // nächstes x nach der Formel x := x+sqrt(x^2 + 1) berechnen:
138 xx = sqrt(square(xx) + cl_float(1,xx)) + xx;
140 } until (float_exponent(xx) > e_limit);
141 // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)),
142 // also x >= 2^(1+limit_slope*floor(sqrt(d))),
143 // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))).
144 // Nun kann die Potenzreihe auf 1/x angewandt werden.
147 xx = - xx; // Vorzeichen wieder rein
149 // Potenzreihe anwenden:
151 var cl_F a = - square(xx); // a = - x^2
152 var cl_F b = cl_float(1,xx); // b := (float 1 x)
153 var cl_F sum = cl_float(0,xx); // sum := (float 0 x)
155 var cl_F new_sum = sum + b / (cl_I)i; // (+ sum (/ b i))
156 if (new_sum == sum) // = sum ?
157 break; // ja -> Potenzreihe abbrechen
162 var cl_F erg = sum*xx; // sum*x als Ergebnis
163 return scale_float(erg,k); // wegen Rekursion noch mal 2^k
165 // Bit complexity (N = length(x)): O(N^(1/2)*M(N)).
167 static const cl_LF atanx_ratseries (const cl_LF& t)
170 // Based on the same ideas as lnx_ratseries.
171 // e := exponent of (decode-float t), d := (float-digits t).
172 // If t=0.0 or e<=-d/2, return t.
173 // (x,y) := (1/sqrt(1+t^2),t/sqrt(1+t^2)), z := 0.
175 // [(x+i*y)*exp(i*z) is invariant, x>0, sqrt(x^2+y^2)=1]
176 // e := exponent of (decode-float y), d := (float-digits y).
177 // If y=0.0 or e<=-d/2, return z+y
178 // (because if e<=-d/2 then |y|^3/6 < 2^(-d)/2*|y|, and since
179 // asin(y) = y+y^3/6+..., asin(y) rounded to d bits is = y).
180 // Choose approximation z' of angle(x+i*y):
181 // If |y| >= 1/2, set z' = 1/2 * sign(y).
182 // If |y| < 2^-n with n maximal, set
183 // z' = truncate(y*2^(2n))/2^(2n).
184 // Set z := z + z' and x+i*y := (x+i*y)*exp(-i*z').
185 var uintC len = TheLfloat(t)->len;
186 var uintC d = intDsize*len;
187 if (zerop(t) || (float_exponent(t) <= (sintC)(-d)>>1))
189 var cl_LF x = recip(sqrt(cl_I_to_LF(1,len) + square(t)));
191 var cl_LF z = cl_I_to_LF(0,len);
193 if (zerop(y) || (float_exponent(y) <= (sintC)(-d)>>1))
195 var cl_idecoded_float y_ = integer_decode_float(y);
196 // y = (-1)^sign * 2^exponent * mantissa
197 var uintC lm = integer_length(y_.mantissa);
198 var uintE me = cl_I_to_UE(- y_.exponent);
201 var bool last_step = false;
202 if (lm >= me) { // |y| >= 1/2 ?
203 p = y_.sign; // 1 or -1
206 var uintE n = me - lm; // |y| < 2^-n with n maximal
207 // Set p to the first n bits of |y|:
209 p = y_.mantissa >> (lm - n);
215 if (minusp(y_.sign)) { p = -p; }
216 // If 2*n >= lm = intDsize*len, then within our
217 // precision exp(-i*z')=1-i*z' (because |z'^2| < 2^-lm),
218 // and we know a priori that the iteration will stop
219 // after the next big multiplication. This saves one
220 // big multiplication at the end.
224 z = z + scale_float(cl_I_to_LF(p,len),-(sintE)lq);
227 var cl_LF_cos_sin_t cis_z = cl_cossin_aux(-p,lq,len);
228 var cl_LF new_x = x*cis_z.cos - y*cis_z.sin;
229 var cl_LF new_y = x*cis_z.sin + y*cis_z.cos;
230 x = new_x; y = new_y;
234 // Bit complexity (N = length(x)): O(log(N)^2*M(N)).
236 // Timings of the above algorithms, on an i486 33 MHz, running Linux,
237 // applied to x = sqrt(2)-1 = 0.414...
238 // N naive1 naive2 ratseries
239 // 10 0.013 0.013 0.043
240 // 25 0.062 0.048 0.122
242 // 100 1.06 0.70 1.07
244 // 500 34.7 23.2 20.0
246 // ==> ratseries faster for N >= 325.
248 const cl_F atanx (const cl_F& x)
251 DeclareType(cl_LF,x);
252 if (TheLfloat(x)->len >= 325)
253 return cl_float(atanx_ratseries(extend(x,TheLfloat(x)->len+1)),x);
255 return atanx_naive(x);
257 return atanx_naive(x);
259 // Bit complexity (N = length(x)): O(log(N)^2*M(N)).