Coverage Report

Created: 2026-02-14 06:49

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
101k
{
50
101k
  ASSERT_ALWAYS (qxn == 0);
51
52
101k
  ASSERT (nn >= 0);
53
101k
  ASSERT (dn >= 0);
54
101k
  ASSERT (dn == 0 || dp[dn - 1] != 0);
55
101k
  ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, np, nn));
56
101k
  ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, dp, dn));
57
58
101k
  switch (dn)
59
101k
    {
60
0
    case 0:
61
0
      DIVIDE_BY_ZERO;
62
63
8.32k
    case 1:
64
8.32k
      {
65
8.32k
  rp[0] = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, dp[0]);
66
8.32k
  return;
67
0
      }
68
69
3.69k
    case 2:
70
3.69k
      {
71
3.69k
  mp_ptr n2p;
72
3.69k
  mp_limb_t qhl, cy;
73
3.69k
  TMP_DECL;
74
3.69k
  TMP_MARK;
75
3.69k
  if ((dp[1] & GMP_NUMB_HIGHBIT) == 0)
76
3.02k
    {
77
3.02k
      int cnt;
78
3.02k
      mp_limb_t d2p[2];
79
3.02k
      count_leading_zeros (cnt, dp[1]);
80
3.02k
      cnt -= GMP_NAIL_BITS;
81
3.02k
      d2p[1] = (dp[1] << cnt) | (dp[0] >> (GMP_NUMB_BITS - cnt));
82
3.02k
      d2p[0] = (dp[0] << cnt) & GMP_NUMB_MASK;
83
3.02k
      n2p = TMP_ALLOC_LIMBS (nn + 1);
84
3.02k
      cy = mpn_lshift (n2p, np, nn, cnt);
85
3.02k
      n2p[nn] = cy;
86
3.02k
      qhl = mpn_divrem_2 (qp, 0L, n2p, nn + (cy != 0), d2p);
87
3.02k
      if (cy == 0)
88
1.06k
        qp[nn - 2] = qhl; /* always store nn-2+1 quotient limbs */
89
3.02k
      rp[0] = (n2p[0] >> cnt)
90
3.02k
        | ((n2p[1] << (GMP_NUMB_BITS - cnt)) & GMP_NUMB_MASK);
91
3.02k
      rp[1] = (n2p[1] >> cnt);
92
3.02k
    }
93
674
  else
94
674
    {
95
674
      n2p = TMP_ALLOC_LIMBS (nn);
96
674
      MPN_COPY (n2p, np, nn);
97
674
      qhl = mpn_divrem_2 (qp, 0L, n2p, nn, dp);
98
674
      qp[nn - 2] = qhl; /* always store nn-2+1 quotient limbs */
99
674
      rp[0] = n2p[0];
100
674
      rp[1] = n2p[1];
101
674
    }
102
3.69k
  TMP_FREE;
103
3.69k
  return;
104
0
      }
105
106
89.6k
    default:
107
89.6k
      {
108
89.6k
  int adjust;
109
89.6k
  gmp_pi1_t dinv;
110
89.6k
  TMP_DECL;
111
89.6k
  TMP_MARK;
112
89.6k
  adjust = np[nn - 1] >= dp[dn - 1];  /* conservative tests for quotient size */
113
89.6k
  if (nn + adjust >= 2 * dn)
114
57.3k
    {
115
57.3k
      mp_ptr n2p, d2p;
116
57.3k
      mp_limb_t cy;
117
57.3k
      int cnt;
118
119
57.3k
      qp[nn - dn] = 0;        /* zero high quotient limb */
120
57.3k
      if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0) /* normalize divisor */
121
4.49k
        {
122
4.49k
    count_leading_zeros (cnt, dp[dn - 1]);
123
4.49k
    cnt -= GMP_NAIL_BITS;
124
4.49k
    d2p = TMP_ALLOC_LIMBS (dn);
125
4.49k
    mpn_lshift (d2p, dp, dn, cnt);
126
4.49k
    n2p = TMP_ALLOC_LIMBS (nn + 1);
127
4.49k
    cy = mpn_lshift (n2p, np, nn, cnt);
128
4.49k
    n2p[nn] = cy;
129
4.49k
    nn += adjust;
130
4.49k
        }
131
52.8k
      else
132
52.8k
        {
133
52.8k
    cnt = 0;
134
52.8k
    d2p = (mp_ptr) dp;
135
52.8k
    n2p = TMP_ALLOC_LIMBS (nn + 1);
136
52.8k
    MPN_COPY (n2p, np, nn);
137
52.8k
    n2p[nn] = 0;
138
52.8k
    nn += adjust;
139
52.8k
        }
140
141
57.3k
      invert_pi1 (dinv, d2p[dn - 1], d2p[dn - 2]);
142
57.3k
      if (BELOW_THRESHOLD (dn, DC_DIV_QR_THRESHOLD))
143
57.0k
        mpn_sbpi1_div_qr (qp, n2p, nn, d2p, dn, dinv.inv32);
144
233
      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
233
        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
57.3k
      if (cnt != 0)
158
4.49k
        mpn_rshift (rp, n2p, dn, cnt);
159
52.8k
      else
160
52.8k
        MPN_COPY (rp, n2p, dn);
161
57.3k
      TMP_FREE;
162
57.3k
      return;
163
57.3k
    }
