1 /* mpz_add_ui, mpz_sub_ui -- Add or subtract an mpz_t and an unsigned 2 one-word integer. 3 4 Copyright 1991, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2004 Free Software 5 Foundation, Inc. 6 7 This file is part of the GNU MP Library. 8 9 The GNU MP Library is free software; you can redistribute it and/or modify 10 it under the terms of the GNU Lesser General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or (at your 12 option) any later version. 13 14 The GNU MP Library is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17 License for more details. 18 19 You should have received a copy of the GNU Lesser General Public License 20 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 21 22 #include "gmp.h" 23 #include "gmp-impl.h" 24 25 26 #ifdef OPERATION_add_ui 27 #define FUNCTION mpz_add_ui 28 #define FUNCTION2 mpz_add 29 #define VARIATION_CMP >= 30 #define VARIATION_NEG 31 #define VARIATION_UNNEG - 32 #endif 33 34 #ifdef OPERATION_sub_ui 35 #define FUNCTION mpz_sub_ui 36 #define FUNCTION2 mpz_sub 37 #define VARIATION_CMP < 38 #define VARIATION_NEG - 39 #define VARIATION_UNNEG 40 #endif 41 42 #ifndef FUNCTION 43 Error, need OPERATION_add_ui or OPERATION_sub_ui 44 #endif 45 46 47 void 48 FUNCTION (mpz_ptr w, mpz_srcptr u, unsigned long int vval) 49 { 50 mp_srcptr up; 51 mp_ptr wp; 52 mp_size_t usize, wsize; 53 mp_size_t abs_usize; 54 55 #if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */ 56 if (vval > GMP_NUMB_MAX) 57 { 58 mpz_t v; 59 mp_limb_t vl[2]; 60 PTR(v) = vl; 61 vl[0] = vval & GMP_NUMB_MASK; 62 vl[1] = vval >> GMP_NUMB_BITS; 63 SIZ(v) = 2; 64 FUNCTION2 (w, u, v); 65 return; 66 } 67 #endif 68 69 usize = u->_mp_size; 70 abs_usize = ABS (usize); 71 72 /* If not space for W (and possible carry), increase space. */ 73 wsize = abs_usize + 1; 74 if (w->_mp_alloc < wsize) 75 _mpz_realloc (w, wsize); 76 77 /* These must be after realloc (U may be the same as W). */ 78 up = u->_mp_d; 79 wp = w->_mp_d; 80 81 if (abs_usize == 0) 82 { 83 wp[0] = vval; 84 w->_mp_size = VARIATION_NEG (vval != 0); 85 return; 86 } 87 88 if (usize VARIATION_CMP 0) 89 { 90 mp_limb_t cy; 91 cy = mpn_add_1 (wp, up, abs_usize, (mp_limb_t) vval); 92 wp[abs_usize] = cy; 93 wsize = VARIATION_NEG (abs_usize + cy); 94 } 95 else 96 { 97 /* The signs are different. Need exact comparison to determine 98 which operand to subtract from which. */ 99 if (abs_usize == 1 && up[0] < vval) 100 { 101 wp[0] = vval - up[0]; 102 wsize = VARIATION_NEG 1; 103 } 104 else 105 { 106 mpn_sub_1 (wp, up, abs_usize, (mp_limb_t) vval); 107 /* Size can decrease with at most one limb. */ 108 wsize = VARIATION_UNNEG (abs_usize - (wp[abs_usize - 1] == 0)); 109 } 110 } 111 112 w->_mp_size = wsize; 113 } 114