Annotation of OpenXM_contrib/gmp/mpz/xor.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpz_xor -- Logical xor.
2:
3: Copyright (C) 1991, 1993, 1994, 1996, 1997, 2000 Free Software Foundation,
4: Inc.
5:
6: This file is part of the GNU MP Library.
7:
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.
12:
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.
17:
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. */
22:
23: #include "gmp.h"
24: #include "gmp-impl.h"
25:
26: void
27: #if __STDC__
28: mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
29: #else
30: mpz_xor (res, op1, op2)
31: mpz_ptr res;
32: mpz_srcptr op1;
33: mpz_srcptr op2;
34: #endif
35: {
36: mp_srcptr op1_ptr, op2_ptr;
37: mp_size_t op1_size, op2_size;
38: mp_ptr res_ptr;
39: mp_size_t res_size, res_alloc;
40: mp_size_t i;
41: TMP_DECL (marker);
42:
43: TMP_MARK (marker);
44: op1_size = op1->_mp_size;
45: op2_size = op2->_mp_size;
46:
47: op1_ptr = op1->_mp_d;
48: op2_ptr = op2->_mp_d;
49: res_ptr = res->_mp_d;
50:
51: if (op1_size >= 0)
52: {
53: if (op2_size >= 0)
54: {
55: if (op1_size >= op2_size)
56: {
57: if (res->_mp_alloc < op1_size)
58: {
59: _mpz_realloc (res, op1_size);
60: op1_ptr = op1->_mp_d;
61: op2_ptr = op2->_mp_d;
62: res_ptr = res->_mp_d;
63: }
64:
65: if (res_ptr != op1_ptr)
66: MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
67: op1_size - op2_size);
68: for (i = op2_size - 1; i >= 0; i--)
69: res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
70: res_size = op1_size;
71: }
72: else
73: {
74: if (res->_mp_alloc < op2_size)
75: {
76: _mpz_realloc (res, op2_size);
77: op1_ptr = op1->_mp_d;
78: op2_ptr = op2->_mp_d;
79: res_ptr = res->_mp_d;
80: }
81:
82: if (res_ptr != op2_ptr)
83: MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
84: op2_size - op1_size);
85: for (i = op1_size - 1; i >= 0; i--)
86: res_ptr[i] = op1_ptr[i] ^ op2_ptr[i];
87: res_size = op2_size;
88: }
89:
90: MPN_NORMALIZE (res_ptr, res_size);
91: res->_mp_size = res_size;
92: return;
93: }
94: else /* op2_size < 0 */
95: {
96: /* Fall through to the code at the end of the function. */
97: }
98: }
99: else
100: {
101: if (op2_size < 0)
102: {
103: mp_ptr opx;
104: mp_limb_t cy;
105:
106: /* Both operands are negative, the result will be positive.
107: (-OP1) ^ (-OP2) =
108: = ~(OP1 - 1) ^ ~(OP2 - 1) =
109: = (OP1 - 1) ^ (OP2 - 1) */
110:
111: op1_size = -op1_size;
112: op2_size = -op2_size;
113:
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);
118: op1_ptr = opx;
119:
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);
122: op2_ptr = opx;
123:
124: res_alloc = MAX (op1_size, op2_size);
125: if (res->_mp_alloc < res_alloc)
126: {
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. */
132: }
133:
134: if (op1_size > op2_size)
135: {
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];
140: res_size = op1_size;
141: }
142: else
143: {
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];
148: res_size = op2_size;
149: }
150:
151: MPN_NORMALIZE (res_ptr, res_size);
152: res->_mp_size = res_size;
153: TMP_FREE (marker);
154: return;
155: }
156: else
157: {
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);
162: }
163: }
164:
165: {
166: mp_ptr opx;
167: mp_limb_t cy;
168: mp_size_t count;
169:
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 */
174:
175: op2_size = -op2_size;
176:
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);
179: op2_ptr = opx;
180:
181: res_alloc = MAX (op1_size, op2_size) + 1;
182: if (res->_mp_alloc < res_alloc)
183: {
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. */
189: }
190:
191: if (op1_size > op2_size)
192: {
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];
196: res_size = op1_size;
197: }
198: else
199: {
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];
203: res_size = op2_size;
204: }
205:
206: cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
207: if (cy)
208: {
209: res_ptr[res_size] = cy;
210: res_size++;
211: }
212:
213: MPN_NORMALIZE (res_ptr, res_size);
214: res->_mp_size = -res_size;
215: TMP_FREE (marker);
216: }
217: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>