Coverage Report

Created: 2025-12-31 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gmp/mpn/tdiv_qr.c
Line
Count
Source
1
/* mpn_tdiv_qr -- Divide the numerator (np,nn) by the denominator (dp,dn) and
2
   write the nn-dn+1 quotient limbs at qp and the dn remainder limbs at rp.  If
3
   qxn is non-zero, generate that many fraction limbs and append them after the
4
   other quotient limbs, and update the remainder accordingly.  The input
5
   operands are unaffected.
6
7
   Preconditions:
8
   1. The most significant limb of the divisor must be non-zero.
9
   2. nn >= dn, even if qxn is non-zero.  (??? relax this ???)
10
11
   The time complexity of this is O(qn*qn+M(dn,qn)), where M(m,n) is the time
12
   complexity of multiplication.
13
14
Copyright 1997, 2000-2002, 2005, 2009, 2015 Free Software Foundation, Inc.
15
16
This file is part of the GNU MP Library.
17
18
The GNU MP Library is free software; you can redistribute it and/or modify
19
it under the terms of either:
20
21
  * the GNU Lesser General Public License as published by the Free
22
    Software Foundation; either version 3 of the License, or (at your
23
    option) any later version.
24
25
or
26
27
  * the GNU General Public License as published by the Free Software
28
    Foundation; either version 2 of the License, or (at your option) any
29
    later version.
30
31
or both in parallel, as here.
32
33
The GNU MP Library is distributed in the hope that it will be useful, but
34
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
35
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
36
for more details.
37
38
You should have received copies of the GNU General Public License and the
39
GNU Lesser General Public License along with the GNU MP Library.  If not,
40
see https://www.gnu.org/licenses/.  */
41
42
#include "gmp-impl.h"
43
#include "longlong.h"
44
45
46
void
47
mpn_tdiv_qr (mp_ptr qp, mp_ptr rp, mp_size_t qxn,
48
       mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
49
130k
{
50
130k
  ASSERT_ALWAYS (qxn == 0);
51
52
130k
  ASSERT (nn >= 0);
53
130k
  ASSERT (dn >= 0);
54
130k
  ASSERT (dn == 0 || dp[dn - 1] != 0);
55
130k
  ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, np, nn));
56
130k
  ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, dp, dn));
57
58
130k
  switch (dn)
59
130k
    {
60
0
    case 0:
61
0
      DIVIDE_BY_ZERO;
62
63
10.7k
    case 1:
64
10.7k
      {
65
10.7k
  rp[0] = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, dp[0]);
66
10.7k
  return;
67
0
      }
68
69
4.63k
    case 2:
70
4.63k
      {
71
4.63k
  mp_ptr n2p;
72
4.63k
  mp_limb_t qhl, cy;
73
4.63k
  TMP_DECL;
74
4.63k
  TMP_MARK;
75
4.63k
  if ((dp[1] & GMP_NUMB_HIGHBIT) == 0)
76
3.85k
    {
77
3.85k
      int cnt;
78
3.85k
      mp_limb_t d2p[2];
79
3.85k
      count_leading_zeros (cnt, dp[1]);
80
3.85k
      cnt -= GMP_NAIL_BITS;
81
3.85k
      d2p[1] = (dp[1] << cnt) | (dp[0] >> (GMP_NUMB_BITS - cnt));
82
3.85k
      d2p[0] = (dp[0] << cnt) & GMP_NUMB_MASK;
83
3.85k
      n2p = TMP_ALLOC_LIMBS (nn + 1);
84
3.85k
      cy = mpn_lshift (n2p, np, nn, cnt);
85
3.85k
      n2p[nn] = cy;
86
3.85k
      qhl = mpn_divrem_2 (qp, 0L, n2p, nn + (cy != 0), d2p);
87
3.85k
      if (cy == 0)
88
1.32k
        qp[nn - 2] = qhl; /* always store nn-2+1 quotient limbs */
89
3.85k
      rp[0] = (n2p[0] >> cnt)
90
3.85k
        | ((n2p[1] << (GMP_NUMB_BITS - cnt)) & GMP_NUMB_MASK);
91
3.85k
      rp[1] = (n2p[1] >> cnt);
92
3.85k
    }
93
779
  else
94
779
    {
95
779
      n2p = TMP_ALLOC_LIMBS (nn);
96
779
      MPN_COPY (n2p, np, nn);
97
779
      qhl = mpn_divrem_2 (qp, 0L, n2p, nn, dp);
98
779
      qp[nn - 2] = qhl; /* always store nn-2+1 quotient limbs */
99
779
      rp[0] = n2p[0];
100
779
      rp[1] = n2p[1];
101
779
    }
102
4.63k
  TMP_FREE;
103
4.63k
  return;
104
0
      }
