Coverage Report

Created: 2025-03-09 06:52

/src/gmp-6.2.1/mpn/remove.c
Line
Count
Source (jump to first uncovered line)
1
/* mpn_remove -- divide out all multiples of odd mpn number from another mpn
2
   number.
3
4
   Contributed to the GNU project by Torbjorn Granlund.
5
6
   THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
7
   SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
8
   GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
9
10
Copyright 2009, 2012-2014, 2017 Free Software Foundation, Inc.
11
12
This file is part of the GNU MP Library.
13
14
The GNU MP Library is free software; you can redistribute it and/or modify
15
it under the terms of either:
16
17
  * the GNU Lesser General Public License as published by the Free
18
    Software Foundation; either version 3 of the License, or (at your
19
    option) any later version.
20
21
or
22
23
  * the GNU General Public License as published by the Free Software
24
    Foundation; either version 2 of the License, or (at your option) any
25
    later version.
26
27
or both in parallel, as here.
28
29
The GNU MP Library is distributed in the hope that it will be useful, but
30
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
32
for more details.
33
34
You should have received copies of the GNU General Public License and the
35
GNU Lesser General Public License along with the GNU MP Library.  If not,
36
see https://www.gnu.org/licenses/.  */
37
38
#include "gmp-impl.h"
39
40
#if GMP_LIMB_BITS > 50
41
#define LOG 50
42
#else
43
#define LOG GMP_LIMB_BITS
44
#endif
45
46
47
/* Input: U = {up,un}, V = {vp,vn} must be odd, cap
48
   Ouput  W = {wp,*wn} allocation need is exactly *wn
49
50
   Set W = U / V^k, where k is the largest integer <= cap such that the
51
   division yields an integer.
52
53
   FIXME: We currently allow any operand overlap.  This is quite non mpn-ish
54
   and might be changed, since it cost significant temporary space.
55
   * If we require W to have space for un + 1 limbs, we could save qp or qp2
56
     (but we will still need to copy things into wp 50% of the time).
57
   * If we allow ourselves to clobber U, we could save the other of qp and qp2,
58
     and the initial COPY (but also here we would need un + 1 limbs).
59
*/
60
61
/* FIXME: We need to wrap mpn_bdiv_qr due to the itch interface.  This need
62
   indicates a flaw in the current itch mechanism: Which operands not greater
63
   than un,un will incur the worst itch?  We need a parallel foo_maxitch set
64
   of functions.  */
65
static void
66
mpn_bdiv_qr_wrap (mp_ptr qp, mp_ptr rp,
67
      mp_srcptr np, mp_size_t nn,
68
      mp_srcptr dp, mp_size_t dn)
69
5.25k
{
70
5.25k
  mp_ptr scratch_out;
71
5.25k
  TMP_DECL;
72
73
5.25k
  TMP_MARK;
74
5.25k
  scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (nn, dn));
75
5.25k
  mpn_bdiv_qr (qp, rp, np, nn, dp, dn, scratch_out);
76
77
5.25k
  TMP_FREE;
78
5.25k
}
79
80
mp_bitcnt_t
81
mpn_remove (mp_ptr wp, mp_size_t *wn,
82
      mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn,
83
      mp_bitcnt_t cap)
84
652
{
85
652
  mp_srcptr pwpsp[LOG];
86
652
  mp_size_t pwpsn[LOG];
87
652
  mp_size_t npowers;
88
652
  mp_ptr tp, qp, np, qp2;
89
652
  mp_srcptr pp;
90
652
  mp_size_t pn, nn, qn, i;
91
652
  mp_bitcnt_t pwr;
92
652
  TMP_DECL;
93
94
652
  ASSERT (un > 0);
95
652
  ASSERT (vn > 0);
96
652
  ASSERT (vp[0] % 2 != 0);  /* 2-adic division wants odd numbers */
97
652
  ASSERT (vn > 1 || vp[0] > 1); /* else we would loop indefinitely */
98
99
652
  TMP_MARK;
100
101
652
  TMP_ALLOC_LIMBS_3 (qp, un + 1, /* quotient, alternating */
102
652
         qp2, un + 1, /* quotient, alternating */
103
652
         tp, (un + 1 + vn) / 2); /* remainder */
104
652
  pp = vp;
105
652
  pn = vn;
106
107
652
  MPN_COPY (qp, up, un);
108
652
  qn = un;
109
110
652
  npowers = 0;
111
2.96k
  while (qn >= pn)
112
2.92k
    {
113
2.92k
      qp[qn] = 0;
114
2.92k
      mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
115
2.92k
      if (!mpn_zero_p (tp, pn))
116
2.92k
  {
117
2.92k
    if (mpn_cmp (tp, pp, pn) != 0)
118
570
      break;   /* could not divide by V^npowers */
119
2.92k
  }
120
121
2.35k
      MP_PTR_SWAP (qp, qp2);
122
2.35k
      qn = qn - pn;
123
2.35k
      mpn_neg (qp, qp, qn+1);
124
125
2.35k
      qn += qp[qn] != 0;
126
127
2.35k
      pwpsp[npowers] = pp;
128
2.35k
      pwpsn[npowers] = pn;
129
2.35k
      ++npowers;
130
131
2.35k
      if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
132
0
  break;
133
134
2.35k
      nn = 2 * pn - 1;    /* next power will be at least this large */
135
2.35k
      if (nn > qn)
136
49
  break;      /* next power would be overlarge */
137
138
2.30k
      if (npowers == 1)    /* Alloc once, but only if it's needed */
139
652
  np = TMP_ALLOC_LIMBS (qn + LOG);  /* powers of V */
140
1.65k
      else
141
1.65k
  np += pn;
142
143
2.30k
      mpn_sqr (np, pp, pn);
144
2.30k
      pn = nn + (np[nn] != 0);
145
2.30k
      pp = np;
146
2.30k
    }
147
148
652
  pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
149
150
3.00k
  for (i = npowers; --i >= 0;)
151
2.35k
    {
152
2.35k
      pn = pwpsn[i];
153
2.35k
      if (qn < pn)
154
29
  continue;
155
156
2.32k
      if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
157
0
  continue;   /* V^i would bring us past cap */
158
159
2.32k
      qp[qn] = 0;
160
2.32k
      mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pwpsp[i], pn);
161
2.32k
      if (!mpn_zero_p (tp, pn))
162
2.32k
  {
163
2.32k
    if (mpn_cmp (tp, pwpsp[i], pn) != 0)
164
1.23k
      continue;   /* could not divide by V^i */
165
2.32k
  }
166
167
1.09k
      MP_PTR_SWAP (qp, qp2);
168
1.09k
      qn = qn - pn;
169
1.09k
      mpn_neg (qp, qp, qn+1);
170
171
1.09k
      qn += qp[qn] != 0;
172
173
1.09k
      pwr += (mp_bitcnt_t) 1 << i;
174
1.09k
    }
175
176
652
  MPN_COPY (wp, qp, qn);
177
652
  *wn = qn;
178
179
652
  TMP_FREE;
180
181
652
  return pwr;
182
652
}