]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/intrinsics/trigd.c
Update copyright years.
[thirdparty/gcc.git] / libgfortran / intrinsics / trigd.c
1 /* Implementation of the degree trignometric functions COSD, SIND, TAND.
2 Copyright (C) 2020-2021 Free Software Foundation, Inc.
3 Contributed by Steven G. Kargl <kargl@gcc.gnu.org>
4
5 This file is part of the GNU Fortran runtime library (libgfortran).
6
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
11
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
25
26 #include "libgfortran.h"
27
28 #include <math.h>
29
30 /* Body of library functions which are cannot be implemented on the current
31 * platform because it lacks a capability, such as an underlying trigonometric
32 * function (sin, cos, tan) or C99 floating-point function (fabs, fmod). */
33 #define STRINGIFY_EXPAND(x) #x
34 #define ERROR_RETURN(f, k, x) runtime_error (#f " is unavailable for" \
35 " REAL(KIND=" STRINGIFY_EXPAND(k) ") because the system math library" \
36 " lacks support for it"); \
37 RETURN(x)
38
39 /*
40 For real x, let {x}_P or x_P be the closest representible number in the
41 floating point representation which uses P binary bits of fractional
42 precision (with IEEE rounding semantics).
43
44 Similarly, let f_P(x) be shorthand for {f(x)}_P.
45
46 Let ulp_P(x) be the unit of least precision for x: in other words the
47 maximal value of |a_P - b_P| where a_P <= x <= b_P and a_P != b_P.
48
49 Let x ~= y <-> | x - y | < ulp_P(x - y).
50
51 Let deg(x) be the value of x radians in degrees.
52
53 Values for each precision P were selected as follows.
54
55
56 COSD_SMALL = 2**{-N} such that for all x <= COSD_SMALL:
57
58 * cos(deg(x)) ~= 1, or equivalently:
59
60 | 1 - cos(deg(x)) | < ulp_P(1).
61
62 Unfortunately for SIND (and therefore TAND) a similar relation is only
63 possible for REAL(4) and REAL(8). With REAL(10) and REAL(16), enough
64 precision is available such that sin_P(x) != x_P for some x less than any
65 value. (There are values where this equality holds, but the distance has
66 inflection points.)
67
68 For REAL(4) and REAL(8), we can select SIND_SMALL such that:
69
70 * sin(deg(x)) ~= deg(x), or equivalently:
71
72 | deg(x) - sin(deg(x)) | < ulp_P(deg(x)).
73
74 */
75
76 #ifdef HAVE_GFC_REAL_4
77
78 /* Build _gfortran_sind_r4, _gfortran_cosd_r4, and _gfortran_tand_r4 */
79
80 #define KIND 4
81 #define TINY 0x1.p-100 /* ~= 7.889e-31 */
82 #define COSD_SMALL 0x1.p-7 /* = 7.8125e-3 */
83 #define SIND_SMALL 0x1.p-5 /* = 3.125e-2 */
84 #define COSD30 8.66025388e-01
85 #define PIO180H 1.74560547e-02 /* high 12 bits. */
86 #define PIO180L -2.76216747e-06 /* Next 24 bits. */
87
88 #if defined(HAVE_FABSF) && defined(HAVE_FMODF) && defined(HAVE_COPYSIGNF)
89
90 #ifdef HAVE_SINF
91 #define ENABLE_SIND
92 #endif
93
94 #ifdef HAVE_COSF
95 #define ENABLE_COSD
96 #endif
97
98 #ifdef HAVE_TANF
99 #define ENABLE_TAND
100 #endif
101
102 #endif /* HAVE_FABSF && HAVE_FMODF && HAVE_COPYSIGNF */
103
104 #ifdef GFC_REAL_4_INFINITY
105 #define HAVE_INFINITY_KIND
106 #endif
107
108 #include "trigd_lib.inc"
109
110 #undef KIND
111 #undef TINY
112 #undef COSD_SMALL
113 #undef SIND_SMALL
114 #undef COSD30
115 #undef PIO180H
116 #undef PIO180L
117 #undef ENABLE_SIND
118 #undef ENABLE_COSD
119 #undef ENABLE_TAND
120 #undef HAVE_INFINITY_KIND
121
122 #endif /* HAVE_GFC_REAL_4... */
123
124
125 #ifdef HAVE_GFC_REAL_8
126
127 /* Build _gfortran_sind_r8, _gfortran_cosd_r8, and _gfortran_tand_r8 */
128
129 #define KIND 8
130 #define TINY 0x1.p-1000 /* ~= 9.33e-302 (min exp -1074) */
131 #define COSD_SMALL 0x1.p-21 /* ~= 4.768e-7 */
132 #define SIND_SMALL 0x1.p-19 /* ~= 9.537e-7 */
133 #define COSD30 8.6602540378443860e-01
134 #define PIO180H 1.7453283071517944e-02 /* high 21 bits. */
135 #define PIO180L 9.4484253514332993e-09 /* Next 53 bits. */
136
137 #if defined(HAVE_FABS) && defined(HAVE_FMOD) && defined(HAVE_COPYSIGN)
138
139 #ifdef HAVE_SIN
140 #define ENABLE_SIND
141 #endif
142
143 #ifdef HAVE_COS
144 #define ENABLE_COSD
145 #endif
146
147 #ifdef HAVE_TAN
148 #define ENABLE_TAND
149 #endif
150
151 #endif /* HAVE_FABS && HAVE_FMOD && HAVE_COPYSIGN */
152
153 #ifdef GFC_REAL_8_INFINITY
154 #define HAVE_INFINITY_KIND
155 #endif
156
157 #include "trigd_lib.inc"
158
159 #undef KIND
160 #undef TINY
161 #undef COSD_SMALL
162 #undef SIND_SMALL
163 #undef COSD30
164 #undef PIO180H
165 #undef PIO180L
166 #undef ENABLE_SIND
167 #undef ENABLE_COSD
168 #undef ENABLE_TAND
169 #undef HAVE_INFINITY_KIND
170
171 #endif /* HAVE_GFC_REAL_8... */
172
173
174 #ifdef HAVE_GFC_REAL_10
175
176 /* Build _gfortran_sind_r10, _gfortran_cosd_r10, and _gfortran_tand_r10 */
177
178 #define KIND 10
179 #define TINY 0x1.p-16400 /* ~= 1.28e-4937 (min exp -16494) */
180 #define COSD_SMALL 0x1.p-26 /* ~= 1.490e-8 */
181 #undef SIND_SMALL /* not precise */
182 #define COSD30 8.66025403784438646787e-01
183 #define PIO180H 1.74532925229868851602e-02 /* high 32 bits */
184 #define PIO180L -3.04358939097084072823e-12 /* Next 64 bits */
185
186 #if defined(HAVE_FABSL) && defined(HAVE_FMODL) && defined(HAVE_COPYSIGNL)
187
188 #ifdef HAVE_SINL
189 #define ENABLE_SIND
190 #endif
191
192 #ifdef HAVE_COSL
193 #define ENABLE_COSD
194 #endif
195
196 #ifdef HAVE_TANL
197 #define ENABLE_TAND
198 #endif
199
200 #endif /* HAVE_FABSL && HAVE_FMODL && HAVE_COPYSIGNL */
201
202 #ifdef GFC_REAL_10_INFINITY
203 #define HAVE_INFINITY_KIND
204 #endif
205
206 #include "trigd_lib.inc"
207
208 #undef KIND
209 #undef TINY
210 #undef COSD_SMALL
211 #undef SIND_SMALL
212 #undef COSD30
213 #undef PIO180H
214 #undef PIO180L
215 #undef ENABLE_SIND
216 #undef ENABLE_COSD
217 #undef ENABLE_TAND
218 #undef HAVE_INFINITY_KIND
219
220 #endif /* HAVE_GFC_REAL_10 */
221
222
223 #ifdef HAVE_GFC_REAL_16
224
225 /* Build _gfortran_sind_r16, _gfortran_cosd_r16, and _gfortran_tand_r16 */
226
227 #define KIND 16
228 #define TINY 0x1.p-16400 /* ~= 1.28e-4937 */
229 #undef SIND_SMALL /* not precise */
230
231 #if GFC_REAL_16_DIGITS == 64
232 /* 80 bit precision, use constants from REAL(10). */
233 #define COSD_SMALL 0x1.p-26 /* ~= 1.490e-8 */
234 #define COSD30 8.66025403784438646787e-01
235 #define PIO180H 1.74532925229868851602e-02 /* high 32 bits */
236 #define PIO180L -3.04358939097084072823e-12 /* Next 64 bits */
237
238 #else
239 /* Proper float128 precision. */
240 #define COSD_SMALL 0x1.p-51 /* ~= 4.441e-16 */
241 #define COSD30 8.66025403784438646763723170752936183e-01
242 #define PIO180H 1.74532925199433197605003442731685936e-02
243 #define PIO180L -2.39912634365882824665106671063098954e-17
244 #endif
245
246 #ifdef GFC_REAL_16_IS_LONG_DOUBLE
247
248 #if defined(HAVE_FABSL) && defined(HAVE_FMODL) && defined(HAVE_COPYSIGNL)
249
250 #ifdef HAVE_SINL
251 #define ENABLE_SIND
252 #endif
253
254 #ifdef HAVE_COSL
255 #define ENABLE_COSD
256 #endif
257
258 #ifdef HAVE_TANL
259 #define ENABLE_TAND
260 #endif
261
262 #endif /* HAVE_FABSL && HAVE_FMODL && HAVE_COPYSIGNL */
263
264 #else
265
266 /* libquadmath: HAVE_*Q are never defined. They must be available. */
267 #define ENABLE_SIND
268 #define ENABLE_COSD
269 #define ENABLE_TAND
270
271 #endif /* GFC_REAL_16_IS_LONG_DOUBLE */
272
273 #ifdef GFC_REAL_16_INFINITY
274 #define HAVE_INFINITY_KIND
275 #endif
276
277 #include "trigd_lib.inc"
278
279 #undef KIND
280 #undef TINY
281 #undef COSD_SMALL
282 #undef SIND_SMALL
283 #undef COSD30
284 #undef PIO180H
285 #undef PIO180L
286 #undef ENABLE_SIND
287 #undef ENABLE_COSD
288 #undef ENABLE_TAND
289 #undef HAVE_INFINITY_KIND
290
291 #endif /* HAVE_GFC_REAL_16 */