105
106
115k
    default:
107
115k
      {
108
115k
  int adjust;
109
115k
  gmp_pi1_t dinv;
110
115k
  TMP_DECL;
111
115k
  TMP_MARK;
112
115k
  adjust = np[nn - 1] >= dp[dn - 1];  /* conservative tests for quotient size */
113
115k
  if (nn + adjust >= 2 * dn)
114
74.7k
    {
115
74.7k
      mp_ptr n2p, d2p;
116
74.7k
      mp_limb_t cy;
117
74.7k
      int cnt;
118
119
74.7k
      qp[nn - dn] = 0;        /* zero high quotient limb */
120
74.7k
      if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0) /* normalize divisor */
121
5.55k
        {
122
5.55k
    count_leading_zeros (cnt, dp[dn - 1]);
123
5.55k
    cnt -= GMP_NAIL_BITS;
124
5.55k
    d2p = TMP_ALLOC_LIMBS (dn);
125
5.55k
    mpn_lshift (d2p, dp, dn, cnt);
126
5.55k
    n2p = TMP_ALLOC_LIMBS (nn + 1);
127
5.55k
    cy = mpn_lshift (n2p, np, nn, cnt);
128
5.55k
    n2p[nn] = cy;
129
5.55k
    nn += adjust;
130
5.55k
        }
131
69.1k
      else
132
69.1k
        {
133
69.1k
    cnt = 0;
134
69.1k
    d2p = (mp_ptr) dp;
135
69.1k
    n2p = TMP_ALLOC_LIMBS (nn + 1);
136
69.1k
    MPN_COPY (n2p, np, nn);
137
69.1k
    n2p[nn] = 0;
138
69.1k
    nn += adjust;
139
69.1k
        }
140
141
74.7k
      invert_pi1 (dinv, d2p[dn - 1], d2p[dn - 2]);
142
74.7k
      if (BELOW_THRESHOLD (dn, DC_DIV_QR_THRESHOLD))
143
74.4k
        mpn_sbpi1_div_qr (qp, n2p, nn, d2p, dn, dinv.inv32);
144
256
      else if (BELOW_THRESHOLD (dn, MUPI_DIV_QR_THRESHOLD) ||   /* fast condition */
145
0
         BELOW_THRESHOLD (nn, 2 * MU_DIV_QR_THRESHOLD) || /* fast condition */
146
0
         (double) (2 * (MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD)) * dn /* slow... */
147
0
         + (double) MUPI_DIV_QR_THRESHOLD * nn > (double) dn * nn)    /* ...condition */
148
256
        mpn_dcpi1_div_qr (qp, n2p, nn, d2p, dn, &dinv);
149
0
      else
150
0
        {
151
0
    mp_size_t itch = mpn_mu_div_qr_itch (nn, dn, 0);
152
0
    mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
153
0
    mpn_mu_div_qr (qp, rp, n2p, nn, d2p, dn, scratch);
154
0
    n2p = rp;
155
0
        }
156
157
74.7k
      if (cnt != 0)
158
5.55k
        mpn_rshift (rp, n2p, dn, cnt);
159
69.1k
      else
160
69.1k
        MPN_COPY (rp, n2p, dn);
161
74.7k
      TMP_FREE;
162
74.7k
      return;
163
74.7k
    }
164
165
  /* When we come here, the numerator/partial remainder is less
166
     than twice the size of the denominator.  */
