tdiv_qr_ui.c revision 1.1.1.1.8.1 1 1.1 mrg /* mpz_tdiv_qr_ui(quot,rem,dividend,short_divisor) --
2 1.1 mrg Set QUOT to DIVIDEND / SHORT_DIVISOR
3 1.1 mrg and REM to DIVIDEND mod SHORT_DIVISOR.
4 1.1 mrg
5 1.1.1.1.8.1 tls Copyright 1991, 1993, 1994, 1996, 1998, 2001, 2002, 2004, 2012 Free Software
6 1.1 mrg Foundation, Inc.
7 1.1 mrg
8 1.1 mrg This file is part of the GNU MP Library.
9 1.1 mrg
10 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
11 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
12 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
13 1.1 mrg option) any later version.
14 1.1 mrg
15 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
16 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 1.1 mrg License for more details.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU Lesser General Public License
21 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
22 1.1 mrg
23 1.1 mrg #include "gmp.h"
24 1.1 mrg #include "gmp-impl.h"
25 1.1 mrg
26 1.1 mrg unsigned long int
27 1.1 mrg mpz_tdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
28 1.1 mrg {
29 1.1 mrg mp_size_t ns, nn, qn;
30 1.1 mrg mp_ptr np, qp;
31 1.1 mrg mp_limb_t rl;
32 1.1 mrg
33 1.1.1.1.8.1 tls if (UNLIKELY (divisor == 0))
34 1.1 mrg DIVIDE_BY_ZERO;
35 1.1 mrg
36 1.1 mrg ns = SIZ(dividend);
37 1.1 mrg if (ns == 0)
38 1.1 mrg {
39 1.1 mrg SIZ(quot) = 0;
40 1.1 mrg SIZ(rem) = 0;
41 1.1 mrg return 0;
42 1.1 mrg }
43 1.1 mrg
44 1.1 mrg nn = ABS(ns);
45 1.1.1.1.8.1 tls qp = MPZ_REALLOC (quot, nn);
46 1.1 mrg np = PTR(dividend);
47 1.1 mrg
48 1.1 mrg #if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
49 1.1 mrg if (divisor > GMP_NUMB_MAX)
50 1.1 mrg {
51 1.1 mrg mp_limb_t dp[2];
52 1.1 mrg mp_ptr rp;
53 1.1 mrg mp_size_t rn;
54 1.1 mrg
55 1.1 mrg if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
56 1.1 mrg {
57 1.1 mrg SIZ(quot) = 0;
58 1.1 mrg rl = np[0];
59 1.1 mrg SIZ(rem) = ns >= 0 ? 1 : -1;
60 1.1 mrg PTR(rem)[0] = rl;
61 1.1 mrg return rl;
62 1.1 mrg }
63 1.1 mrg
64 1.1.1.1.8.1 tls rp = MPZ_REALLOC (rem, 2);
65 1.1 mrg
66 1.1 mrg dp[0] = divisor & GMP_NUMB_MASK;
67 1.1 mrg dp[1] = divisor >> GMP_NUMB_BITS;
68 1.1 mrg mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
69 1.1 mrg rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
70 1.1 mrg qn = nn - 2 + 1; qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
71 1.1 mrg rn = 2 - (rp[1] == 0); rn -= (rp[rn - 1] == 0);
72 1.1 mrg SIZ(rem) = ns >= 0 ? rn : -rn;
73 1.1 mrg }
74 1.1 mrg else
75 1.1 mrg #endif
76 1.1 mrg {
77 1.1 mrg rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
78 1.1 mrg if (rl == 0)
79 1.1 mrg SIZ(rem) = 0;
80 1.1 mrg else
81 1.1 mrg {
82 1.1 mrg /* Store the single-limb remainder. We don't check if there's space
83 1.1 mrg for just one limb, since no function ever makes zero space. */
84 1.1 mrg SIZ(rem) = ns >= 0 ? 1 : -1;
85 1.1 mrg PTR(rem)[0] = rl;
86 1.1 mrg }
87 1.1 mrg qn = nn - (qp[nn - 1] == 0);
88 1.1 mrg }
89 1.1 mrg
90 1.1 mrg SIZ(quot) = ns >= 0 ? qn : -qn;
91 1.1 mrg return rl;
92 1.1 mrg }
93