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