annotate libquadmath/math/tanq_kernel.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 * ====================================================
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 * Developed at SunPro, a Sun Microsystems, Inc. business.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 * Permission to use, copy, modify, and distribute this
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 * software is freely granted, provided that this notice
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 * is preserved.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 * ====================================================
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 Long double expansions are
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 and are incorporated herein by permission of the author. The author
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 reserves the right to distribute this material elsewhere under different
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 copying permissions. These modifications are distributed here under
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 the following terms:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 This library is free software; you can redistribute it and/or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 modify it under the terms of the GNU Lesser General Public
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 License as published by the Free Software Foundation; either
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 version 2.1 of the License, or (at your option) any later version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 This library is distributed in the hope that it will be useful,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 Lesser General Public License for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 You should have received a copy of the GNU Lesser General Public
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 License along with this library; if not, see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 /* __quadmath_kernel_tanq( x, y, k )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 * Input x is assumed to be bounded by ~pi/4 in magnitude.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 * Input y is the tail of x.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 * Input k indicates whether tan (if k=1) or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 * -1/tan (if k= -1) is returned.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 * Algorithm
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 * 2. if x < 2^-57, return x with inexact if x!=0.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 * 3. tan(x) is approximated by a rational form x + x^3 / 3 + x^5 R(x^2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 * on [0,0.67433].
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 * Note: tan(x+y) = tan(x) + tan'(x)*y
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 * ~ tan(x) + (1+x*x)*y
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 * Therefore, for better accuracy in computing tan(x+y), let
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 * r = x^3 * R(x^2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 * then
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 * tan(x+y) = x + (x^3 / 3 + (x^2 *(r+y)+y))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 * 4. For x in [0.67433,pi/4], let y = pi/4 - x, then
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 #include "quadmath-imp.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 static const __float128
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 one = 1,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 pio4hi = 7.8539816339744830961566084581987569936977E-1Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 pio4lo = 2.1679525325309452561992610065108379921906E-35Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 /* tan x = x + x^3 / 3 + x^5 T(x^2)/U(x^2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 0 <= x <= 0.6743316650390625
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 Peak relative error 8.0e-36 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 TH = 3.333333333333333333333333333333333333333E-1Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 T0 = -1.813014711743583437742363284336855889393E7Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 T1 = 1.320767960008972224312740075083259247618E6Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 T2 = -2.626775478255838182468651821863299023956E4Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 T3 = 1.764573356488504935415411383687150199315E2Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 T4 = -3.333267763822178690794678978979803526092E-1Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 U0 = -1.359761033807687578306772463253710042010E8Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 U1 = 6.494370630656893175666729313065113194784E7Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 U2 = -4.180787672237927475505536849168729386782E6Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 U3 = 8.031643765106170040139966622980914621521E4Q,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 U4 = -5.323131271912475695157127875560667378597E2Q;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 /* 1.000000000000000000000000000000000000000E0 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 __float128
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 __quadmath_kernel_tanq (__float128 x, __float128 y, int iy)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 __float128 z, r, v, w, s;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 int32_t ix, sign;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 ieee854_float128 u, u1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 u.value = x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 ix = u.words32.w0 & 0x7fffffff;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 if (ix < 0x3fc60000) /* x < 2**-57 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 if ((int) x == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 { /* generate inexact */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 if ((ix | u.words32.w1 | u.words32.w2 | u.words32.w3
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 | (iy + 1)) == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 return one / fabsq (x);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 else if (iy == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 math_check_force_underflow (x);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 return x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 return -one / x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 if (ix >= 0x3ffe5942) /* |x| >= 0.6743316650390625 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 if ((u.words32.w0 & 0x80000000) != 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 x = -x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 y = -y;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 sign = -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 sign = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 z = pio4hi - x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 w = pio4lo - y;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 x = z + w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 y = 0.0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 z = x * x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 r = T0 + z * (T1 + z * (T2 + z * (T3 + z * T4)));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 v = U0 + z * (U1 + z * (U2 + z * (U3 + z * (U4 + z))));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 r = r / v;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 s = z * x;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 r = y + z * (s * r + y);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 r += TH * s;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 w = x + r;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 if (ix >= 0x3ffe5942)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 v = (__float128) iy;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 w = (v - 2.0 * (x - (w * w / (w + v) - r)));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 /* SIGN is set for arguments that reach this code, but not
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 otherwise, resulting in warnings that it may be used
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 uninitialized although in the cases where it is used it has
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 always been set. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 if (sign < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 w = -w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 return w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 if (iy == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 return w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 { /* if allow error up to 2 ulp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 simply return -1.0/(x+r) here */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 /* compute -1.0/(x+r) accurately */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 u1.value = w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 u1.words32.w2 = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 u1.words32.w3 = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 v = r - (u1.value - x); /* u1+v = r+x */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 z = -1.0 / w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 u.value = z;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 u.words32.w2 = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 u.words32.w3 = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 s = 1.0 + u.value * u1.value;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 return u.value + z * (s + u.value * v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 }