1 1.1 mrg /* mpz_com(mpz_ptr dst, mpz_ptr src) -- Assign the bit-complemented value of 2 1.1 mrg SRC to DST. 3 1.1 mrg 4 1.1.1.4 mrg Copyright 1991, 1993, 1994, 1996, 2001, 2003, 2012, 2015 Free Software 5 1.1.1.4 mrg Foundation, Inc. 6 1.1 mrg 7 1.1 mrg This file is part of the GNU MP Library. 8 1.1 mrg 9 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 10 1.1.1.3 mrg it under the terms of either: 11 1.1.1.3 mrg 12 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free 13 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your 14 1.1.1.3 mrg option) any later version. 15 1.1.1.3 mrg 16 1.1.1.3 mrg or 17 1.1.1.3 mrg 18 1.1.1.3 mrg * the GNU General Public License as published by the Free Software 19 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any 20 1.1.1.3 mrg later version. 21 1.1.1.3 mrg 22 1.1.1.3 mrg or both in parallel, as here. 23 1.1 mrg 24 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 25 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 26 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27 1.1.1.3 mrg for more details. 28 1.1 mrg 29 1.1.1.3 mrg You should have received copies of the GNU General Public License and the 30 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 31 1.1.1.3 mrg see https://www.gnu.org/licenses/. */ 32 1.1 mrg 33 1.1 mrg #include "gmp-impl.h" 34 1.1 mrg 35 1.1 mrg void 36 1.1 mrg mpz_com (mpz_ptr dst, mpz_srcptr src) 37 1.1 mrg { 38 1.1.1.2 mrg mp_size_t size = SIZ (src); 39 1.1 mrg mp_srcptr src_ptr; 40 1.1 mrg mp_ptr dst_ptr; 41 1.1 mrg 42 1.1 mrg if (size >= 0) 43 1.1 mrg { 44 1.1 mrg /* As with infinite precision: one's complement, two's complement. 45 1.1 mrg But this can be simplified using the identity -x = ~x + 1. 46 1.1 mrg So we're going to compute (~~x) + 1 = x + 1! */ 47 1.1 mrg 48 1.1 mrg if (UNLIKELY (size == 0)) 49 1.1 mrg { 50 1.1 mrg /* special case, as mpn_add_1 wants size!=0 */ 51 1.1.1.4 mrg MPZ_NEWALLOC (dst, 1)[0] = 1; 52 1.1.1.2 mrg SIZ (dst) = -1; 53 1.1 mrg } 54 1.1.1.2 mrg else 55 1.1.1.2 mrg { 56 1.1.1.2 mrg mp_limb_t cy; 57 1.1 mrg 58 1.1.1.2 mrg dst_ptr = MPZ_REALLOC (dst, size + 1); 59 1.1 mrg 60 1.1.1.2 mrg src_ptr = PTR (src); 61 1.1.1.2 mrg 62 1.1.1.2 mrg cy = mpn_add_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); 63 1.1.1.2 mrg dst_ptr[size] = cy; 64 1.1.1.3 mrg size += cy; 65 1.1 mrg 66 1.1.1.2 mrg /* Store a negative size, to indicate ones-extension. */ 67 1.1.1.2 mrg SIZ (dst) = -size; 68 1.1.1.2 mrg } 69 1.1 mrg } 70 1.1 mrg else 71 1.1 mrg { 72 1.1 mrg /* As with infinite precision: two's complement, then one's complement. 73 1.1 mrg But that can be simplified using the identity -x = ~(x - 1). 74 1.1 mrg So we're going to compute ~~(x - 1) = x - 1! */ 75 1.1 mrg size = -size; 76 1.1 mrg 77 1.1.1.2 mrg dst_ptr = MPZ_REALLOC (dst, size); 78 1.1 mrg 79 1.1.1.2 mrg src_ptr = PTR (src); 80 1.1 mrg 81 1.1 mrg mpn_sub_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); 82 1.1 mrg size -= dst_ptr[size - 1] == 0; 83 1.1 mrg 84 1.1 mrg /* Store a positive size, to indicate zero-extension. */ 85 1.1.1.2 mrg SIZ (dst) = size; 86 1.1 mrg } 87 1.1 mrg } 88