1/* mpn_submul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR
2   by S2_LIMB, subtract the S1_SIZE least significant limbs of the product
3   from the limb vector pointed to by RES_PTR.  Return the most significant
4   limb of the product, adjusted for carry-out from the subtraction.
5
6Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
7
8This file is part of the GNU MP Library.
9
10The GNU MP Library is free software; you can redistribute it and/or modify
11it under the terms of the GNU Library General Public License as published by
12the Free Software Foundation; either version 2 of the License, or (at your
13option) any later version.
14
15The GNU MP Library is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
18License for more details.
19
20You should have received a copy of the GNU Library General Public License
21along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
22the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23MA 02111-1307, USA. */
24
25#include "gmp.h"
26#include "gmp-impl.h"
27#include "longlong.h"
28
29mp_limb_t
30mpn_submul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
31     register mp_ptr res_ptr;
32     register mp_srcptr s1_ptr;
33     mp_size_t s1_size;
34     register mp_limb_t s2_limb;
35{
36  register mp_limb_t cy_limb;
37  register mp_size_t j;
38  register mp_limb_t prod_high, prod_low;
39  register mp_limb_t x;
40
41  /* The loop counter and index J goes from -SIZE to -1.  This way
42     the loop becomes faster.  */
43  j = -s1_size;
44
45  /* Offset the base pointers to compensate for the negative indices.  */
46  res_ptr -= j;
47  s1_ptr -= j;
48
49  cy_limb = 0;
50  do
51    {
52      umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
53
54      prod_low += cy_limb;
55      cy_limb = (prod_low < cy_limb) + prod_high;
56
57      x = res_ptr[j];
58      prod_low = x - prod_low;
59      cy_limb += (prod_low > x);
60      res_ptr[j] = prod_low;
61    }
62  while (++j != 0);
63
64  return cy_limb;
65}
66