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