Annotation of OpenXM_contrib/gmp/mpz/ior.c, Revision 1.1.1.3
1.1 maekawa 1: /* mpz_ior -- Logical inclusive or.
2:
1.1.1.3 ! ohara 3: Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001 Free Software Foundation,
1.1.1.2 maekawa 4: Inc.
1.1 maekawa 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
1.1.1.2 maekawa 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
1.1 maekawa 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
1.1.1.2 maekawa 15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1.1 maekawa 16: License for more details.
17:
1.1.1.2 maekawa 18: You should have received a copy of the GNU Lesser General Public License
1.1 maekawa 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: mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
28: {
29: mp_srcptr op1_ptr, op2_ptr;
30: mp_size_t op1_size, op2_size;
31: mp_ptr res_ptr;
32: mp_size_t res_size;
33: mp_size_t i;
34: TMP_DECL (marker);
35:
36: TMP_MARK (marker);
37: op1_size = op1->_mp_size;
38: op2_size = op2->_mp_size;
39:
40: op1_ptr = op1->_mp_d;
41: op2_ptr = op2->_mp_d;
42: res_ptr = res->_mp_d;
43:
44: if (op1_size >= 0)
45: {
46: if (op2_size >= 0)
47: {
48: if (op1_size >= op2_size)
49: {
50: if (res->_mp_alloc < op1_size)
51: {
52: _mpz_realloc (res, op1_size);
53: op1_ptr = op1->_mp_d;
54: op2_ptr = op2->_mp_d;
55: res_ptr = res->_mp_d;
56: }
57:
58: if (res_ptr != op1_ptr)
59: MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
60: op1_size - op2_size);
61: for (i = op2_size - 1; i >= 0; i--)
62: res_ptr[i] = op1_ptr[i] | op2_ptr[i];
63: res_size = op1_size;
64: }
65: else
66: {
67: if (res->_mp_alloc < op2_size)
68: {
69: _mpz_realloc (res, op2_size);
70: op1_ptr = op1->_mp_d;
71: op2_ptr = op2->_mp_d;
72: res_ptr = res->_mp_d;
73: }
74:
75: if (res_ptr != op2_ptr)
76: MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
77: op2_size - op1_size);
78: for (i = op1_size - 1; i >= 0; i--)
79: res_ptr[i] = op1_ptr[i] | op2_ptr[i];
80: res_size = op2_size;
81: }
82:
83: res->_mp_size = res_size;
84: return;
85: }
86: else /* op2_size < 0 */
87: {
88: /* Fall through to the code at the end of the function. */
89: }
90: }
91: else
92: {
93: if (op2_size < 0)
94: {
95: mp_ptr opx;
96: mp_limb_t cy;
97:
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 */
102:
103: op1_size = -op1_size;
104: op2_size = -op2_size;
105:
106: res_size = MIN (op1_size, op2_size);
107:
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);
112: op1_ptr = opx;
113:
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);
116: op2_ptr = opx;
117:
118: if (res->_mp_alloc < res_size)
119: {
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
1.1.1.2 maekawa 123: temporary space--never to the space RES->_mp_d used
1.1 maekawa 124: to point to before reallocation. */
125: }
126:
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)
130: break;
131: res_size = i + 1;
132:
133: if (res_size != 0)
134: {
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];
138:
139: cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
140: if (cy)
141: {
142: res_ptr[res_size] = cy;
143: res_size++;
144: }
145: }
146: else
147: {
148: res_ptr[0] = 1;
149: res_size = 1;
150: }
151:
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. */
1.1.1.2 maekawa 160: MPZ_SRCPTR_SWAP (op1, op2);
161: MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size);
1.1 maekawa 162: }
163: }
164:
165: {
166: mp_ptr opx;
167: mp_limb_t cy;
168: mp_size_t res_alloc;
169: mp_size_t count;
170:
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 */
175:
176: op2_size = -op2_size;
177:
178: res_alloc = op2_size;
179:
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);
182: op2_ptr = opx;
1.1.1.2 maekawa 183: op2_size -= op2_ptr[op2_size - 1] == 0;
1.1 maekawa 184:
185: if (res->_mp_alloc < res_alloc)
186: {
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
1.1.1.2 maekawa 191: to the space RES->_mp_d used to point to before reallocation. */
1.1 maekawa 192: }
193:
194: if (op1_size >= op2_size)
195: {
196: /* We can just ignore the part of OP1 that stretches above OP2,
197: because the result limbs are zero there. */
198:
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)
202: break;
203: res_size = i + 1;
204: count = res_size;
205: }
206: else
207: {
208: res_size = op2_size;
209:
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);
212: count = op1_size;
213: }
214:
215: if (res_size != 0)
216: {
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];
220:
221: cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
222: if (cy)
223: {
224: res_ptr[res_size] = cy;
225: res_size++;
226: }
227: }
228: else
229: {
230: res_ptr[0] = 1;
231: res_size = 1;
232: }
233:
234: res->_mp_size = -res_size;
235: }
236: TMP_FREE (marker);
237: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>