1 /* mpz_and -- Logical and.
3 Copyright (C) 1991 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 the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 The GNU MP Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with the GNU MP Library; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #define min(l,o) ((l) < (o) ? (l) : (o))
25 #define max(h,i) ((h) > (i) ? (h) : (i))
29 mpz_and (MP_INT *res, const MP_INT *op1, const MP_INT *op2)
31 mpz_and (res, op1, op2)
37 mp_srcptr op1_ptr, op2_ptr;
38 mp_size op1_size, op2_size;
54 res_size = min (op1_size, op2_size);
55 /* First loop finds the size of the result. */
56 for (i = res_size - 1; i >= 0; i--)
57 if ((op1_ptr[i] & op2_ptr[i]) != 0)
61 /* Handle allocation, now when we know exactly how much space is
62 needed for the result. */
63 if (res->alloc < res_size)
65 _mpz_realloc (res, res_size);
71 /* Second loop computes the real result. */
72 for (i = res_size - 1; i >= 0; i--)
73 res_ptr[i] = op1_ptr[i] & op2_ptr[i];
78 else /* op2_size < 0 */
79 /* Fall through to the code at the end of the function. */
91 /* Both operands are negative, so will be the result.
92 -((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) =
93 = ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 =
94 = ((OP1 - 1) | (OP2 - 1)) + 1 */
99 res_alloc = 1 + max (op1_size, op2_size);
101 opx = (mp_ptr) alloca (op1_size * BYTES_PER_MP_LIMB);
102 op1_size += mpn_sub (opx, op1_ptr, op1_size, &one, 1);
105 opx = (mp_ptr) alloca (op2_size * BYTES_PER_MP_LIMB);
106 op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 1);
109 if (res->alloc < res_alloc)
111 _mpz_realloc (res, res_alloc);
113 /* Don't re-read OP1_PTR and OP2_PTR. They point to
114 temporary space--never to the space RES->D used
115 to point to before reallocation. */
118 if (op1_size >= op2_size)
120 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
121 op1_size - op2_size);
122 for (i = op2_size - 1; i >= 0; i--)
123 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
128 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
129 op2_size - op1_size);
130 for (i = op1_size - 1; i >= 0; i--)
131 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
137 cy = mpn_add (res_ptr, res_ptr, res_size, &one, 1);
140 res_ptr[res_size] = cy;
150 res->size = -res_size;
155 /* We should compute -OP1 & OP2. Swap OP1 and OP2 and fall
156 through to the code that handles OP1 & -OP2. */
157 {const MP_INT *t = op1; op1 = op2; op2 = t;}
158 {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
159 {mp_size t = op1_size; op1_size = op2_size; op2_size = t;}
168 /* OP2 must be negated as with infinite precision.
170 Scan from the low end for a non-zero limb. The first non-zero
171 limb is simply negated (two's complement). Any subsequent
172 limbs are one's complemented. Of course, we don't need to
173 handle more limbs than there are limbs in the other, positive
174 operand as the result for those limbs is going to become zero
177 /* Scan for the least significant. non-zero OP2 limb, and zero the
178 result meanwhile for those limb positions. (We will surely
179 find a non-zero limb, so we can write the loop with one
180 termination condition only.) */
181 for (i = 0; op2_ptr[i] == 0; i++)
185 op2_size = -op2_size;
187 if (op1_size <= op2_size)
189 /* The ones-extended OP2 is >= than the zero-extended OP1.
190 RES_SIZE <= OP1_SIZE. Find the exact size. */
191 for (i = op1_size - 1; i > op2_lim; i--)
192 if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
198 /* The ones-extended OP2 is < than the zero-extended OP1.
199 RES_SIZE == OP1_SIZE, since OP1 is normalized. */
204 /* OP1 is positive and zero-extended,
205 OP2 is negative and ones-extended.
206 The result will be positive.
207 OP1 & -OP2 = OP1 & ~(OP2 - 1). */
210 const mp_limb one = 1;
212 op2_size = -op2_size;
213 opx = (mp_ptr) alloca (op2_size * BYTES_PER_MP_LIMB);
214 op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 1);
217 if (op1_size > op2_size)
219 /* The result has the same size as OP1, since OP1 is normalized
220 and longer than the ones-extended OP2. */
223 /* Handle allocation, now when we know exactly how much space is
224 needed for the result. */
225 if (res->alloc < res_size)
227 _mpz_realloc (res, res_size);
230 /* Don't re-read OP2_PTR. It points to temporary space--never
231 to the space RES->D used to point to before reallocation. */
234 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
235 res_size - op2_size);
236 for (i = op2_size - 1; i >= 0; i--)
237 res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
239 res->size = res_size;
243 /* Find out the exact result size. Ignore the high limbs of OP2,
244 OP1 is zero-extended and would make the result zero. */
245 for (i = op1_size - 1; i >= 0; i--)
246 if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
250 /* Handle allocation, now when we know exactly how much space is
251 needed for the result. */
252 if (res->alloc < res_size)
254 _mpz_realloc (res, res_size);
257 /* Don't re-read OP2_PTR. It points to temporary space--never
258 to the space RES->D used to point to before reallocation. */
261 for (i = res_size - 1; i >= 0; i--)
262 res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
264 res->size = res_size;