github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/xor.c (about) 1 /* mpz_xor -- Logical xor. 2 3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012 Free Software 4 Foundation, 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 either: 10 11 * the GNU Lesser General Public License as published by the Free 12 Software Foundation; either version 3 of the License, or (at your 13 option) any later version. 14 15 or 16 17 * the GNU General Public License as published by the Free Software 18 Foundation; either version 2 of the License, or (at your option) any 19 later version. 20 21 or both in parallel, as here. 22 23 The GNU MP Library is distributed in the hope that it will be useful, but 24 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 25 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26 for more details. 27 28 You should have received copies of the GNU General Public License and the 29 GNU Lesser General Public License along with the GNU MP Library. If not, 30 see https://www.gnu.org/licenses/. */ 31 32 #include "gmp.h" 33 #include "gmp-impl.h" 34 35 void 36 mpz_xor (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) 37 { 38 mp_srcptr op1_ptr, op2_ptr; 39 mp_size_t op1_size, op2_size; 40 mp_ptr res_ptr; 41 mp_size_t res_size, res_alloc; 42 TMP_DECL; 43 44 TMP_MARK; 45 op1_size = SIZ(op1); 46 op2_size = SIZ(op2); 47 48 op1_ptr = PTR(op1); 49 op2_ptr = PTR(op2); 50 res_ptr = PTR(res); 51 52 if (op1_size >= 0) 53 { 54 if (op2_size >= 0) 55 { 56 if (op1_size >= op2_size) 57 { 58 if (ALLOC(res) < op1_size) 59 { 60 _mpz_realloc (res, op1_size); 61 /* No overlapping possible: op1_ptr = PTR(op1); */ 62 op2_ptr = PTR(op2); 63 res_ptr = PTR(res); 64 } 65 66 if (res_ptr != op1_ptr) 67 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, 68 op1_size - op2_size); 69 if (LIKELY (op2_size != 0)) 70 mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op2_size); 71 res_size = op1_size; 72 } 73 else 74 { 75 if (ALLOC(res) < op2_size) 76 { 77 _mpz_realloc (res, op2_size); 78 op1_ptr = PTR(op1); 79 /* No overlapping possible: op2_ptr = PTR(op2); */ 80 res_ptr = PTR(res); 81 } 82 83 if (res_ptr != op2_ptr) 84 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, 85 op2_size - op1_size); 86 if (LIKELY (op1_size != 0)) 87 mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); 88 res_size = op2_size; 89 } 90 91 MPN_NORMALIZE (res_ptr, res_size); 92 SIZ(res) = res_size; 93 return; 94 } 95 else /* op2_size < 0 */ 96 { 97 /* Fall through to the code at the end of the function. */ 98 } 99 } 100 else 101 { 102 if (op2_size < 0) 103 { 104 mp_ptr opx, opy; 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 TMP_ALLOC_LIMBS_2 (opx, op1_size, opy, op2_size); 117 mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1); 118 op1_ptr = opx; 119 120 mpn_sub_1 (opy, op2_ptr, op2_size, (mp_limb_t) 1); 121 op2_ptr = opy; 122 123 if (op1_size > op2_size) 124 MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size); 125 126 res_alloc = op2_size; 127 res_ptr = MPZ_REALLOC (res, res_alloc); 128 129 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, 130 op2_size - op1_size); 131 mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); 132 res_size = op2_size; 133 134 MPN_NORMALIZE (res_ptr, res_size); 135 SIZ(res) = res_size; 136 TMP_FREE; 137 return; 138 } 139 else 140 { 141 /* We should compute -OP1 ^ OP2. Swap OP1 and OP2 and fall 142 through to the code that handles OP1 ^ -OP2. */ 143 MPZ_SRCPTR_SWAP (op1, op2); 144 MPN_SRCPTR_SWAP (op1_ptr,op1_size, op2_ptr,op2_size); 145 } 146 } 147 148 { 149 mp_ptr opx; 150 mp_limb_t cy; 151 152 /* Operand 2 negative, so will be the result. 153 -(OP1 ^ (-OP2)) = -(OP1 ^ ~(OP2 - 1)) = 154 = ~(OP1 ^ ~(OP2 - 1)) + 1 = 155 = (OP1 ^ (OP2 - 1)) + 1 */ 156 157 op2_size = -op2_size; 158 159 opx = TMP_ALLOC_LIMBS (op2_size); 160 mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1); 161 op2_ptr = opx; 162 163 res_alloc = MAX (op1_size, op2_size) + 1; 164 if (ALLOC(res) < res_alloc) 165 { 166 _mpz_realloc (res, res_alloc); 167 op1_ptr = PTR(op1); 168 /* op2_ptr points to temporary space. */ 169 res_ptr = PTR(res); 170 } 171 172 if (op1_size > op2_size) 173 { 174 MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size); 175 mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op2_size); 176 res_size = op1_size; 177 } 178 else 179 { 180 MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size); 181 if (LIKELY (op1_size != 0)) 182 mpn_xor_n (res_ptr, op1_ptr, op2_ptr, op1_size); 183 res_size = op2_size; 184 } 185 186 cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1); 187 res_ptr[res_size] = cy; 188 res_size += (cy != 0); 189 190 MPN_NORMALIZE (res_ptr, res_size); 191 SIZ(res) = -res_size; 192 TMP_FREE; 193 } 194 }