Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / ieee754 / ldbl-128 / s_fma.c
blobe3cae61cf9243292a91c1b9f2add0bdbac17947c
1 /* Compute x * y + z as ternary operation.
2 Copyright (C) 2010-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Jakub Jelinek <jakub@redhat.com>, 2010.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <math.h>
21 #include <fenv.h>
22 #include <ieee754.h>
24 /* This implementation relies on long double being more than twice as
25 precise as double and uses rounding to odd in order to avoid problems
26 with double rounding.
27 See a paper by Boldo and Melquiond:
28 http://www.lri.fr/~melquion/doc/08-tc.pdf */
30 double
31 __fma (double x, double y, double z)
33 fenv_t env;
34 /* Multiplication is always exact. */
35 long double temp = (long double) x * (long double) y;
37 /* Ensure correct sign of an exact zero result by performing the
38 addition in the original rounding mode in that case. */
39 if (temp == -z)
40 return (double) temp + z;
42 union ieee854_long_double u;
43 feholdexcept (&env);
44 fesetround (FE_TOWARDZERO);
45 /* Perform addition with round to odd. */
46 u.d = temp + (long double) z;
47 if ((u.ieee.mantissa3 & 1) == 0 && u.ieee.exponent != 0x7fff)
48 u.ieee.mantissa3 |= fetestexcept (FE_INEXACT) != 0;
49 feupdateenv (&env);
50 /* And finally truncation with round to nearest. */
51 return (double) u.d;
53 #ifndef __fma
54 weak_alias (__fma, fma)
55 #endif