1/* mpz_mul_ui/si (product, multiplier, small_multiplicand) -- Set PRODUCT to 2 MULTIPLICATOR times SMALL_MULTIPLICAND. 3 4Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2002, 2005, 2008 Free Software 5Foundation, Inc. 6 7This file is part of the GNU MP Library. 8 9The GNU MP Library is free software; you can redistribute it and/or modify 10it under the terms of the GNU Lesser General Public License as published by 11the Free Software Foundation; either version 3 of the License, or (at your 12option) any later version. 13 14The GNU MP Library is distributed in the hope that it will be useful, but 15WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17License for more details. 18 19You should have received a copy of the GNU Lesser General Public License 20along 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_mul_si 27#define FUNCTION mpz_mul_si 28#define MULTIPLICAND_UNSIGNED 29#define MULTIPLICAND_ABS(x) ABS_CAST(unsigned long, (x)) 30#endif 31 32#ifdef OPERATION_mul_ui 33#define FUNCTION mpz_mul_ui 34#define MULTIPLICAND_UNSIGNED unsigned 35#define MULTIPLICAND_ABS(x) x 36#endif 37 38#ifndef FUNCTION 39Error, error, unrecognised OPERATION 40#endif 41 42 43void 44FUNCTION (mpz_ptr prod, mpz_srcptr mult, 45 MULTIPLICAND_UNSIGNED long int small_mult) 46{ 47 mp_size_t size = SIZ(mult); 48 mp_size_t sign_product = size; 49 mp_limb_t sml; 50 mp_limb_t cy; 51 mp_ptr pp; 52 53 if (size == 0 || small_mult == 0) 54 { 55 SIZ(prod) = 0; 56 return; 57 } 58 59 size = ABS (size); 60 61 sml = MULTIPLICAND_ABS (small_mult); 62 63 if (sml <= GMP_NUMB_MAX) 64 { 65 MPZ_REALLOC (prod, size + 1); 66 pp = PTR(prod); 67 cy = mpn_mul_1 (pp, PTR(mult), size, sml & GMP_NUMB_MASK); 68 pp[size] = cy; 69 size += cy != 0; 70 } 71#if GMP_NAIL_BITS != 0 72 else 73 { 74 /* Operand too large for the current nails size. Use temporary for 75 intermediate products, to allow prod and mult being identical. */ 76 mp_ptr tp; 77 TMP_DECL; 78 TMP_MARK; 79 80 tp = TMP_ALLOC_LIMBS (size + 2); 81 82 cy = mpn_mul_1 (tp, PTR(mult), size, sml & GMP_NUMB_MASK); 83 tp[size] = cy; 84 cy = mpn_addmul_1 (tp + 1, PTR(mult), size, sml >> GMP_NUMB_BITS); 85 tp[size + 1] = cy; 86 size += 2; 87 MPN_NORMALIZE_NOT_ZERO (tp, size); /* too general, need to trim one or two limb */ 88 MPZ_REALLOC (prod, size); 89 pp = PTR(prod); 90 MPN_COPY (pp, tp, size); 91 TMP_FREE; 92 } 93#endif 94 95 SIZ(prod) = ((sign_product < 0) ^ (small_mult < 0)) ? -size : size; 96} 97