divexact.c revision 1.1.1.1
1/* mpz_divexact -- finds quotient when known that quot * den == num && den != 0.
2
3Contributed to the GNU project by Niels M�ller.
4
5Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2005,
62006, 2007, 2009 Free Software Foundation, Inc.
7
8This file is part of the GNU MP Library.
9
10The GNU MP Library is free software; you can redistribute it and/or modify
11it under the terms of the GNU Lesser General Public License as published by
12the Free Software Foundation; either version 3 of the License, or (at your
13option) any later version.
14
15The GNU MP Library is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18License for more details.
19
20You should have received a copy of the GNU Lesser General Public License
21along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
22
23
24#include "gmp.h"
25#include "gmp-impl.h"
26#include "longlong.h"
27
28void
29mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den)
30{
31  mp_ptr qp;
32  mp_size_t qn;
33  mp_srcptr np, dp;
34  mp_size_t nn, dn;
35  TMP_DECL;
36
37#if WANT_ASSERT
38  {
39    mpz_t  rem;
40    mpz_init (rem);
41    mpz_tdiv_r (rem, num, den);
42    ASSERT (SIZ(rem) == 0);
43    mpz_clear (rem);
44  }
45#endif
46
47  nn = ABSIZ (num);
48  dn = ABSIZ (den);
49
50  qn = nn - dn + 1;
51  MPZ_REALLOC (quot, qn);
52
53  if (nn < dn)
54    {
55      /* This special case avoids segfaults below when the function is
56	 incorrectly called with |N| < |D|, N != 0.  It also handles the
57	 well-defined case N = 0.  */
58      SIZ(quot) = 0;
59      return;
60    }
61
62  TMP_MARK;
63
64  qp = PTR(quot);
65
66  if (quot == num || quot == den)
67    qp = TMP_ALLOC_LIMBS (qn);
68
69  np = PTR(num);
70  dp = PTR(den);
71
72  mpn_divexact (qp, np, nn, dp, dn);
73  MPN_NORMALIZE (qp, qn);
74
75  SIZ(quot) = (SIZ(num) ^ SIZ(den)) >= 0 ? qn : -qn;
76
77  if (qp != PTR(quot))
78    MPN_COPY (PTR(quot), qp, qn);
79
80  TMP_FREE;
81}
82