Annotation of OpenXM_contrib/gmp/mpfr/fma.c, Revision 1.1.1.1
1.1 ohara 1: /* mpfr_fma -- Floating multiply-add
2:
3: Copyright 2001, 2002 Free Software Foundation, Inc.
4:
5: This file is part of the MPFR Library.
6:
7: The MPFR Library is free software; you can redistribute
8: it and/or modify it under the terms of the GNU Lesser
9: General Public License as published by the Free Software
10: Foundation; either version 2.1 of the License, or (at your
11: option) any later version.
12:
13: The MPFR Library is distributed in the hope that it will
14: be useful, but WITHOUT ANY WARRANTY; without even the
15: implied warranty of MERCHANTABILITY or FITNESS FOR A
16: PARTICULAR PURPOSE. See the GNU Lesser General Public
17: License for more details.
18:
19: You should have received a copy of the GNU Lesser
20: General Public License along with the MPFR Library; see
21: the file COPYING.LIB. If not, write to the Free Software
22: Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23: MA 02111-1307, USA. */
24:
25: #include "gmp.h"
26: #include "gmp-impl.h"
27: #include "mpfr.h"
28: #include "mpfr-impl.h"
29:
30:
31: /* The computation of fma of x y and u is done by
32: fma(s,x,y,z)= z + x*y = s
33: */
34:
35: int
36: mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z,
37: mp_rnd_t rnd_mode)
38: {
39: int inexact;
40: mpfr_t u;
41:
42: /* particular cases */
43: if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y) || MPFR_IS_NAN(z))
44: {
45: MPFR_SET_NAN(s);
46: MPFR_RET_NAN;
47: }
48:
49: if (MPFR_IS_INF(x) || MPFR_IS_INF(y))
50: {
51: /* cases Inf*0+z, 0*Inf+z, Inf-Inf */
52: if ((MPFR_IS_FP(y) && MPFR_IS_ZERO(y)) ||
53: (MPFR_IS_FP(x) && MPFR_IS_ZERO(x)) ||
54: (MPFR_IS_INF(z) && ((MPFR_SIGN(x) * MPFR_SIGN(y)) != MPFR_SIGN(z))))
55: {
56: MPFR_SET_NAN(s);
57: MPFR_RET_NAN;
58: }
59:
60: MPFR_CLEAR_NAN(s);
61:
62: if (MPFR_IS_INF(z)) /* case Inf-Inf already checked above */
63: {
64: MPFR_SET_INF(s);
65: MPFR_SET_SAME_SIGN(s, z);
66: MPFR_RET(0);
67: }
68: else /* z is finite */
69: {
70: MPFR_SET_INF(s);
71: if (MPFR_SIGN(s) != (MPFR_SIGN(x) * MPFR_SIGN(y)))
72: MPFR_CHANGE_SIGN(s);
73: MPFR_RET(0);
74: }
75: }
76:
77: MPFR_CLEAR_NAN(s);
78:
79: /* now x and y are finite */
80: if (MPFR_IS_INF(z))
81: {
82: MPFR_SET_INF(s);
83: MPFR_SET_SAME_SIGN(s, z);
84: MPFR_RET(0);
85: }
86:
87: MPFR_CLEAR_INF(s);
88:
89: if (MPFR_IS_ZERO(x) || MPFR_IS_ZERO(y))
90: {
91: if (MPFR_IS_ZERO(z))
92: {
93: int sign_p, sign_z;
94: sign_p = MPFR_SIGN(x) * MPFR_SIGN(y);
95: sign_z = MPFR_SIGN(z);
96: if (MPFR_SIGN(s) !=
97: (rnd_mode != GMP_RNDD ?
98: ((sign_p < 0 && sign_z < 0) ? -1 : 1) :
99: ((sign_p > 0 && sign_z > 0) ? 1 : -1)))
100: {
101: MPFR_CHANGE_SIGN(s);
102: }
103: MPFR_SET_ZERO(s);
104: MPFR_RET(0);
105: }
106: else
107: return mpfr_set (s, z, rnd_mode);
108: }
109:
110: if (MPFR_IS_ZERO(z))
111: return mpfr_mul (s, x, y, rnd_mode);
112:
113: /* if we take prec(u) >= prec(x) + prec(y), the product
114: u <- x*y is always exact */
115: mpfr_init2 (u, MPFR_PREC(x) + MPFR_PREC(y));
116: mpfr_mul (u, x, y, GMP_RNDN); /* always exact */
117: inexact = mpfr_add (s, z, u, rnd_mode);
118: mpfr_clear(u);
119:
120: return inexact;
121: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>