1 /* mpz_ior -- Logical inclusive or.
3 Copyright (C) 1991, 1993, 1994, 1996 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 Library General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 MA 02111-1307, USA. */
27 mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
29 mpz_ior (res, op1, op2)
35 mp_srcptr op1_ptr, op2_ptr;
36 mp_size_t op1_size, op2_size;
43 op1_size = op1->_mp_size;
44 op2_size = op2->_mp_size;
54 if (op1_size >= op2_size)
56 if (res->_mp_alloc < op1_size)
58 _mpz_realloc (res, op1_size);
64 if (res_ptr != op1_ptr)
65 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
67 for (i = op2_size - 1; i >= 0; i--)
68 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
73 if (res->_mp_alloc < op2_size)
75 _mpz_realloc (res, op2_size);
81 if (res_ptr != op2_ptr)
82 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
84 for (i = op1_size - 1; i >= 0; i--)
85 res_ptr[i] = op1_ptr[i] | op2_ptr[i];
89 res->_mp_size = res_size;
92 else /* op2_size < 0 */
94 /* Fall through to the code at the end of the function. */
104 /* Both operands are negative, so will be the result.
105 -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
106 = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
107 = ((OP1 - 1) & (OP2 - 1)) + 1 */
109 op1_size = -op1_size;
110 op2_size = -op2_size;
112 res_size = MIN (op1_size, op2_size);
114 /* Possible optimization: Decrease mpn_sub precision,
115 as we won't use the entire res of both. */
116 opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
117 mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
120 opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
121 mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
124 if (res->_mp_alloc < res_size)
126 _mpz_realloc (res, res_size);
127 res_ptr = res->_mp_d;
128 /* Don't re-read OP1_PTR and OP2_PTR. They point to
129 temporary space--never to the space RES->_mp_D used
130 to point to before reallocation. */
133 /* First loop finds the size of the result. */
134 for (i = res_size - 1; i >= 0; i--)
135 if ((op1_ptr[i] & op2_ptr[i]) != 0)
141 /* Second loop computes the real result. */
142 for (i = res_size - 1; i >= 0; i--)
143 res_ptr[i] = op1_ptr[i] & op2_ptr[i];
145 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
148 res_ptr[res_size] = cy;
158 res->_mp_size = -res_size;
164 /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
165 through to the code that handles OP1 | -OP2. */
166 {mpz_srcptr t = op1; op1 = op2; op2 = t;}
167 {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
168 {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;}
178 /* Operand 2 negative, so will be the result.
179 -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
180 = ~(OP1 | ~(OP2 - 1)) + 1 =
181 = (~OP1 & (OP2 - 1)) + 1 */
183 op2_size = -op2_size;
185 res_alloc = op2_size;
187 opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
188 mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
191 if (res->_mp_alloc < res_alloc)
193 _mpz_realloc (res, res_alloc);
194 op1_ptr = op1->_mp_d;
195 res_ptr = res->_mp_d;
196 /* Don't re-read OP2_PTR. It points to temporary space--never
197 to the space RES->_mp_D used to point to before reallocation. */
200 if (op1_size >= op2_size)
202 /* We can just ignore the part of OP1 that stretches above OP2,
203 because the result limbs are zero there. */
205 /* First loop finds the size of the result. */
206 for (i = op2_size - 1; i >= 0; i--)
207 if ((~op1_ptr[i] & op2_ptr[i]) != 0)
216 /* Copy the part of OP2 that stretches above OP1, to RES. */
217 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
223 /* Second loop computes the real result. */
224 for (i = count - 1; i >= 0; i--)
225 res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
227 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
230 res_ptr[res_size] = cy;
240 res->_mp_size = -res_size;