top(1): Raise WARNS to 6 and fix warnings.
[dragonfly.git] / contrib / gmp / mpz / ior.c
blob26362c94289d500204d40872fd5c11407cc6668f
1 /* mpz_ior -- Logical inclusive or.
3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005 Free Software
4 Foundation, Inc.
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MP Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 #include "gmp.h"
22 #include "gmp-impl.h"
24 void
25 mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
27 mp_srcptr op1_ptr, op2_ptr;
28 mp_size_t op1_size, op2_size;
29 mp_ptr res_ptr;
30 mp_size_t res_size;
31 mp_size_t i;
32 TMP_DECL;
34 TMP_MARK;
35 op1_size = SIZ(op1);
36 op2_size = SIZ(op2);
38 op1_ptr = PTR(op1);
39 op2_ptr = PTR(op2);
40 res_ptr = PTR(res);
42 if (op1_size >= 0)
44 if (op2_size >= 0)
46 if (op1_size >= op2_size)
48 if (ALLOC(res) < op1_size)
50 _mpz_realloc (res, op1_size);
51 /* No overlapping possible: op1_ptr = PTR(op1); */
52 op2_ptr = PTR(op2);
53 res_ptr = PTR(res);
56 if (res_ptr != op1_ptr)
57 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
58 op1_size - op2_size);
59 for (i = op2_size - 1; i >= 0; i--)
60 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
61 res_size = op1_size;
63 else
65 if (ALLOC(res) < op2_size)
67 _mpz_realloc (res, op2_size);
68 op1_ptr = PTR(op1);
69 /* No overlapping possible: op2_ptr = PTR(op2); */
70 res_ptr = PTR(res);
73 if (res_ptr != op2_ptr)
74 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
75 op2_size - op1_size);
76 for (i = op1_size - 1; i >= 0; i--)
77 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
78 res_size = op2_size;
81 SIZ(res) = res_size;
82 return;
84 else /* op2_size < 0 */
86 /* Fall through to the code at the end of the function. */
89 else
91 if (op2_size < 0)
93 mp_ptr opx;
94 mp_limb_t cy;
96 /* Both operands are negative, so will be the result.
97 -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
98 = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
99 = ((OP1 - 1) & (OP2 - 1)) + 1 */
101 op1_size = -op1_size;
102 op2_size = -op2_size;
104 res_size = MIN (op1_size, op2_size);
106 /* Possible optimization: Decrease mpn_sub precision,
107 as we won't use the entire res of both. */
108 opx = TMP_ALLOC_LIMBS (res_size);
109 mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
110 op1_ptr = opx;
112 opx = TMP_ALLOC_LIMBS (res_size);
113 mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
114 op2_ptr = opx;
116 if (ALLOC(res) < res_size)
118 _mpz_realloc (res, res_size);
119 /* op1_ptr and op2_ptr point to temporary space. */
120 res_ptr = PTR(res);
123 /* First loop finds the size of the result. */
124 for (i = res_size - 1; i >= 0; i--)
125 if ((op1_ptr[i] & op2_ptr[i]) != 0)
126 break;
127 res_size = i + 1;
129 if (res_size != 0)
131 /* Second loop computes the real result. */
132 for (i = res_size - 1; i >= 0; i--)
133 res_ptr[i] = op1_ptr[i] & op2_ptr[i];
135 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
136 if (cy)
138 res_ptr[res_size] = cy;
139 res_size++;
142 else
144 res_ptr[0] = 1;
145 res_size = 1;
148 SIZ(res) = -res_size;
149 TMP_FREE;
150 return;
152 else
154 /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
155 through to the code that handles OP1 | -OP2. */
156 MPZ_SRCPTR_SWAP (op1, op2);
157 MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size);
162 mp_ptr opx;
163 mp_limb_t cy;
164 mp_size_t res_alloc;
165 mp_size_t count;
167 /* Operand 2 negative, so will be the result.
168 -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
169 = ~(OP1 | ~(OP2 - 1)) + 1 =
170 = (~OP1 & (OP2 - 1)) + 1 */
172 op2_size = -op2_size;
174 res_alloc = op2_size;
176 opx = TMP_ALLOC_LIMBS (op2_size);
177 mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
178 op2_ptr = opx;
179 op2_size -= op2_ptr[op2_size - 1] == 0;
181 if (ALLOC(res) < res_alloc)
183 _mpz_realloc (res, res_alloc);
184 op1_ptr = PTR(op1);
185 /* op2_ptr points to temporary space. */
186 res_ptr = PTR(res);
189 if (op1_size >= op2_size)
191 /* We can just ignore the part of OP1 that stretches above OP2,
192 because the result limbs are zero there. */
194 /* First loop finds the size of the result. */
195 for (i = op2_size - 1; i >= 0; i--)
196 if ((~op1_ptr[i] & op2_ptr[i]) != 0)
197 break;
198 res_size = i + 1;
199 count = res_size;
201 else
203 res_size = op2_size;
205 /* Copy the part of OP2 that stretches above OP1, to RES. */
206 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
207 count = op1_size;
210 if (res_size != 0)
212 /* Second loop computes the real result. */
213 for (i = count - 1; i >= 0; i--)
214 res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
216 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
217 if (cy)
219 res_ptr[res_size] = cy;
220 res_size++;
223 else
225 res_ptr[0] = 1;
226 res_size = 1;
229 SIZ(res) = -res_size;
231 TMP_FREE;