1 /* mpf_add -- Add two floats.
3 Copyright 1993, 1994, 1996, 2000, 2001, 2005 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of either:
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
16 * the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any
20 or both in parallel, as here.
22 The GNU MP Library is distributed in the hope that it will be useful, but
23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 You should have received copies of the GNU General Public License and the
28 GNU Lesser General Public License along with the GNU MP Library. If not,
29 see https://www.gnu.org/licenses/. */
35 mpf_add (mpf_ptr r
, mpf_srcptr u
, mpf_srcptr v
)
39 mp_size_t usize
, vsize
, rsize
;
50 /* Handle special cases that don't work in generic code below. */
64 /* If signs of U and V are different, perform subtraction. */
65 if ((usize
^ vsize
) < 0)
67 __mpf_struct v_negated
;
68 v_negated
._mp_size
= -vsize
;
69 v_negated
._mp_exp
= v
->_mp_exp
;
70 v_negated
._mp_d
= v
->_mp_d
;
71 mpf_sub (r
, u
, &v_negated
);
77 /* Signs are now known to be the same. */
80 /* Make U be the operand with the largest exponent. */
81 if (u
->_mp_exp
< v
->_mp_exp
)
96 ediff
= u
->_mp_exp
- v
->_mp_exp
;
98 /* If U extends beyond PREC, ignore the part that does. */
105 /* If V extends beyond PREC, ignore the part that does.
106 Note that this may make vsize negative. */
107 if (vsize
+ ediff
> prec
)
109 vp
+= vsize
+ ediff
- prec
;
110 vsize
= prec
- ediff
;
114 /* Locate the least significant non-zero limb in (the needed parts
115 of) U and V, to simplify the code below. */
122 /* Allocate temp space for the result. Allocate
123 just vsize + ediff later??? */
124 tp
= TMP_ALLOC_LIMBS (prec
);
128 /* V completely cancelled. */
130 MPN_COPY_INCR (rp
, up
, usize
);
135 /* uuuu | uuuu | uuuu | uuuu | uuuu */
136 /* vvvvvvv | vv | vvvvv | v | vv */
140 /* U and V partially overlaps. */
141 if (vsize
+ ediff
<= usize
)
146 size
= usize
- ediff
- vsize
;
147 MPN_COPY (tp
, up
, size
);
148 cy
= mpn_add (tp
+ size
, up
+ size
, usize
- size
, vp
, vsize
);
156 size
= vsize
+ ediff
- usize
;
157 MPN_COPY (tp
, vp
, size
);
158 cy
= mpn_add (tp
+ size
, up
, usize
, vp
+ size
, usize
- ediff
);
159 rsize
= vsize
+ ediff
;
167 size
= vsize
+ ediff
- usize
;
168 MPN_COPY (tp
, vp
, vsize
);
169 MPN_ZERO (tp
+ vsize
, ediff
- usize
);
170 MPN_COPY (tp
+ size
, up
, usize
);
172 rsize
= size
+ usize
;
175 MPN_COPY (rp
, tp
, rsize
);
181 r
->_mp_size
= negate
? -rsize
: rsize
;