1 /*
2     Copyright (C) 2014 Fredrik Johansson
3 
4     This file is part of Arb.
5 
6     Arb is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #include "mag.h"
13 
14 void
mag_add(mag_t z,const mag_t x,const mag_t y)15 mag_add(mag_t z, const mag_t x, const mag_t y)
16 {
17     if (mag_is_zero(x))
18     {
19         mag_set(z, y);
20     }
21     else if (mag_is_zero(y))
22     {
23         mag_set(z, x);
24     }
25     else if (mag_is_inf(x) || mag_is_inf(y))
26     {
27         mag_inf(z);
28     }
29     else
30     {
31         slong shift;
32         shift = _fmpz_sub_small(MAG_EXPREF(x), MAG_EXPREF(y));
33 
34         if (shift == 0)
35         {
36             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x));
37             MAG_MAN(z) = MAG_MAN(x) + MAG_MAN(y);
38             MAG_ADJUST_ONE_TOO_LARGE(z); /* may need two adjustments */
39         }
40         else if (shift > 0)
41         {
42             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x));
43 
44             if (shift >= MAG_BITS)
45                 MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE;
46             else
47                 MAG_MAN(z) = MAG_MAN(x) + (MAG_MAN(y) >> shift) + LIMB_ONE;
48         }
49         else
50         {
51             shift = -shift;
52             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(y));
53 
54             if (shift >= MAG_BITS)
55                 MAG_MAN(z) = MAG_MAN(y) + LIMB_ONE;
56             else
57                 MAG_MAN(z) = MAG_MAN(y) + (MAG_MAN(x) >> shift) + LIMB_ONE;
58         }
59 
60         /* TODO: combine */
61         MAG_ADJUST_ONE_TOO_LARGE(z);
62     }
63 }
64 
65 void
mag_add_lower(mag_t z,const mag_t x,const mag_t y)66 mag_add_lower(mag_t z, const mag_t x, const mag_t y)
67 {
68     if (mag_is_zero(x))
69     {
70         mag_set(z, y);
71     }
72     else if (mag_is_zero(y))
73     {
74         mag_set(z, x);
75     }
76     else if (mag_is_inf(x) || mag_is_inf(y))
77     {
78         mag_inf(z);
79     }
80     else
81     {
82         slong shift;
83         shift = _fmpz_sub_small(MAG_EXPREF(x), MAG_EXPREF(y));
84 
85         if (shift == 0)
86         {
87             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x));
88             MAG_MAN(z) = MAG_MAN(x) + MAG_MAN(y);
89         }
90         else if (shift > 0)
91         {
92             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(x));
93 
94             if (shift >= MAG_BITS)
95                 MAG_MAN(z) = MAG_MAN(x);
96             else
97                 MAG_MAN(z) = MAG_MAN(x) + (MAG_MAN(y) >> shift);
98         }
99         else
100         {
101             shift = -shift;
102             _fmpz_set_fast(MAG_EXPREF(z), MAG_EXPREF(y));
103 
104             if (shift >= MAG_BITS)
105                 MAG_MAN(z) = MAG_MAN(y);
106             else
107                 MAG_MAN(z) = MAG_MAN(y) + (MAG_MAN(x) >> shift);
108         }
109 
110         if (MAG_MAN(z) >> MAG_BITS)
111         {
112             MAG_MAN(z) >>= 1;
113             _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(z), 1);
114         }
115     }
116 }
117