diff options
Diffstat (limited to 'gmp/mpz/xor.c')
-rw-r--r-- | gmp/mpz/xor.c | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/gmp/mpz/xor.c b/gmp/mpz/xor.c index cd701000d5..18edd8129e 100644 --- a/gmp/mpz/xor.c +++ b/gmp/mpz/xor.c @@ -1,33 +1,22 @@ /* mpz_xor -- Logical xor. -Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012 Free Software +Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #include "gmp.h" #include "gmp-impl.h" @@ -39,6 +28,7 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) mp_size_t op1_size, op2_size; mp_ptr res_ptr; mp_size_t res_size, res_alloc; + mp_size_t i; TMP_DECL; TMP_MARK; @@ -66,8 +56,8 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) if (res_ptr != op1_ptr) MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size); - if (LIKELY (op2_size != 0)) - mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; res_size = op1_size; } else @@ -83,8 +73,8 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) if (res_ptr != op2_ptr) MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size); - if (LIKELY (op1_size != 0)) - mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); + for (i = op1_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; res_size = op2_size; } @@ -101,7 +91,7 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) { if (op2_size < 0) { - mp_ptr opx, opy; + mp_ptr opx; /* Both operands are negative, the result will be positive. (-OP1) ^ (-OP2) = @@ -113,23 +103,38 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) /* Possible optimization: Decrease mpn_sub precision, as we won't use the entire res of both. */ - TMP_ALLOC_LIMBS_2 (opx, op1_size, opy, op2_size); + opx = TMP_ALLOC_LIMBS (op1_size); mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1); op1_ptr = opx; - mpn_sub_1 (opy, op2_ptr, op2_size, (mp_limb_t) 1); - op2_ptr = opy; + opx = TMP_ALLOC_LIMBS (op2_size); + mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1); + op2_ptr = opx; - if (op1_size > op2_size) - MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size); - - res_alloc = op2_size; - res_ptr = MPZ_REALLOC (res, res_alloc); + res_alloc = MAX (op1_size, op2_size); + if (ALLOC(res) < res_alloc) + { + _mpz_realloc (res, res_alloc); + res_ptr = PTR(res); + /* op1_ptr and op2_ptr point to temporary space. */ + } - MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, - op2_size - op1_size); - mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); - res_size = op2_size; + if (op1_size > op2_size) + { + MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, + op1_size - op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; + res_size = op1_size; + } + else + { + MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, + op2_size - op1_size); + for (i = op1_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; + res_size = op2_size; + } MPN_NORMALIZE (res_ptr, res_size); SIZ(res) = res_size; @@ -140,8 +145,8 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) { /* We should compute -OP1 ^ OP2. Swap OP1 and OP2 and fall through to the code that handles OP1 ^ -OP2. */ - MPZ_SRCPTR_SWAP (op1, op2); - MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size); + MPZ_SRCPTR_SWAP (op1, op2); + MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size); } } @@ -172,20 +177,24 @@ mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) if (op1_size > op2_size) { MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size); - mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; res_size = op1_size; } else { MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size); - if (LIKELY (op1_size != 0)) - mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); + for (i = op1_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] ^ op2_ptr[i]; res_size = op2_size; } cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1); - res_ptr[res_size] = cy; - res_size += (cy != 0); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } MPN_NORMALIZE (res_ptr, res_size); SIZ(res) = -res_size; |