[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / runtime / gmp / mpz_dmincl.c
1 /* mpz_dmincl.c -- include file for mpz_dm.c, mpz_mod.c, mdiv.c.
2
3 Copyright (C) 1991 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with the GNU MP Library; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* THIS CODE IS OBSOLETE.  IT WILL SOON BE REPLACED BY CLEANER CODE WITH
22    LESS MEMORY ALLOCATION OVERHEAD.  */
23
24 /* If den == quot, den needs temporary storage.
25    If den == rem, den needs temporary storage.
26    If num == quot, num needs temporary storage.
27    If den has temporary storage, it can be normalized while being copied,
28      i.e no extra storage should be allocated.  */
29
30 /* This is the function body of mdiv, mpz_divmod, and mpz_mod.
31
32    If COMPUTE_QUOTIENT is defined, the quotient is put in the MP_INT
33    object quot, otherwise that variable is not referenced at all.
34
35    The remainder is always computed, and the result is put in the MP_INT
36    object rem.  */
37
38 {
39   mp_ptr np, dp;
40   mp_ptr qp, rp;
41   mp_size nsize = num->size;
42   mp_size dsize = den->size;
43   mp_size qsize, rsize;
44   mp_size sign_remainder = nsize;
45 #ifdef COMPUTE_QUOTIENT
46   mp_size sign_quotient = nsize ^ dsize;
47 #endif
48   unsigned normalization_steps;
49
50   nsize = ABS (nsize);
51   dsize = ABS (dsize);
52
53   /* Ensure space is enough for quotient and remainder. */
54
55   /* We need space for an extra limb in the remainder, because it's
56      up-shifted (normalized) below.  */
57   rsize = nsize + 1;
58   if (rem->alloc < rsize)
59     _mpz_realloc (rem, rsize);
60
61   qsize = nsize - dsize + 1;    /* qsize cannot be bigger than this.  */
62   if (qsize <= 0)
63     {
64 #ifdef COMPUTE_QUOTIENT
65       quot->size = 0;
66 #endif
67       if (num != rem)
68         {
69           rem->size = num->size;
70           MPN_COPY (rem->d, num->d, nsize);
71         }
72       return;
73     }
74
75 #ifdef COMPUTE_QUOTIENT
76   if (quot->alloc < qsize)
77     _mpz_realloc (quot, qsize);
78   qp = quot->d;
79 #else
80   qp = (mp_ptr) alloca (qsize * BYTES_PER_MP_LIMB);
81 #endif
82   np = num->d;
83   dp = den->d;
84   rp = rem->d;
85
86   /* Make sure quot and num are different.  Otherwise the numerator
87      would be successively overwritten by the quotient digits.  */
88   if (qp == np)
89     {
90       np = (mp_ptr) alloca (nsize * BYTES_PER_MP_LIMB);
91       MPN_COPY (np, qp, nsize);
92     }
93
94   count_leading_zeros (normalization_steps, dp[dsize - 1]);
95
96   /* Normalize the denominator, i.e. make its most significant bit set by
97      shifting it NORMALIZATION_STEPS bits to the left.  Also shift the
98      numerator the same number of steps (to keep the quotient the same!).  */
99   if (normalization_steps != 0)
100     {
101       mp_ptr tp;
102       mp_limb ndigit;
103
104       /* Shift up the denominator setting the most significant bit of
105          the most significant word.  Use temporary storage not to clobber
106          the original contents of the denominator.  */
107       tp = (mp_ptr) alloca (dsize * BYTES_PER_MP_LIMB);
108       (void) mpn_lshift (tp, dp, dsize, normalization_steps);
109       dp = tp;
110
111       /* Shift up the numerator, possibly introducing a new most
112          significant word.  Move the shifted numerator in the remainder
113          meanwhile.  */
114       ndigit = mpn_lshift (rp, np, nsize, normalization_steps);
115       if (ndigit != 0)
116         {
117           rp[nsize] = ndigit;
118           rsize = nsize + 1;
119         }
120       else
121         rsize = nsize;
122     }
123   else
124     {
125 #ifdef COMPUTE_QUOTIENT
126       if (rem == den || quot == den)
127 #else
128       if (rem == den)
129 #endif
130         {
131           mp_ptr tp;
132
133           tp = (mp_ptr) alloca (dsize * BYTES_PER_MP_LIMB);
134           MPN_COPY (tp, dp, dsize);
135           dp = tp;
136         }
137
138       /* Move the numerator to the remainder.  */
139       if (rp != np)
140         MPN_COPY (rp, np, nsize);
141
142       rsize = nsize;
143     }
144
145   qsize = rsize - dsize + mpn_div (qp, rp, rsize, dp, dsize);
146
147   rsize = dsize;
148
149   /* Normalize the remainder.  */
150   while (rsize > 0)
151     {
152       if (rp[rsize - 1] != 0)
153         break;
154       rsize--;
155     }
156
157   if (normalization_steps != 0)
158     rsize = mpn_rshift (rp, rp, rsize, normalization_steps);
159
160   rem->size = (sign_remainder >= 0) ? rsize : -rsize;
161
162 #ifdef COMPUTE_QUOTIENT
163   /* Normalize the quotient.  We may have at most one leading
164      zero-word, so no loop is needed.  */
165   if (qsize > 0)
166     qsize -= (qp[qsize - 1] == 0);
167
168   quot->size = (sign_quotient >= 0) ? qsize : -qsize;
169 #endif
170
171   alloca (0);
172 }