Coverage Report

Created: 2025-04-11 06:45

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