167
168
40.3k
    {
169
      /* Problem:
170
171
         Divide a numerator N with nn limbs by a denominator D with dn
172
         limbs forming a quotient of qn=nn-dn+1 limbs.  When qn is small
173
         compared to dn, conventional division algorithms perform poorly.
174
         We want an algorithm that has an expected running time that is
175
         dependent only on qn.
176
177
         Algorithm (very informally stated):
178
179
         1) Divide the 2 x qn most significant limbs from the numerator
180
      by the qn most significant limbs from the denominator.  Call
181
      the result qest.  This is either the correct quotient, but
182
      might be 1 or 2 too large.  Compute the remainder from the
183
      division.  (This step is implemented by an mpn_divrem call.)
184
185
         2) Is the most significant limb from the remainder < p, where p
186
      is the product of the most significant limb from the quotient
187
      and the next(d)?  (Next(d) denotes the next ignored limb from
188
      the denominator.)  If it is, decrement qest, and adjust the
189
      remainder accordingly.
190
191
         3) Is the remainder >= qest?  If it is, qest is the desired
192
      quotient.  The algorithm terminates.
193
194
         4) Subtract qest x next(d) from the remainder.  If there is
195
      borrow out, decrement qest, and adjust the remainder
196
      accordingly.
197
198
         5) Skip one word from the denominator (i.e., let next(d) denote
199
      the next less significant limb.  */
200
201
40.3k
      mp_size_t qn;
202
40.3k
      mp_ptr n2p, d2p;
203
40.3k
      mp_ptr tp;
204
40.3k
      mp_limb_t cy;
205
40.3k
      mp_size_t in, rn;
206
40.3k
      mp_limb_t quotient_too_large;
207
40.3k
      unsigned int cnt;
208
209
40.3k
      qn = nn - dn;
210
40.3k
      qp[qn] = 0;       /* zero high quotient limb */
211
40.3k
      qn += adjust;     /* qn cannot become bigger */
212
213
40.3k
      if (qn == 0)
214
275
        {
215
275
    MPN_COPY (rp, np, dn);
216
275
    TMP_FREE;
217
275
    return;
218
275
        }
219
220
40.0k
      in = dn - qn;   /* (at least partially) ignored # of limbs in ops */
221
      /* Normalize denominator by shifting it to the left such that its
222
         most significant bit is set.  Then shift the numerator the same
223
         amount, to mathematically preserve quotient.  */
224
40.0k
      if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0)
225
26.3k
        {
226
26.3k
    count_leading_zeros (cnt, dp[dn - 1]);
227
26.3k
    cnt -= GMP_NAIL_BITS;
228
229
26.3k
    d2p = TMP_ALLOC_LIMBS (qn);
230
26.3k
    mpn_lshift (d2p, dp + in, qn, cnt);
231
26.3k
    d2p[0] |= dp[in - 1] >> (GMP_NUMB_BITS - cnt);
232
233
26.3k
    n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
234
26.3k
    cy = mpn_lshift (n2p, np + nn - 2 * qn, 2 * qn, cnt);
235
26.3k
    if (adjust)
236
14.7k
      {
237
14.7k
        n2p[2 * qn] = cy;
238
14.7k
        n2p++;
239
14.7k
      }
240
11.5k
    else
241
11.5k
      {
242
11.5k
        n2p[0] |= np[nn - 2 * qn - 1] >> (GMP_NUMB_BITS - cnt);
243
11.5k
      }
244
26.3k
        }
245
13.7k
      else
246
13.7k
        {
247
13.7k
    cnt = 0;
248
13.7k
    d2p = (mp_ptr) dp + in;
249
250
13.7k
    n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
251
13.7k
    MPN_COPY (n2p, np + nn - 2 * qn, 2 * qn);
252
13.7k
    if (adjust)
253
1.11k
      {
254
1.11k
        n2p[2 * qn] = 0;
255
1.11k
        n2p++;
256
1.11k
      }
257
13.7k
        }
258
259
      /* Get an approximate quotient using the extracted operands.  */
260
40.0k
      if (qn == 1)
261
9.74k
        {
262
9.74k
    mp_limb_t q0, r0;
263
9.74k
    udiv_qrnnd (q0, r0, n2p[1], n2p[0] << GMP_NAIL_BITS, d2p[0] << GMP_NAIL_BITS);
264
9.74k
    n2p[0] = r0 >> GMP_NAIL_BITS;
265
9.74k
    qp[0] = q0;
266
9.74k
        }
267
30.2k
      else if (qn == 2)
268
9.19k
        mpn_divrem_2 (qp, 0L, n2p, 4L, d2p); /* FIXME: obsolete function */
269
21.0k
      else
270
21.0k
        {
271
21.0k
    invert_pi1 (dinv, d2p[qn - 1], d2p[qn - 2]);
272
21.0k
    if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
273
19.8k
      mpn_sbpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, dinv.inv32);
274
1.23k
    else if (BELOW_THRESHOLD (qn, MU_DIV_QR_THRESHOLD))
275
1.23k
      mpn_dcpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, &dinv);
276
0
    else
277
0
      {
278
0
        mp_size_t itch = mpn_mu_div_qr_itch (2 * qn, qn, 0);
279
0
        mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
280
0
        mp_ptr r2p = rp;
281
0
        if (np == r2p) /* If N and R share space, put ... */
282
0
          r2p += nn - qn; /* intermediate remainder at N's upper end. */
283
0
        mpn_mu_div_qr (qp, r2p, n2p, 2 * qn, d2p, qn, scratch);
284
0
        MPN_COPY (n2p, r2p, qn);
285
0
      }
286
21.0k
        }
287
288
40.0k
      rn = qn;
