xref: /netbsd-src/external/gpl3/gcc.old/dist/libquadmath/math/cbrtq.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1*627f7eb2Smrg /*							cbrtq.c
2*627f7eb2Smrg  *
3*627f7eb2Smrg  *	Cube root, long double precision
4*627f7eb2Smrg  *
5*627f7eb2Smrg  *
6*627f7eb2Smrg  *
7*627f7eb2Smrg  * SYNOPSIS:
8*627f7eb2Smrg  *
9*627f7eb2Smrg  * long double x, y, cbrtq();
10*627f7eb2Smrg  *
11*627f7eb2Smrg  * y = cbrtq( x );
12*627f7eb2Smrg  *
13*627f7eb2Smrg  *
14*627f7eb2Smrg  *
15*627f7eb2Smrg  * DESCRIPTION:
16*627f7eb2Smrg  *
17*627f7eb2Smrg  * Returns the cube root of the argument, which may be negative.
18*627f7eb2Smrg  *
19*627f7eb2Smrg  * Range reduction involves determining the power of 2 of
20*627f7eb2Smrg  * the argument.  A polynomial of degree 2 applied to the
21*627f7eb2Smrg  * mantissa, and multiplication by the cube root of 1, 2, or 4
22*627f7eb2Smrg  * approximates the root to within about 0.1%.  Then Newton's
23*627f7eb2Smrg  * iteration is used three times to converge to an accurate
24*627f7eb2Smrg  * result.
25*627f7eb2Smrg  *
26*627f7eb2Smrg  *
27*627f7eb2Smrg  *
28*627f7eb2Smrg  * ACCURACY:
29*627f7eb2Smrg  *
30*627f7eb2Smrg  *                      Relative error:
31*627f7eb2Smrg  * arithmetic   domain     # trials      peak         rms
32*627f7eb2Smrg  *    IEEE       -8,8       100000      1.3e-34     3.9e-35
33*627f7eb2Smrg  *    IEEE    exp(+-707)    100000      1.3e-34     4.3e-35
34*627f7eb2Smrg  *
35*627f7eb2Smrg  */
36*627f7eb2Smrg 
37*627f7eb2Smrg /*
38*627f7eb2Smrg Cephes Math Library Release 2.2: January, 1991
39*627f7eb2Smrg Copyright 1984, 1991 by Stephen L. Moshier
40*627f7eb2Smrg Adapted for glibc October, 2001.
41*627f7eb2Smrg 
42*627f7eb2Smrg     This library is free software; you can redistribute it and/or
43*627f7eb2Smrg     modify it under the terms of the GNU Lesser General Public
44*627f7eb2Smrg     License as published by the Free Software Foundation; either
45*627f7eb2Smrg     version 2.1 of the License, or (at your option) any later version.
46*627f7eb2Smrg 
47*627f7eb2Smrg     This library is distributed in the hope that it will be useful,
48*627f7eb2Smrg     but WITHOUT ANY WARRANTY; without even the implied warranty of
49*627f7eb2Smrg     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
50*627f7eb2Smrg     Lesser General Public License for more details.
51*627f7eb2Smrg 
52*627f7eb2Smrg     You should have received a copy of the GNU Lesser General Public
53*627f7eb2Smrg     License along with this library; if not, see
54*627f7eb2Smrg     <http://www.gnu.org/licenses/>.  */
55*627f7eb2Smrg 
56*627f7eb2Smrg #include "quadmath-imp.h"
57*627f7eb2Smrg 
58*627f7eb2Smrg static const __float128 CBRT2 = 1.259921049894873164767210607278228350570251Q;
59*627f7eb2Smrg static const __float128 CBRT4 = 1.587401051968199474751705639272308260391493Q;
60*627f7eb2Smrg static const __float128 CBRT2I = 0.7937005259840997373758528196361541301957467Q;
61*627f7eb2Smrg static const __float128 CBRT4I = 0.6299605249474365823836053036391141752851257Q;
62*627f7eb2Smrg 
63*627f7eb2Smrg 
64*627f7eb2Smrg __float128
cbrtq(__float128 x)65*627f7eb2Smrg cbrtq (__float128 x)
66*627f7eb2Smrg {
67*627f7eb2Smrg   int e, rem, sign;
68*627f7eb2Smrg   __float128 z;
69*627f7eb2Smrg 
70*627f7eb2Smrg   if (!finiteq (x))
71*627f7eb2Smrg     return x + x;
72*627f7eb2Smrg 
73*627f7eb2Smrg   if (x == 0)
74*627f7eb2Smrg     return (x);
75*627f7eb2Smrg 
76*627f7eb2Smrg   if (x > 0)
77*627f7eb2Smrg     sign = 1;
78*627f7eb2Smrg   else
79*627f7eb2Smrg     {
80*627f7eb2Smrg       sign = -1;
81*627f7eb2Smrg       x = -x;
82*627f7eb2Smrg     }
83*627f7eb2Smrg 
84*627f7eb2Smrg   z = x;
85*627f7eb2Smrg  /* extract power of 2, leaving mantissa between 0.5 and 1  */
86*627f7eb2Smrg   x = frexpq (x, &e);
87*627f7eb2Smrg 
88*627f7eb2Smrg   /* Approximate cube root of number between .5 and 1,
89*627f7eb2Smrg      peak relative error = 1.2e-6  */
90*627f7eb2Smrg   x = ((((1.3584464340920900529734e-1Q * x
91*627f7eb2Smrg 	  - 6.3986917220457538402318e-1Q) * x
92*627f7eb2Smrg 	 + 1.2875551670318751538055e0Q) * x
93*627f7eb2Smrg 	- 1.4897083391357284957891e0Q) * x
94*627f7eb2Smrg        + 1.3304961236013647092521e0Q) * x + 3.7568280825958912391243e-1Q;
95*627f7eb2Smrg 
96*627f7eb2Smrg   /* exponent divided by 3 */
97*627f7eb2Smrg   if (e >= 0)
98*627f7eb2Smrg     {
99*627f7eb2Smrg       rem = e;
100*627f7eb2Smrg       e /= 3;
101*627f7eb2Smrg       rem -= 3 * e;
102*627f7eb2Smrg       if (rem == 1)
103*627f7eb2Smrg 	x *= CBRT2;
104*627f7eb2Smrg       else if (rem == 2)
105*627f7eb2Smrg 	x *= CBRT4;
106*627f7eb2Smrg     }
107*627f7eb2Smrg   else
108*627f7eb2Smrg     {				/* argument less than 1 */
109*627f7eb2Smrg       e = -e;
110*627f7eb2Smrg       rem = e;
111*627f7eb2Smrg       e /= 3;
112*627f7eb2Smrg       rem -= 3 * e;
113*627f7eb2Smrg       if (rem == 1)
114*627f7eb2Smrg 	x *= CBRT2I;
115*627f7eb2Smrg       else if (rem == 2)
116*627f7eb2Smrg 	x *= CBRT4I;
117*627f7eb2Smrg       e = -e;
118*627f7eb2Smrg     }
119*627f7eb2Smrg 
120*627f7eb2Smrg   /* multiply by power of 2 */
121*627f7eb2Smrg   x = ldexpq (x, e);
122*627f7eb2Smrg 
123*627f7eb2Smrg   /* Newton iteration */
124*627f7eb2Smrg   x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333Q;
125*627f7eb2Smrg   x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333Q;
126*627f7eb2Smrg   x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333Q;
127*627f7eb2Smrg 
128*627f7eb2Smrg   if (sign < 0)
129*627f7eb2Smrg     x = -x;
130*627f7eb2Smrg   return (x);
131*627f7eb2Smrg }
132