1/* mpfr_add -- add two floating-point numbers
2
3Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4Contributed by the AriC and Caramel projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include "mpfr-impl.h"
24
25int
26mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
27{
28  MPFR_LOG_FUNC
29    (("b[%Pu]=%.*Rg c[%Pu]=%.*Rg rnd=%d",
30      mpfr_get_prec (b), mpfr_log_prec, b,
31      mpfr_get_prec (c), mpfr_log_prec, c, rnd_mode),
32     ("a[%Pu]=%.*Rg", mpfr_get_prec (a), mpfr_log_prec, a));
33
34  if (MPFR_ARE_SINGULAR(b,c))
35    {
36      if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
37        {
38          MPFR_SET_NAN(a);
39          MPFR_RET_NAN;
40        }
41      /* neither b nor c is NaN here */
42      else if (MPFR_IS_INF(b))
43        {
44          if (!MPFR_IS_INF(c) || MPFR_SIGN(b) == MPFR_SIGN(c))
45            {
46              MPFR_SET_INF(a);
47              MPFR_SET_SAME_SIGN(a, b);
48              MPFR_RET(0); /* exact */
49            }
50          else
51            {
52              MPFR_SET_NAN(a);
53              MPFR_RET_NAN;
54            }
55        }
56      else if (MPFR_IS_INF(c))
57          {
58            MPFR_SET_INF(a);
59            MPFR_SET_SAME_SIGN(a, c);
60            MPFR_RET(0); /* exact */
61          }
62      /* now either b or c is zero */
63      else if (MPFR_IS_ZERO(b))
64        {
65          if (MPFR_IS_ZERO(c))
66            {
67              /* for round away, we take the same convention for 0 + 0
68                 as for round to zero or to nearest: it always gives +0,
69                 except (-0) + (-0) = -0. */
70              MPFR_SET_SIGN(a,
71                            (rnd_mode != MPFR_RNDD ?
72                             ((MPFR_IS_NEG(b) && MPFR_IS_NEG(c)) ? -1 : 1) :
73                             ((MPFR_IS_POS(b) && MPFR_IS_POS(c)) ? 1 : -1)));
74              MPFR_SET_ZERO(a);
75              MPFR_RET(0); /* 0 + 0 is exact */
76            }
77          return mpfr_set (a, c, rnd_mode);
78        }
79      else
80        {
81          MPFR_ASSERTD(MPFR_IS_ZERO(c));
82          return mpfr_set (a, b, rnd_mode);
83        }
84    }
85
86  MPFR_ASSERTD (MPFR_IS_PURE_FP (b));
87  MPFR_ASSERTD (MPFR_IS_PURE_FP (c));
88
89  if (MPFR_UNLIKELY(MPFR_SIGN(b) != MPFR_SIGN(c)))
90    { /* signs differ, it is a subtraction */
91      if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
92                      && MPFR_PREC(b) == MPFR_PREC(c)))
93        return mpfr_sub1sp(a, b, c, rnd_mode);
94      else
95        return mpfr_sub1(a, b, c, rnd_mode);
96    }
97  else
98    { /* signs are equal, it's an addition */
99      if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
100                      && MPFR_PREC(b) == MPFR_PREC(c)))
101        if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
102          return mpfr_add1sp(a, c, b, rnd_mode);
103        else
104          return mpfr_add1sp(a, b, c, rnd_mode);
105      else
106        if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
107          return mpfr_add1(a, c, b, rnd_mode);
108        else
109          return mpfr_add1(a, b, c, rnd_mode);
110    }
111}
112