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