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