]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/ieee754/ldbl-128/s_fma.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / ieee754 / ldbl-128 / s_fma.c
CommitLineData
5e908464 1/* Compute x * y + z as ternary operation.
b168057a 2 Copyright (C) 2010-2015 Free Software Foundation, Inc.
5e908464
JJ
3 This file is part of the GNU C Library.
4 Contributed by Jakub Jelinek <jakub@redhat.com>, 2010.
5
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.
10
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.
15
16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
5e908464
JJ
19
20#include <math.h>
21#include <fenv.h>
22#include <ieee754.h>
23
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 */
29
30double
31__fma (double x, double y, double z)
32{
33 fenv_t env;
34 /* Multiplication is always exact. */
35 long double temp = (long double) x * (long double) y;
8ec5b013
JM
36
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;
41
5e908464
JJ
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;
52}
53#ifndef __fma
54weak_alias (__fma, fma)
55#endif