cdiv_q_ui.c revision 1.1.1.2 1 1.1 mrg /* mpz_cdiv_q_ui -- Division rounding the quotient towards +infinity. The
2 1.1 mrg remainder gets the opposite sign as the denominator. In order to make it
3 1.1 mrg always fit into the return type, the negative of the true remainder is
4 1.1 mrg returned.
5 1.1 mrg
6 1.1.1.2 mrg Copyright 1994, 1996, 1999, 2001, 2002, 2004, 2012 Free Software Foundation,
7 1.1.1.2 mrg Inc.
8 1.1 mrg
9 1.1 mrg This file is part of the GNU MP Library.
10 1.1 mrg
11 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
12 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
13 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
14 1.1 mrg option) any later version.
15 1.1 mrg
16 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
17 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 1.1 mrg License for more details.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU Lesser General Public License
22 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
23 1.1 mrg
24 1.1 mrg #include "gmp.h"
25 1.1 mrg #include "gmp-impl.h"
26 1.1 mrg
27 1.1 mrg unsigned long int
28 1.1 mrg mpz_cdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
29 1.1 mrg {
30 1.1 mrg mp_size_t ns, nn, qn;
31 1.1 mrg mp_ptr np, qp;
32 1.1 mrg mp_limb_t rl;
33 1.1 mrg
34 1.1.1.2 mrg if (UNLIKELY (divisor == 0))
35 1.1 mrg DIVIDE_BY_ZERO;
36 1.1 mrg
37 1.1 mrg ns = SIZ(dividend);
38 1.1 mrg if (ns == 0)
39 1.1 mrg {
40 1.1 mrg SIZ(quot) = 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.2 mrg 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], rp[2];
52 1.1 mrg
53 1.1 mrg if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
54 1.1 mrg {
55 1.1 mrg qp[0] = 0;
56 1.1 mrg rl = np[0];
57 1.1 mrg qn = 1; /* a white lie, fixed below */
58 1.1 mrg }
59 1.1 mrg else
60 1.1 mrg {
61 1.1 mrg dp[0] = divisor & GMP_NUMB_MASK;
62 1.1 mrg dp[1] = divisor >> GMP_NUMB_BITS;
63 1.1 mrg mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
64 1.1 mrg rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
65 1.1 mrg qn = nn - 2 + 1;
66 1.1 mrg }
67 1.1 mrg
68 1.1 mrg if (rl != 0 && ns >= 0)
69 1.1 mrg {
70 1.1 mrg mpn_incr_u (qp, (mp_limb_t) 1);
71 1.1 mrg rl = divisor - rl;
72 1.1 mrg }
73 1.1 mrg
74 1.1 mrg qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
75 1.1 mrg }
76 1.1 mrg else
77 1.1 mrg #endif
78 1.1 mrg {
79 1.1 mrg rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
80 1.1 mrg
81 1.1 mrg if (rl != 0 && ns >= 0)
82 1.1 mrg {
83 1.1 mrg mpn_incr_u (qp, (mp_limb_t) 1);
84 1.1 mrg rl = divisor - rl;
85 1.1 mrg }
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