tdiv_qr.c revision 1.1.1.2 1 1.1 mrg /* mpz_tdiv_qr(quot,rem,dividend,divisor) -- Set QUOT to DIVIDEND/DIVISOR,
2 1.1 mrg and REM to DIVIDEND mod DIVISOR.
3 1.1 mrg
4 1.1.1.2 mrg Copyright 1991, 1993, 1994, 2000, 2001, 2005, 2011, 2012 Free Software
5 1.1.1.2 mrg Foundation, Inc.
6 1.1 mrg
7 1.1 mrg This file is part of the GNU MP Library.
8 1.1 mrg
9 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
10 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
11 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
12 1.1 mrg option) any later version.
13 1.1 mrg
14 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
15 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 1.1 mrg License for more details.
18 1.1 mrg
19 1.1 mrg You should have received a copy of the GNU Lesser General Public License
20 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 1.1 mrg
22 1.1 mrg #include "gmp.h"
23 1.1 mrg #include "gmp-impl.h"
24 1.1 mrg #include "longlong.h"
25 1.1 mrg
26 1.1 mrg void
27 1.1 mrg mpz_tdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr num, mpz_srcptr den)
28 1.1 mrg {
29 1.1 mrg mp_size_t ql;
30 1.1 mrg mp_size_t ns, ds, nl, dl;
31 1.1 mrg mp_ptr np, dp, qp, rp;
32 1.1 mrg TMP_DECL;
33 1.1 mrg
34 1.1 mrg ns = SIZ (num);
35 1.1 mrg ds = SIZ (den);
36 1.1 mrg nl = ABS (ns);
37 1.1 mrg dl = ABS (ds);
38 1.1 mrg ql = nl - dl + 1;
39 1.1 mrg
40 1.1.1.2 mrg if (UNLIKELY (dl == 0))
41 1.1 mrg DIVIDE_BY_ZERO;
42 1.1 mrg
43 1.1.1.2 mrg rp = MPZ_REALLOC (rem, dl);
44 1.1 mrg
45 1.1 mrg if (ql <= 0)
46 1.1 mrg {
47 1.1 mrg if (num != rem)
48 1.1 mrg {
49 1.1 mrg np = PTR (num);
50 1.1 mrg MPN_COPY (rp, np, nl);
51 1.1 mrg SIZ (rem) = SIZ (num);
52 1.1 mrg }
53 1.1 mrg /* This needs to follow the assignment to rem, in case the
54 1.1 mrg numerator and quotient are the same. */
55 1.1 mrg SIZ (quot) = 0;
56 1.1 mrg return;
57 1.1 mrg }
58 1.1 mrg
59 1.1.1.2 mrg qp = MPZ_REALLOC (quot, ql);
60 1.1 mrg
61 1.1 mrg TMP_MARK;
62 1.1 mrg np = PTR (num);
63 1.1 mrg dp = PTR (den);
64 1.1 mrg
65 1.1 mrg /* FIXME: We should think about how to handle the temporary allocation.
66 1.1 mrg Perhaps mpn_tdiv_qr should handle it, since it anyway often needs to
67 1.1 mrg allocate temp space. */
68 1.1 mrg
69 1.1 mrg /* Copy denominator to temporary space if it overlaps with the quotient
70 1.1 mrg or remainder. */
71 1.1 mrg if (dp == rp || dp == qp)
72 1.1 mrg {
73 1.1 mrg mp_ptr tp;
74 1.1 mrg tp = TMP_ALLOC_LIMBS (dl);
75 1.1 mrg MPN_COPY (tp, dp, dl);
76 1.1 mrg dp = tp;
77 1.1 mrg }
78 1.1 mrg /* Copy numerator to temporary space if it overlaps with the quotient or
79 1.1 mrg remainder. */
80 1.1 mrg if (np == rp || np == qp)
81 1.1 mrg {
82 1.1 mrg mp_ptr tp;
83 1.1 mrg tp = TMP_ALLOC_LIMBS (nl);
84 1.1 mrg MPN_COPY (tp, np, nl);
85 1.1 mrg np = tp;
86 1.1 mrg }
87 1.1 mrg
88 1.1 mrg mpn_tdiv_qr (qp, rp, 0L, np, nl, dp, dl);
89 1.1 mrg
90 1.1 mrg ql -= qp[ql - 1] == 0;
91 1.1 mrg MPN_NORMALIZE (rp, dl);
92 1.1 mrg
93 1.1 mrg SIZ (quot) = (ns ^ ds) >= 0 ? ql : -ql;
94 1.1 mrg SIZ (rem) = ns >= 0 ? dl : -dl;
95 1.1 mrg TMP_FREE;
96 1.1 mrg }
97