1
/* mpz_ior -- Logical inclusive or.
3
Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001 Free Software Foundation,
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 2.1 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; see the file COPYING.LIB. If not, write to
20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21
MA 02111-1307, USA. */
27
mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
29
mp_srcptr op1_ptr, op2_ptr;
30
mp_size_t op1_size, op2_size;
37
op1_size = op1->_mp_size;
38
op2_size = op2->_mp_size;
48
if (op1_size >= op2_size)
50
if (res->_mp_alloc < op1_size)
52
_mpz_realloc (res, op1_size);
58
if (res_ptr != op1_ptr)
59
MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
61
for (i = op2_size - 1; i >= 0; i--)
62
res_ptr[i] = op1_ptr[i] | op2_ptr[i];
67
if (res->_mp_alloc < op2_size)
69
_mpz_realloc (res, op2_size);
75
if (res_ptr != op2_ptr)
76
MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
78
for (i = op1_size - 1; i >= 0; i--)
79
res_ptr[i] = op1_ptr[i] | op2_ptr[i];
83
res->_mp_size = res_size;
86
else /* op2_size < 0 */
88
/* Fall through to the code at the end of the function. */
98
/* Both operands are negative, so will be the result.
99
-((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
100
= ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
101
= ((OP1 - 1) & (OP2 - 1)) + 1 */
103
op1_size = -op1_size;
104
op2_size = -op2_size;
106
res_size = MIN (op1_size, op2_size);
108
/* Possible optimization: Decrease mpn_sub precision,
109
as we won't use the entire res of both. */
110
opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
111
mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
114
opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
115
mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
118
if (res->_mp_alloc < res_size)
120
_mpz_realloc (res, res_size);
121
res_ptr = res->_mp_d;
122
/* Don't re-read OP1_PTR and OP2_PTR. They point to
123
temporary space--never to the space RES->_mp_d used
124
to point to before reallocation. */
127
/* First loop finds the size of the result. */
128
for (i = res_size - 1; i >= 0; i--)
129
if ((op1_ptr[i] & op2_ptr[i]) != 0)
135
/* Second loop computes the real result. */
136
for (i = res_size - 1; i >= 0; i--)
137
res_ptr[i] = op1_ptr[i] & op2_ptr[i];
139
cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
142
res_ptr[res_size] = cy;
152
res->_mp_size = -res_size;
158
/* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
159
through to the code that handles OP1 | -OP2. */
160
MPZ_SRCPTR_SWAP (op1, op2);
161
MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size);
171
/* Operand 2 negative, so will be the result.
172
-(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
173
= ~(OP1 | ~(OP2 - 1)) + 1 =
174
= (~OP1 & (OP2 - 1)) + 1 */
176
op2_size = -op2_size;
178
res_alloc = op2_size;
180
opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
181
mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
183
op2_size -= op2_ptr[op2_size - 1] == 0;
185
if (res->_mp_alloc < res_alloc)
187
_mpz_realloc (res, res_alloc);
188
op1_ptr = op1->_mp_d;
189
res_ptr = res->_mp_d;
190
/* Don't re-read OP2_PTR. It points to temporary space--never
191
to the space RES->_mp_d used to point to before reallocation. */
194
if (op1_size >= op2_size)
196
/* We can just ignore the part of OP1 that stretches above OP2,
197
because the result limbs are zero there. */
199
/* First loop finds the size of the result. */
200
for (i = op2_size - 1; i >= 0; i--)
201
if ((~op1_ptr[i] & op2_ptr[i]) != 0)
210
/* Copy the part of OP2 that stretches above OP1, to RES. */
211
MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
217
/* Second loop computes the real result. */
218
for (i = count - 1; i >= 0; i--)
219
res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
221
cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
224
res_ptr[res_size] = cy;
234
res->_mp_size = -res_size;