Merge branch 'vendor/MDOCML'
[dragonfly.git] / contrib / gdtoa / dmisc.c
1 /****************************************************************
2
3 The author of this software is David M. Gay.
4
5 Copyright (C) 1998 by Lucent Technologies
6 All Rights Reserved
7
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
17
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS SOFTWARE.
26
27 ****************************************************************/
28
29 /* Please send bug reports to David M. Gay (dmg at acm dot org,
30  * with " at " changed at "@" and " dot " changed to ".").      */
31
32 #include "gdtoaimp.h"
33
34 #ifndef MULTIPLE_THREADS
35  char *dtoa_result;
36 #endif
37
38  char *
39 #ifdef KR_headers
40 rv_alloc(i) int i;
41 #else
42 rv_alloc(int i)
43 #endif
44 {
45         int j, k, *r;
46
47         j = sizeof(ULong);
48         for(k = 0;
49                 sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
50                 j <<= 1)
51                         k++;
52         r = (int*)Balloc(k);
53         *r = k;
54         return
55 #ifndef MULTIPLE_THREADS
56         dtoa_result =
57 #endif
58                 (char *)(r+1);
59         }
60
61  char *
62 #ifdef KR_headers
63 nrv_alloc(s, rve, n) char *s, **rve; int n;
64 #else
65 nrv_alloc(char *s, char **rve, int n)
66 #endif
67 {
68         char *rv, *t;
69
70         t = rv = rv_alloc(n);
71         while((*t = *s++) !=0)
72                 t++;
73         if (rve)
74                 *rve = t;
75         return rv;
76         }
77
78 /* freedtoa(s) must be used to free values s returned by dtoa
79  * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
80  * but for consistency with earlier versions of dtoa, it is optional
81  * when MULTIPLE_THREADS is not defined.
82  */
83
84  void
85 #ifdef KR_headers
86 freedtoa(s) char *s;
87 #else
88 freedtoa(char *s)
89 #endif
90 {
91         Bigint *b = (Bigint *)((int *)s - 1);
92         b->maxwds = 1 << (b->k = *(int*)b);
93         Bfree(b);
94 #ifndef MULTIPLE_THREADS
95         if (s == dtoa_result)
96                 dtoa_result = 0;
97 #endif
98         }
99
100  int
101 quorem
102 #ifdef KR_headers
103         (b, S) Bigint *b, *S;
104 #else
105         (Bigint *b, Bigint *S)
106 #endif
107 {
108         int n;
109         ULong *bx, *bxe, q, *sx, *sxe;
110 #ifdef ULLong
111         ULLong borrow, carry, y, ys;
112 #else
113         ULong borrow, carry, y, ys;
114 #ifdef Pack_32
115         ULong si, z, zs;
116 #endif
117 #endif
118
119         n = S->wds;
120 #ifdef DEBUG
121         /*debug*/ if (b->wds > n)
122         /*debug*/       Bug("oversize b in quorem");
123 #endif
124         if (b->wds < n)
125                 return 0;
126         sx = S->x;
127         sxe = sx + --n;
128         bx = b->x;
129         bxe = bx + n;
130         q = *bxe / (*sxe + 1);  /* ensure q <= true quotient */
131 #ifdef DEBUG
132         /*debug*/ if (q > 9)
133         /*debug*/       Bug("oversized quotient in quorem");
134 #endif
135         if (q) {
136                 borrow = 0;
137                 carry = 0;
138                 do {
139 #ifdef ULLong
140                         ys = *sx++ * (ULLong)q + carry;
141                         carry = ys >> 32;
142                         y = *bx - (ys & 0xffffffffUL) - borrow;
143                         borrow = y >> 32 & 1UL;
144                         *bx++ = y & 0xffffffffUL;
145 #else
146 #ifdef Pack_32
147                         si = *sx++;
148                         ys = (si & 0xffff) * q + carry;
149                         zs = (si >> 16) * q + (ys >> 16);
150                         carry = zs >> 16;
151                         y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
152                         borrow = (y & 0x10000) >> 16;
153                         z = (*bx >> 16) - (zs & 0xffff) - borrow;
154                         borrow = (z & 0x10000) >> 16;
155                         Storeinc(bx, z, y);
156 #else
157                         ys = *sx++ * q + carry;
158                         carry = ys >> 16;
159                         y = *bx - (ys & 0xffff) - borrow;
160                         borrow = (y & 0x10000) >> 16;
161                         *bx++ = y & 0xffff;
162 #endif
163 #endif
164                         }
165                         while(sx <= sxe);
166                 if (!*bxe) {
167                         bx = b->x;
168                         while(--bxe > bx && !*bxe)
169                                 --n;
170                         b->wds = n;
171                         }
172                 }
173         if (cmp(b, S) >= 0) {
174                 q++;
175                 borrow = 0;
176                 carry = 0;
177                 bx = b->x;
178                 sx = S->x;
179                 do {
180 #ifdef ULLong
181                         ys = *sx++ + carry;
182                         carry = ys >> 32;
183                         y = *bx - (ys & 0xffffffffUL) - borrow;
184                         borrow = y >> 32 & 1UL;
185                         *bx++ = y & 0xffffffffUL;
186 #else
187 #ifdef Pack_32
188                         si = *sx++;
189                         ys = (si & 0xffff) + carry;
190                         zs = (si >> 16) + (ys >> 16);
191                         carry = zs >> 16;
192                         y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
193                         borrow = (y & 0x10000) >> 16;
194                         z = (*bx >> 16) - (zs & 0xffff) - borrow;
195                         borrow = (z & 0x10000) >> 16;
196                         Storeinc(bx, z, y);
197 #else
198                         ys = *sx++ + carry;
199                         carry = ys >> 16;
200                         y = *bx - (ys & 0xffff) - borrow;
201                         borrow = (y & 0x10000) >> 16;
202                         *bx++ = y & 0xffff;
203 #endif
204 #endif
205                         }
206                         while(sx <= sxe);
207                 bx = b->x;
208                 bxe = bx + n;
209                 if (!*bxe) {
210                         while(--bxe > bx && !*bxe)
211                                 --n;
212                         b->wds = n;
213                         }
214                 }
215         return q;
216         }