Annotation of OpenXM/src/kan96xx/gmp-2.0.2-ssh-2/mpz/ior.c, Revision 1.1.1.1
1.1 takayama 1: /* mpz_ior -- Logical inclusive or.
2:
3: Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
4:
5: This file is part of the GNU MP Library.
6:
7: The GNU MP Library is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Library General Public License as published by
9: the Free Software Foundation; either version 2 of the License, or (at your
10: option) any later version.
11:
12: The GNU MP Library is distributed in the hope that it will be useful, but
13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15: License for more details.
16:
17: You should have received a copy of the GNU Library General Public License
18: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20: MA 02111-1307, USA. */
21:
22: #include "gmp.h"
23: #include "gmp-impl.h"
24:
25: void
26: #if __STDC__
27: mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
28: #else
29: mpz_ior (res, op1, op2)
30: mpz_ptr res;
31: mpz_srcptr op1;
32: mpz_srcptr op2;
33: #endif
34: {
35: mp_srcptr op1_ptr, op2_ptr;
36: mp_size_t op1_size, op2_size;
37: mp_ptr res_ptr;
38: mp_size_t res_size;
39: mp_size_t i;
40: TMP_DECL (marker);
41:
42: TMP_MARK (marker);
43: op1_size = op1->_mp_size;
44: op2_size = op2->_mp_size;
45:
46: op1_ptr = op1->_mp_d;
47: op2_ptr = op2->_mp_d;
48: res_ptr = res->_mp_d;
49:
50: if (op1_size >= 0)
51: {
52: if (op2_size >= 0)
53: {
54: if (op1_size >= op2_size)
55: {
56: if (res->_mp_alloc < op1_size)
57: {
58: _mpz_realloc (res, op1_size);
59: op1_ptr = op1->_mp_d;
60: op2_ptr = op2->_mp_d;
61: res_ptr = res->_mp_d;
62: }
63:
64: if (res_ptr != op1_ptr)
65: MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
66: op1_size - op2_size);
67: for (i = op2_size - 1; i >= 0; i--)
68: res_ptr[i] = op1_ptr[i] | op2_ptr[i];
69: res_size = op1_size;
70: }
71: else
72: {
73: if (res->_mp_alloc < op2_size)
74: {
75: _mpz_realloc (res, op2_size);
76: op1_ptr = op1->_mp_d;
77: op2_ptr = op2->_mp_d;
78: res_ptr = res->_mp_d;
79: }
80:
81: if (res_ptr != op2_ptr)
82: MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
83: op2_size - op1_size);
84: for (i = op1_size - 1; i >= 0; i--)
85: res_ptr[i] = op1_ptr[i] | op2_ptr[i];
86: res_size = op2_size;
87: }
88:
89: res->_mp_size = res_size;
90: return;
91: }
92: else /* op2_size < 0 */
93: {
94: /* Fall through to the code at the end of the function. */
95: }
96: }
97: else
98: {
99: if (op2_size < 0)
100: {
101: mp_ptr opx;
102: mp_limb_t cy;
103:
104: /* Both operands are negative, so will be the result.
105: -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
106: = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
107: = ((OP1 - 1) & (OP2 - 1)) + 1 */
108:
109: op1_size = -op1_size;
110: op2_size = -op2_size;
111:
112: res_size = MIN (op1_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 (res_size * BYTES_PER_MP_LIMB);
117: mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
118: op1_ptr = opx;
119:
120: opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
121: mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
122: op2_ptr = opx;
123:
124: if (res->_mp_alloc < res_size)
125: {
126: _mpz_realloc (res, res_size);
127: res_ptr = res->_mp_d;
128: /* Don't re-read OP1_PTR and OP2_PTR. They point to
129: temporary space--never to the space RES->_mp_D used
130: to point to before reallocation. */
131: }
132:
133: /* First loop finds the size of the result. */
134: for (i = res_size - 1; i >= 0; i--)
135: if ((op1_ptr[i] & op2_ptr[i]) != 0)
136: break;
137: res_size = i + 1;
138:
139: if (res_size != 0)
140: {
141: /* Second loop computes the real result. */
142: for (i = res_size - 1; i >= 0; i--)
143: res_ptr[i] = op1_ptr[i] & op2_ptr[i];
144:
145: cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
146: if (cy)
147: {
148: res_ptr[res_size] = cy;
149: res_size++;
150: }
151: }
152: else
153: {
154: res_ptr[0] = 1;
155: res_size = 1;
156: }
157:
158: res->_mp_size = -res_size;
159: TMP_FREE (marker);
160: return;
161: }
162: else
163: {
164: /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
165: through to the code that handles OP1 | -OP2. */
166: {mpz_srcptr t = op1; op1 = op2; op2 = t;}
167: {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
168: {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;}
169: }
170: }
171:
172: {
173: mp_ptr opx;
174: mp_limb_t cy;
175: mp_size_t res_alloc;
176: mp_size_t count;
177:
178: /* Operand 2 negative, so will be the result.
179: -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
180: = ~(OP1 | ~(OP2 - 1)) + 1 =
181: = (~OP1 & (OP2 - 1)) + 1 */
182:
183: op2_size = -op2_size;
184:
185: res_alloc = op2_size;
186:
187: opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
188: mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
189: op2_ptr = opx;
190:
191: if (res->_mp_alloc < res_alloc)
192: {
193: _mpz_realloc (res, res_alloc);
194: op1_ptr = op1->_mp_d;
195: res_ptr = res->_mp_d;
196: /* Don't re-read OP2_PTR. It points to temporary space--never
197: to the space RES->_mp_D used to point to before reallocation. */
198: }
199:
200: if (op1_size >= op2_size)
201: {
202: /* We can just ignore the part of OP1 that stretches above OP2,
203: because the result limbs are zero there. */
204:
205: /* First loop finds the size of the result. */
206: for (i = op2_size - 1; i >= 0; i--)
207: if ((~op1_ptr[i] & op2_ptr[i]) != 0)
208: break;
209: res_size = i + 1;
210: count = res_size;
211: }
212: else
213: {
214: res_size = op2_size;
215:
216: /* Copy the part of OP2 that stretches above OP1, to RES. */
217: MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
218: count = op1_size;
219: }
220:
221: if (res_size != 0)
222: {
223: /* Second loop computes the real result. */
224: for (i = count - 1; i >= 0; i--)
225: res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
226:
227: cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
228: if (cy)
229: {
230: res_ptr[res_size] = cy;
231: res_size++;
232: }
233: }
234: else
235: {
236: res_ptr[0] = 1;
237: res_size = 1;
238: }
239:
240: res->_mp_size = -res_size;
241: }
242: TMP_FREE (marker);
243: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>