1 /* mpz_xor -- Logical xor.
3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012 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 either:
11 * the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
17 * the GNU General Public License as published by the Free Software
18 Foundation; either version 2 of the License, or (at your option) any
21 or both in parallel, as here.
23 The GNU MP Library is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 You should have received copies of the GNU General Public License and the
29 GNU Lesser General Public License along with the GNU MP Library. If not,
30 see https://www.gnu.org/licenses/. */
36 mpz_xor (mpz_ptr res
, mpz_srcptr op1
, mpz_srcptr op2
)
38 mp_srcptr op1_ptr
, op2_ptr
;
39 mp_size_t op1_size
, op2_size
;
41 mp_size_t res_size
, res_alloc
;
56 if (op1_size
>= op2_size
)
58 if (ALLOC(res
) < op1_size
)
60 _mpz_realloc (res
, op1_size
);
61 /* No overlapping possible: op1_ptr = PTR(op1); */
66 if (res_ptr
!= op1_ptr
)
67 MPN_COPY (res_ptr
+ op2_size
, op1_ptr
+ op2_size
,
69 if (LIKELY (op2_size
!= 0))
70 mpn_xor_n (res_ptr
, op1_ptr
, op2_ptr
, op2_size
);
75 if (ALLOC(res
) < op2_size
)
77 _mpz_realloc (res
, op2_size
);
79 /* No overlapping possible: op2_ptr = PTR(op2); */
83 if (res_ptr
!= op2_ptr
)
84 MPN_COPY (res_ptr
+ op1_size
, op2_ptr
+ op1_size
,
86 if (LIKELY (op1_size
!= 0))
87 mpn_xor_n (res_ptr
, op1_ptr
, op2_ptr
, op1_size
);
91 MPN_NORMALIZE (res_ptr
, res_size
);
95 else /* op2_size < 0 */
97 /* 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 TMP_ALLOC_LIMBS_2 (opx
, op1_size
, opy
, op2_size
);
117 mpn_sub_1 (opx
, op1_ptr
, op1_size
, (mp_limb_t
) 1);
120 mpn_sub_1 (opy
, op2_ptr
, op2_size
, (mp_limb_t
) 1);
123 if (op1_size
> op2_size
)
124 MPN_SRCPTR_SWAP (op1_ptr
,op1_size
, op2_ptr
,op2_size
);
126 res_alloc
= op2_size
;
127 res_ptr
= MPZ_REALLOC (res
, res_alloc
);
129 MPN_COPY (res_ptr
+ op1_size
, op2_ptr
+ op1_size
,
130 op2_size
- op1_size
);
131 mpn_xor_n (res_ptr
, op1_ptr
, op2_ptr
, op1_size
);
134 MPN_NORMALIZE (res_ptr
, res_size
);
141 /* We should compute -OP1 ^ OP2. Swap OP1 and OP2 and fall
142 through to the code that handles OP1 ^ -OP2. */
143 MPZ_SRCPTR_SWAP (op1
, op2
);
144 MPN_SRCPTR_SWAP (op1_ptr
,op1_size
, op2_ptr
,op2_size
);
152 /* Operand 2 negative, so will be the result.
153 -(OP1 ^ (-OP2)) = -(OP1 ^ ~(OP2 - 1)) =
154 = ~(OP1 ^ ~(OP2 - 1)) + 1 =
155 = (OP1 ^ (OP2 - 1)) + 1 */
157 op2_size
= -op2_size
;
159 opx
= TMP_ALLOC_LIMBS (op2_size
);
160 mpn_sub_1 (opx
, op2_ptr
, op2_size
, (mp_limb_t
) 1);
163 res_alloc
= MAX (op1_size
, op2_size
) + 1;
164 if (ALLOC(res
) < res_alloc
)
166 _mpz_realloc (res
, res_alloc
);
168 /* op2_ptr points to temporary space. */
172 if (op1_size
> op2_size
)
174 MPN_COPY (res_ptr
+ op2_size
, op1_ptr
+ op2_size
, op1_size
- op2_size
);
175 mpn_xor_n (res_ptr
, op1_ptr
, op2_ptr
, op2_size
);
180 MPN_COPY (res_ptr
+ op1_size
, op2_ptr
+ op1_size
, op2_size
- op1_size
);
181 if (LIKELY (op1_size
!= 0))
182 mpn_xor_n (res_ptr
, op1_ptr
, op2_ptr
, op1_size
);
186 cy
= mpn_add_1 (res_ptr
, res_ptr
, res_size
, (mp_limb_t
) 1);
187 res_ptr
[res_size
] = cy
;
188 res_size
+= (cy
!= 0);
190 MPN_NORMALIZE (res_ptr
, res_size
);
191 SIZ(res
) = -res_size
;