]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/intrinsics/c99_functions.c
re PR libfortran/19280 (Inconsistent licensing of libgfortran)
[thirdparty/gcc.git] / libgfortran / intrinsics / c99_functions.c
CommitLineData
a2a2059f
BD
1/* Implementation of various C99 functions
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4This file is part of the GNU Fortran 95 runtime library (libgfortran).
5
6Libgfortran is free software; you can redistribute it and/or
57dea9f6 7modify it under the terms of the GNU General Public
a2a2059f 8License as published by the Free Software Foundation; either
57dea9f6
TM
9version 2 of the License, or (at your option) any later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file into combinations with other programs,
14and to distribute those combinations without any restriction coming
15from the use of this file. (The General Public License restrictions
16do apply in other respects; for example, they cover modification of
17the file, and distribution when not linked into a combine
18executable.)
a2a2059f
BD
19
20Libgfortran is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57dea9f6 23GNU General Public License for more details.
a2a2059f 24
57dea9f6
TM
25You should have received a copy of the GNU General Public
26License along with libgfortran; see the file COPYING. If not,
a2a2059f
BD
27write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28Boston, MA 02111-1307, USA. */
29
30#include "config.h"
31#include <sys/types.h>
453310d8 32#include <float.h>
a2a2059f
BD
33#include <math.h>
34#include "libgfortran.h"
35
36
453310d8
RS
37#ifndef HAVE_ACOSF
38float
39acosf(float x)
40{
41 return (float) acos(x);
42}
43#endif
44
45#ifndef HAVE_ASINF
46float
47asinf(float x)
48{
49 return (float) asin(x);
50}
51#endif
52
53#ifndef HAVE_ATAN2F
54float
55atan2f(float y, float x)
56{
57 return (float) atan2(y, x);
58}
59#endif
60
61#ifndef HAVE_ATANF
62float
63atanf(float x)
64{
65 return (float) atan(x);
66}
67#endif
68
69#ifndef HAVE_CEILF
70float
71ceilf(float x)
72{
73 return (float) ceil(x);
74}
75#endif
76
77#ifndef HAVE_COPYSIGNF
78float
79copysignf(float x, float y)
80{
81 return (float) copysign(x, y);
82}
83#endif
84
85#ifndef HAVE_COSF
86float
87cosf(float x)
88{
89 return (float) cos(x);
90}
91#endif
92
93#ifndef HAVE_COSHF
94float
95coshf(float x)
96{
97 return (float) cosh(x);
98}
99#endif
100
101#ifndef HAVE_EXPF
102float
103expf(float x)
104{
105 return (float) exp(x);
106}
107#endif
108
6e4d9244
EB
109#ifndef HAVE_FABSF
110float
111fabsf(float x)
112{
113 return (float) fabs(x);
114}
115#endif
116
453310d8
RS
117#ifndef HAVE_FLOORF
118float
119floorf(float x)
120{
121 return (float) floor(x);
122}
123#endif
124
125#ifndef HAVE_FREXPF
126float
127frexpf(float x, int *exp)
128{
129 return (float) frexp(x, exp);
130}
131#endif
132
133#ifndef HAVE_HYPOTF
134float
135hypotf(float x, float y)
136{
137 return (float) hypot(x, y);
138}
139#endif
140
141#ifndef HAVE_LOGF
142float
143logf(float x)
144{
145 return (float) log(x);
146}
147#endif
148
149#ifndef HAVE_LOG10F
150float
151log10f(float x)
152{
153 return (float) log10(x);
154}
155#endif
156
157#ifndef HAVE_SCALBNF
158float
159scalbnf(float x, int y)
160{
161 return (float) scalbn(x, y);
162}
163#endif
164
165#ifndef HAVE_SINF
166float
167sinf(float x)
168{
169 return (float) sin(x);
170}
171#endif
172
173#ifndef HAVE_SINHF
174float
175sinhf(float x)
176{
177 return (float) sinh(x);
178}
179#endif
180
181#ifndef HAVE_SQRTF
182float
183sqrtf(float x)
184{
185 return (float) sqrt(x);
186}
187#endif
188
189#ifndef HAVE_TANF
190float
191tanf(float x)
192{
193 return (float) tan(x);
194}
195#endif
196
197#ifndef HAVE_TANHF
198float
199tanhf(float x)
200{
201 return (float) tanh(x);
202}
203#endif
204
205#ifndef HAVE_NEXTAFTERF
206/* This is a portable implementation of nextafterf that is intended to be
207 independent of the floating point format or its in memory representation.
067a5735 208 This implementation works correctly with denormalized values. */
453310d8
RS
209float
210nextafterf(float x, float y)
211{
067a5735
RS
212 /* This variable is marked volatile to avoid excess precision problems
213 on some platforms, including IA-32. */
214 volatile float delta;
215 float absx, denorm_min;
453310d8
RS
216
217 if (isnan(x) || isnan(y))
067a5735 218 return x + y;
453310d8
RS
219 if (x == y)
220 return x;
221
067a5735
RS
222 /* absx = fabsf (x); */
223 absx = (x < 0.0) ? -x : x;
453310d8 224
067a5735
RS
225 /* __FLT_DENORM_MIN__ is non-zero iff the target supports denormals. */
226 if (__FLT_DENORM_MIN__ == 0.0f)
227 denorm_min = __FLT_MIN__;
228 else
229 denorm_min = __FLT_DENORM_MIN__;
230
231 if (absx < __FLT_MIN__)
232 delta = denorm_min;
453310d8
RS
233 else
234 {
067a5735
RS
235 float frac;
236 int exp;
237
238 /* Discard the fraction from x. */
239 frac = frexpf (absx, &exp);
240 delta = scalbnf (0.5f, exp);
241
242 /* Scale x by the epsilon of the representation. By rights we should
243 have been able to combine this with scalbnf, but some targets don't
244 get that correct with denormals. */
245 delta *= __FLT_EPSILON__;
246
247 /* If we're going to be reducing the absolute value of X, and doing so
248 would reduce the exponent of X, then the delta to be applied is
249 one exponent smaller. */
250 if (frac == 0.5f && (y < x) == (x > 0))
251 delta *= 0.5f;
252
253 /* If that underflows to zero, then we're back to the minimum. */
254 if (delta == 0.0f)
255 delta = denorm_min;
453310d8 256 }
067a5735
RS
257
258 if (y < x)
259 delta = -delta;
260
261 return x + delta;
453310d8
RS
262}
263#endif
264
bf4d99cf
TS
265
266#ifndef HAVE_POWF
267float
268powf(float x, float y)
269{
270 return (float) pow(x, y);
271}
272#endif
273
69d3c9a4 274/* Note that if fpclassify is not defined, then NaN is not handled */
bc20e36d 275
a2a2059f
BD
276/* Algorithm by Steven G. Kargl. */
277
278#ifndef HAVE_ROUND
279/* Round to nearest integral value. If the argument is halfway between two
280 integral values then round away from zero. */
281
282double
283round(double x)
284{
285 double t;
69d3c9a4 286#if defined(fpclassify)
a2a2059f 287 int i;
a2a2059f
BD
288 i = fpclassify(x);
289 if (i == FP_INFINITE || i == FP_NAN)
290 return (x);
bc20e36d 291#endif
a2a2059f
BD
292
293 if (x >= 0.0)
294 {
295 t = ceil(x);
296 if (t - x > 0.5)
297 t -= 1.0;
298 return (t);
299 }
300 else
301 {
302 t = ceil(-x);
303 if (t + x > 0.5)
304 t -= 1.0;
305 return (-t);
306 }
307}
308#endif
309
310#ifndef HAVE_ROUNDF
311/* Round to nearest integral value. If the argument is halfway between two
312 integral values then round away from zero. */
313
314float
315roundf(float x)
316{
317 float t;
69d3c9a4 318#if defined(fpclassify)
a2a2059f
BD
319 int i;
320
321 i = fpclassify(x);
322 if (i == FP_INFINITE || i == FP_NAN)
323 return (x);
bc20e36d 324#endif
a2a2059f
BD
325
326 if (x >= 0.0)
327 {
328 t = ceilf(x);
329 if (t - x > 0.5)
330 t -= 1.0;
331 return (t);
332 }
333 else
334 {
335 t = ceilf(-x);
336 if (t + x > 0.5)
337 t -= 1.0;
338 return (-t);
339 }
340}
341#endif