1 /* mpz_xor -- Logical xor.
3 Copyright (C) 1991, 1993, 1994, 1996, 1997, 2000 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. */
28 mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
30 mpz_xor (res, op1, op2)
36 mp_srcptr op1_ptr, op2_ptr;
37 mp_size_t op1_size, op2_size;
39 mp_size_t res_size, res_alloc;
44 op1_size = op1->_mp_size;
45 op2_size = op2->_mp_size;
55 if (op1_size >= op2_size)
57 if (res->_mp_alloc < op1_size)
59 _mpz_realloc (res, op1_size);
65 if (res_ptr != op1_ptr)
66 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
68 for (i = op2_size - 1; i >= 0; i--)
69 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
74 if (res->_mp_alloc < op2_size)
76 _mpz_realloc (res, op2_size);
82 if (res_ptr != op2_ptr)
83 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
85 for (i = op1_size - 1; i >= 0; i--)
86 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
90 MPN_NORMALIZE (res_ptr, res_size);
91 res->_mp_size = res_size;
94 else /* op2_size < 0 */
96 /* Fall through to the code at the end of the function. */
106 /* Both operands are negative, the result will be positive.
108 = ~(OP1 - 1) ^ ~(OP2 - 1) =
109 = (OP1 - 1) ^ (OP2 - 1) */
111 op1_size = -op1_size;
112 op2_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 (op1_size * BYTES_PER_MP_LIMB);
117 mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1);
120 opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
121 mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
124 res_alloc = MAX (op1_size, op2_size);
125 if (res->_mp_alloc < res_alloc)
127 _mpz_realloc (res, res_alloc);
128 res_ptr = res->_mp_d;
129 /* Don't re-read OP1_PTR and OP2_PTR. They point to
130 temporary space--never to the space RES->_mp_d used
131 to point to before reallocation. */
134 if (op1_size > op2_size)
136 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
137 op1_size - op2_size);
138 for (i = op2_size - 1; i >= 0; i--)
139 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
144 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
145 op2_size - op1_size);
146 for (i = op1_size - 1; i >= 0; i--)
147 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
151 MPN_NORMALIZE (res_ptr, res_size);
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);
170 /* Operand 2 negative, so will be the result.
171 -(OP1 ^ (-OP2)) = -(OP1 ^ ~(OP2 - 1)) =
172 = ~(OP1 ^ ~(OP2 - 1)) + 1 =
173 = (OP1 ^ (OP2 - 1)) + 1 */
175 op2_size = -op2_size;
177 opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
178 mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
181 res_alloc = MAX (op1_size, op2_size) + 1;
182 if (res->_mp_alloc < res_alloc)
184 _mpz_realloc (res, res_alloc);
185 op1_ptr = op1->_mp_d;
186 res_ptr = res->_mp_d;
187 /* Don't re-read OP2_PTR. It points to temporary space--never
188 to the space RES->_mp_d used to point to before reallocation. */
191 if (op1_size > op2_size)
193 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size);
194 for (i = op2_size - 1; i >= 0; i--)
195 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
200 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
201 for (i = op1_size - 1; i >= 0; i--)
202 res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
206 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
209 res_ptr[res_size] = cy;
213 MPN_NORMALIZE (res_ptr, res_size);
214 res->_mp_size = -res_size;