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