1 /* mpz_ior -- Logical inclusive or.
3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005 Free Software
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/. */
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;
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); */
56 if (res_ptr != op1_ptr)
57 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
59 for (i = op2_size - 1; i >= 0; i--)
60 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
65 if (ALLOC(res) < op2_size)
67 _mpz_realloc (res, op2_size);
69 /* No overlapping possible: op2_ptr = PTR(op2); */
73 if (res_ptr != op2_ptr)
74 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
76 for (i = op1_size - 1; i >= 0; i--)
77 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
84 else /* op2_size < 0 */
86 /* Fall through to the code at the end of the function. */
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);
112 opx = TMP_ALLOC_LIMBS (res_size);
113 mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
116 if (ALLOC(res) < res_size)
118 _mpz_realloc (res, res_size);
119 /* op1_ptr and op2_ptr point to temporary space. */
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)
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);
138 res_ptr[res_size] = cy;
148 SIZ(res) = -res_size;
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);
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);
179 op2_size -= op2_ptr[op2_size - 1] == 0;
181 if (ALLOC(res) < res_alloc)
183 _mpz_realloc (res, res_alloc);
185 /* op2_ptr points to temporary space. */
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)
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);
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);
219 res_ptr[res_size] = cy;
229 SIZ(res) = -res_size;