1 /* mpz_ior -- Logical inclusive or.
3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005 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 the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 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. If not, see http://www.gnu.org/licenses/. */
25 mpz_ior (mpz_ptr res
, mpz_srcptr op1
, mpz_srcptr op2
)
27 mp_srcptr op1_ptr
, op2_ptr
;
28 mp_size_t op1_size
, op2_size
;
46 if (op1_size
>= op2_size
)
48 if (ALLOC(res
) < op1_size
)
50 _mpz_realloc (res
, op1_size
);
51 /* No overlapping possible: op1_ptr = PTR(op1); */
56 if (res_ptr
!= op1_ptr
)
57 MPN_COPY (res_ptr
+ op2_size
, op1_ptr
+ op2_size
,
59 for (i
= op2_size
- 1; i
>= 0; i
--)
60 res_ptr
[i
] = op1_ptr
[i
] | op2_ptr
[i
];
65 if (ALLOC(res
) < op2_size
)
67 _mpz_realloc (res
, op2_size
);
69 /* No overlapping possible: op2_ptr = PTR(op2); */
73 if (res_ptr
!= op2_ptr
)
74 MPN_COPY (res_ptr
+ op1_size
, op2_ptr
+ op1_size
,
76 for (i
= op1_size
- 1; i
>= 0; i
--)
77 res_ptr
[i
] = op1_ptr
[i
] | op2_ptr
[i
];
84 else /* op2_size < 0 */
86 /* Fall through to the code at the end of the function. */
96 /* Both operands are negative, so will be the result.
97 -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
98 = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
99 = ((OP1 - 1) & (OP2 - 1)) + 1 */
101 op1_size
= -op1_size
;
102 op2_size
= -op2_size
;
104 res_size
= MIN (op1_size
, op2_size
);
106 /* Possible optimization: Decrease mpn_sub precision,
107 as we won't use the entire res of both. */
108 opx
= TMP_ALLOC_LIMBS (res_size
);
109 mpn_sub_1 (opx
, op1_ptr
, res_size
, (mp_limb_t
) 1);
112 opx
= TMP_ALLOC_LIMBS (res_size
);
113 mpn_sub_1 (opx
, op2_ptr
, res_size
, (mp_limb_t
) 1);
116 if (ALLOC(res
) < res_size
)
118 _mpz_realloc (res
, res_size
);
119 /* op1_ptr and op2_ptr point to temporary space. */
123 /* First loop finds the size of the result. */
124 for (i
= res_size
- 1; i
>= 0; i
--)
125 if ((op1_ptr
[i
] & op2_ptr
[i
]) != 0)
131 /* Second loop computes the real result. */
132 for (i
= res_size
- 1; i
>= 0; i
--)
133 res_ptr
[i
] = op1_ptr
[i
] & op2_ptr
[i
];
135 cy
= mpn_add_1 (res_ptr
, res_ptr
, res_size
, (mp_limb_t
) 1);
138 res_ptr
[res_size
] = cy
;
148 SIZ(res
) = -res_size
;
154 /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
155 through to the code that handles OP1 | -OP2. */
156 MPZ_SRCPTR_SWAP (op1
, op2
);
157 MPN_SRCPTR_SWAP (op1_ptr
,op1_size
, op2_ptr
,op2_size
);
167 /* Operand 2 negative, so will be the result.
168 -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
169 = ~(OP1 | ~(OP2 - 1)) + 1 =
170 = (~OP1 & (OP2 - 1)) + 1 */
172 op2_size
= -op2_size
;
174 res_alloc
= op2_size
;
176 opx
= TMP_ALLOC_LIMBS (op2_size
);
177 mpn_sub_1 (opx
, op2_ptr
, op2_size
, (mp_limb_t
) 1);
179 op2_size
-= op2_ptr
[op2_size
- 1] == 0;
181 if (ALLOC(res
) < res_alloc
)
183 _mpz_realloc (res
, res_alloc
);
185 /* op2_ptr points to temporary space. */
189 if (op1_size
>= op2_size
)
191 /* We can just ignore the part of OP1 that stretches above OP2,
192 because the result limbs are zero there. */
194 /* First loop finds the size of the result. */
195 for (i
= op2_size
- 1; i
>= 0; i
--)
196 if ((~op1_ptr
[i
] & op2_ptr
[i
]) != 0)
205 /* Copy the part of OP2 that stretches above OP1, to RES. */
206 MPN_COPY (res_ptr
+ op1_size
, op2_ptr
+ op1_size
, op2_size
- op1_size
);
212 /* Second loop computes the real result. */
213 for (i
= count
- 1; i
>= 0; i
--)
214 res_ptr
[i
] = ~op1_ptr
[i
] & op2_ptr
[i
];
216 cy
= mpn_add_1 (res_ptr
, res_ptr
, res_size
, (mp_limb_t
) 1);
219 res_ptr
[res_size
] = cy
;
229 SIZ(res
) = -res_size
;