1/* mpz_fdiv_ui -- Division rounding the quotient towards -infinity.
2   The remainder gets the same sign as the denominator.
3
4Copyright 1994, 1995, 1996, 2001, 2002, 2004, 2005 Free Software Foundation,
5Inc.
6
7This file is part of the GNU MP Library.
8
9The GNU MP Library is free software; you can redistribute it and/or modify
10it under the terms of the GNU Lesser General Public License as published by
11the Free Software Foundation; either version 3 of the License, or (at your
12option) any later version.
13
14The GNU MP Library is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17License for more details.
18
19You should have received a copy of the GNU Lesser General Public License
20along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
21
22#include "gmp.h"
23#include "gmp-impl.h"
24
25unsigned long int
26mpz_fdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
27{
28  mp_size_t ns, nn;
29  mp_ptr np;
30  mp_limb_t rl;
31
32  if (divisor == 0)
33    DIVIDE_BY_ZERO;
34
35  ns = SIZ(dividend);
36  if (ns == 0)
37    {
38      return 0;
39    }
40
41  nn = ABS(ns);
42  np = PTR(dividend);
43#if BITS_PER_ULONG > GMP_NUMB_BITS  /* avoid warnings about shift amount */
44  if (divisor > GMP_NUMB_MAX)
45    {
46      mp_limb_t dp[2], rp[2];
47      mp_ptr qp;
48      mp_size_t rn;
49      TMP_DECL;
50
51      if (nn == 1)		/* tdiv_qr requirements; tested above for 0 */
52	{
53	  rl = np[0];
54	  rp[0] = rl;
55	}
56      else
57	{
58	  TMP_MARK;
59	  dp[0] = divisor & GMP_NUMB_MASK;
60	  dp[1] = divisor >> GMP_NUMB_BITS;
61	  qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
62	  mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
63	  TMP_FREE;
64	  rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
65	}
66
67      if (rl != 0 && ns < 0)
68	{
69	  rl = divisor - rl;
70	  rp[0] = rl & GMP_NUMB_MASK;
71	  rp[1] = rl >> GMP_NUMB_BITS;
72	}
73
74      rn = 1 + (rl > GMP_NUMB_MAX);  rn -= (rp[rn - 1] == 0);
75    }
76  else
77#endif
78    {
79      rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
80      if (rl == 0)
81	;
82      else
83	{
84	  if (ns < 0)
85	    rl = divisor - rl;
86	}
87    }
88
89  return rl;
90}
91