164
165
  /* When we come here, the numerator/partial remainder is less
166
     than twice the size of the denominator.  */
167
168
32.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
32.3k
      mp_size_t qn;
202
32.3k
      mp_ptr n2p, d2p;
203
32.3k
      mp_ptr tp;
204
32.3k
      mp_limb_t cy;
205
32.3k
      mp_size_t in, rn;
206
32.3k
      mp_limb_t quotient_too_large;
207
32.3k
      unsigned int cnt;
208
209
32.3k
      qn = nn - dn;
210
32.3k
      qp[qn] = 0;       /* zero high quotient limb */
211
32.3k
      qn += adjust;     /* qn cannot become bigger */
212
213
32.3k
      if (qn == 0)
214
199
        {
215
199
    MPN_COPY (rp, np, dn);
216
199
    TMP_FREE;
217
199
    return;
218
199
        }
219
220
32.1k
      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
32.1k
      if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0)
225
21.4k
        {
226
21.4k
    count_leading_zeros (cnt, dp[dn - 1]);
227
21.4k
    cnt -= GMP_NAIL_BITS;
228
229
21.4k
    d2p = TMP_ALLOC_LIMBS (qn);
230
21.4k
    mpn_lshift (d2p, dp + in, qn, cnt);
231
21.4k
    d2p[0] |= dp[in - 1] >> (GMP_NUMB_BITS - cnt);
232
233
21.4k
    n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
234
21.4k
    cy = mpn_lshift (n2p, np + nn - 2 * qn, 2 * qn, cnt);
235
21.4k
    if (adjust)
236
12.3k
      {
237
12.3k
        n2p[2 * qn] = cy;
238
12.3k
        n2p++;
239
12.3k
      }
240
9.18k
    else
241
9.18k
      {
242
9.18k
        n2p[0] |= np[nn - 2 * qn - 1] >> (GMP_NUMB_BITS - cnt);
243
9.18k
      }
244
21.4k
        }
245
10.6k
      else
246
10.6k
        {
247
10.6k
    cnt = 0;
248
10.6k
    d2p = (mp_ptr) dp + in;
249
250
10.6k
    n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
251
10.6k
    MPN_COPY (n2p, np + nn - 2 * qn, 2 * qn);
252
10.6k
    if (adjust)
253
936
      {
254
936
        n2p[2 * qn] = 0;
255
936
        n2p++;
256
936
      }
257
10.6k
        }
258
259
      /* Get an approximate quotient using the extracted operands.  */
260
32.1k
      if (qn == 1)
261
7.87k
        {
262
7.87k
    mp_limb_t q0, r0;
263
7.87k
    udiv_qrnnd (q0, r0, n2p[1], n2p[0] << GMP_NAIL_BITS, d2p[0] << GMP_NAIL_BITS);
264
7.87k
    n2p[0] = r0 >> GMP_NAIL_BITS;
265
7.87k
    qp[0] = q0;
266
7.87k
        }
267
24.2k
      else if (qn == 2)
268
7.24k
        mpn_divrem_2 (qp, 0L, n2p, 4L, d2p); /* FIXME: obsolete function */
269
17.0k
      else