289
      /* Multiply the first ignored divisor limb by the most significant
290
         quotient limb.  If that product is > the partial remainder's
291
         most significant limb, we know the quotient is too large.  This
292
         test quickly catches most cases where the quotient is too large;
293
         it catches all cases where the quotient is 2 too large.  */
294
40.0k
      {
295
40.0k
        mp_limb_t dl, x;
296
40.0k
        mp_limb_t h, dummy;
297
298
40.0k
        if (in - 2 < 0)
299
2.12k
    dl = 0;
300
37.9k
        else
301
37.9k
    dl = dp[in - 2];
302
303
40.0k
#if GMP_NAIL_BITS == 0
304
40.0k
        x = (dp[in - 1] << cnt) | ((dl >> 1) >> ((~cnt) % GMP_LIMB_BITS));
305
#else
306
        x = (dp[in - 1] << cnt) & GMP_NUMB_MASK;
307
        if (cnt != 0)
308
    x |= dl >> (GMP_NUMB_BITS - cnt);
309
#endif
310
40.0k
        umul_ppmm (h, dummy, x, qp[qn - 1] << GMP_NAIL_BITS);
311
312
40.0k
        if (n2p[qn - 1] < h)
313
2.56k
    {
314
2.56k
      mp_limb_t cy;
315
316
2.56k
      mpn_decr_u (qp, (mp_limb_t) 1);
317
2.56k
      cy = mpn_add_n (n2p, n2p, d2p, qn);
318
2.56k
      if (cy)
319
1.04k
        {
320
          /* The partial remainder is safely large.  */
321
1.04k
          n2p[qn] = cy;
322
1.04k
          ++rn;
323
1.04k
        }
324
2.56k
    }
325
40.0k
      }
326
327
40.0k
      quotient_too_large = 0;
328
40.0k
      if (cnt != 0)
329
26.3k
        {
330
26.3k
    mp_limb_t cy1, cy2;
331
332
    /* Append partially used numerator limb to partial remainder.  */
333
26.3k
    cy1 = mpn_lshift (n2p, n2p, rn, GMP_NUMB_BITS - cnt);
334
26.3k
    n2p[0] |= np[in - 1] & (GMP_NUMB_MASK >> cnt);
335
336
    /* Update partial remainder with partially used divisor limb.  */
337
26.3k
    cy2 = mpn_submul_1 (n2p, qp, qn, dp[in - 1] & (GMP_NUMB_MASK >> cnt));
338
26.3k
    if (qn != rn)
339
596
      {
340
596
        ASSERT_ALWAYS (n2p[qn] >= cy2);
341
596
        n2p[qn] -= cy2;
342
596
      }
343
25.7k
    else
344
25.7k
      {
345
25.7k
        n2p[qn] = cy1 - cy2; /* & GMP_NUMB_MASK; */
346
347
25.7k
        quotient_too_large = (cy1 < cy2);
348
25.7k
        ++rn;
349
25.7k
      }
350
26.3k
    --in;
351
26.3k
        }
352
      /* True: partial remainder now is neutral, i.e., it is not shifted up.  */
353
354
40.0k
      tp = TMP_ALLOC_LIMBS (dn);
355
356
40.0k
      if (in < qn)
357
13.0k
        {
358
13.0k
    if (in == 0)
359
1.71k
      {
360
1.71k
        MPN_COPY (rp, n2p, rn);
361
1.71k
        ASSERT_ALWAYS (rn == dn);
362
1.71k
        goto foo;
363
1.71k
      }
364
11.3k
    mpn_mul (tp, qp, qn, dp, in);
365
11.3k
        }
366
26.9k
      else
367
26.9k
        mpn_mul (tp, dp, in, qp, qn);
368
369
38.3k
      cy = mpn_sub (n2p, n2p, rn, tp + in, qn);
370
38.3k
      MPN_COPY (rp + in, n2p, dn - in);
371
38.3k
      quotient_too_large |= cy;
372
38.3k
      cy = mpn_sub_n (rp, np, tp, in);
373
38.3k
      cy = mpn_sub_1 (rp + in, rp + in, rn, cy);
374
38.3k
      quotient_too_large |= cy;
375
40.0k
    foo:
376
40.0k
      if (quotient_too_large)
377
1.69k
        {
378
1.69k
    mpn_decr_u (qp, (mp_limb_t) 1);
379
1.69k
    mpn_add_n (rp, rp, dp, dn);
380
1.69k
        }
381
40.0k
    }
382
40.0k
  TMP_FREE;
383
40.0k
  return;
384
38.3k
      }
385
130k
    }
386
130k
}