119026Sjulian/* mpz_com(mpz_ptr dst, mpz_ptr src) -- Assign the bit-complemented value of 267627Sasmodai SRC to DST. 319026Sjulian 419026SjulianCopyright 1991, 1993, 1994, 1996, 2001, 2003, 2012, 2015 Free Software 519026SjulianFoundation, Inc. 619026Sjulian 719026SjulianThis file is part of the GNU MP Library. 819026Sjulian 919026SjulianThe GNU MP Library is free software; you can redistribute it and/or modify 1019026Sjulianit under the terms of either: 1119026Sjulian 1219026Sjulian * the GNU Lesser General Public License as published by the Free 1319026Sjulian Software Foundation; either version 3 of the License, or (at your 1419026Sjulian option) any later version. 1519026Sjulian 1619026Sjulianor 1719026Sjulian 1819026Sjulian * the GNU General Public License as published by the Free Software 1919026Sjulian Foundation; either version 2 of the License, or (at your option) any 2019026Sjulian later version. 2119026Sjulian 2219026Sjulianor both in parallel, as here. 2319026Sjulian 2419026SjulianThe GNU MP Library is distributed in the hope that it will be useful, but 2519026SjulianWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 2650476Speteror FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2720920Swoschfor more details. 28264522Smav 295884SdgYou should have received copies of the GNU General Public License and the 3079538SruGNU Lesser General Public License along with the GNU MP Library. If not, 315884Sdgsee https://www.gnu.org/licenses/. */ 325884Sdg 3313472Swollman#include "gmp-impl.h" 345884Sdg 3513472Swollmanvoid 365884Sdgmpz_com (mpz_ptr dst, mpz_srcptr src) 375884Sdg{ 3868962Sru mp_size_t size = SIZ (src); 3979727Sschweikh mp_srcptr src_ptr; 4013472Swollman mp_ptr dst_ptr; 4113472Swollman 4213472Swollman if (size >= 0) 4379727Sschweikh { 445884Sdg /* As with infinite precision: one's complement, two's complement. 4513744Smpp But this can be simplified using the identity -x = ~x + 1. 4613472Swollman So we're going to compute (~~x) + 1 = x + 1! */ 4713472Swollman 4813472Swollman if (UNLIKELY (size == 0)) 4979727Sschweikh { 5013472Swollman /* special case, as mpn_add_1 wants size!=0 */ 5113472Swollman MPZ_NEWALLOC (dst, 1)[0] = 1; 5279727Sschweikh SIZ (dst) = -1; 53231244Sgjb } 5413472Swollman else 5540246Sken { 565884Sdg mp_limb_t cy; 5713472Swollman 5813472Swollman dst_ptr = MPZ_REALLOC (dst, size + 1); 5979727Sschweikh 6013472Swollman src_ptr = PTR (src); 6157676Ssheldonh 6257676Ssheldonh cy = mpn_add_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); 6379727Sschweikh dst_ptr[size] = cy; 645884Sdg size += cy; 656813Sdufault 6624091Smpp /* Store a negative size, to indicate ones-extension. */ 6724091Smpp SIZ (dst) = -size; 6824091Smpp } 6913472Swollman } 7079727Sschweikh else 7113472Swollman { 725884Sdg /* As with infinite precision: two's complement, then one's complement. 7324091Smpp But that can be simplified using the identity -x = ~(x - 1). 7424091Smpp So we're going to compute ~~(x - 1) = x - 1! */ 7524091Smpp size = -size; 766813Sdufault 776813Sdufault dst_ptr = MPZ_REALLOC (dst, size); 786813Sdufault 795884Sdg src_ptr = PTR (src); 805884Sdg 8113472Swollman mpn_sub_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); 825884Sdg size -= dst_ptr[size - 1] == 0; 8313472Swollman 8479727Sschweikh /* Store a positive size, to indicate zero-extension. */ 8513472Swollman SIZ (dst) = size; 865884Sdg } 875884Sdg} 8813472Swollman