270
17.0k
        {
271
17.0k
    invert_pi1 (dinv, d2p[qn - 1], d2p[qn - 2]);
272
17.0k
    if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
273
16.1k
      mpn_sbpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, dinv.inv32);
274
909
    else if (BELOW_THRESHOLD (qn, MU_DIV_QR_THRESHOLD))
275
909
      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
17.0k
        }
287
288
32.1k
      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
32.1k
      {
295
32.1k
        mp_limb_t dl, x;
296
32.1k
        mp_limb_t h, dummy;
297
298
32.1k
        if (in - 2 < 0)
299
1.81k
    dl = 0;
300
30.3k
        else
301
30.3k
    dl = dp[in - 2];
302
303
32.1k
#if GMP_NAIL_BITS == 0
304
32.1k
        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
32.1k
        umul_ppmm (h, dummy, x, qp[qn - 1] << GMP_NAIL_BITS);
311
312
32.1k
        if (n2p[qn - 1] < h)
313
2.14k
    {
314
2.14k
      mp_limb_t cy;
315
316
2.14k
      mpn_decr_u (qp, (mp_limb_t) 1);
317
2.14k
      cy = mpn_add_n (n2p, n2p, d2p, qn);
318
2.14k
      if (cy)
319
823
        {
320
          /* The partial remainder is safely large.  */
321
823
          n2p[qn] = cy;
322
823
          ++rn;
323
823
        }
324
2.14k
    }
325
32.1k
      }
326
327
32.1k
      quotient_too_large = 0;
328
32.1k
      if (cnt != 0)
329
21.4k
        {
330
21.4k
    mp_limb_t cy1, cy2;
331
332
    /* Append partially used numerator limb to partial remainder.  */
333
21.4k
    cy1 = mpn_lshift (n2p, n2p, rn, GMP_NUMB_BITS - cnt);
334
21.4k
    n2p[0] |= np[in - 1] & (GMP_NUMB_MASK >> cnt);
335
336
    /* Update partial remainder with partially used divisor limb.  */
337
21.4k
    cy2 = mpn_submul_1 (n2p, qp, qn, dp[in - 1] & (GMP_NUMB_MASK >> cnt));
338
21.4k
    if (qn != rn)
339
495
      {
340
495
        ASSERT_ALWAYS (n2p[qn] >= cy2);
341
495
        n2p[qn] -= cy2;
342
495
      }
343
20.9k
    else
344
20.9k
      {
345
20.9k
        n2p[qn] = cy1 - cy2; /* & GMP_NUMB_MASK; */
346
347
20.9k
        quotient_too_large = (cy1 < cy2);
348
20.9k
        ++rn;
349
20.9k
      }
350
21.4k
    --in;
351
21.4k
        }
352
      /* True: partial remainder now is neutral, i.e., it is not shifted up.  */
353
354
32.1k
      tp = TMP_ALLOC_LIMBS (dn);
355
356
32.1k
      if (in < qn)
357
10.2k
        {
358
10.2k
    if (in == 0)
359
1.47k
      {
360
1.47k
        MPN_COPY (rp, n2p, rn);
361
1.47k
        ASSERT_ALWAYS (rn == dn);
362
1.47k
        goto foo;
363
1.47k
      }
364
8.78k
    mpn_mul (tp, qp, qn, dp, in);
365
8.78k
        }
366
21.8k
      else
367
21.8k
        mpn_mul (tp, dp, in, qp, qn);
368
369
30.6k
      cy = mpn_sub (n2p, n2p, rn, tp + in, qn);
370
30.6k
      MPN_COPY (rp + in, n2p, dn - in);
371
30.6k
      quotient_too_large |= cy;
372
30.6k
      cy = mpn_sub_n (rp, np, tp, in);
373
30.6k
      cy = mpn_sub_1 (rp + in, rp + in, rn, cy);
374
30.6k
      quotient_too_large |= cy;
375
32.1k
    foo:
376
32.1k
      if (quotient_too_large)
377
1.46k
        {
378
1.46k
    mpn_decr_u (qp, (mp_limb_t) 1);
379
1.46k
    mpn_add_n (rp, rp, dp, dn);
380
1.46k
        }
381
32.1k
    }
382
32.1k
  TMP_FREE;
383
32.1k
  return;
384
30.6k
      }
385
101k
    }
386
101k
}