BSD 3 development
[unix-history] / usr / src / cmd / lisp / divbig.c
CommitLineData
8cd657f4
JF
1#include "global.h"
2
3#define b 0x40000000
4#define toint(p) ((int) (p))
5
6divbig(dividend, divisor, quotient, remainder)
7lispval dividend, divisor, *quotient, *remainder;
8{
9 register *ujp, *vip;
10 int *sp(), *alloca(), d, negflag = 0, m, n, carry, rem, qhat, j;
11 int borrow, negrem = 0;
12 int *utop = sp(), *ubot, *vbot, *qbot;
13 register lispval work; lispval export();
14
15 /* copy dividend */
16 for(work = dividend; work; work = work ->CDR)
17 stack(work->I);
18 ubot = sp();
19 if(*ubot < 0) { /* knuth's division alg works only for pos
20 bignums */
21 negflag ^= 1;
22 negrem = 1;
23 dsmult(utop-1,ubot,-1);
24 }
25 stack(0);
26 ubot = sp();
27
28
29 /*copy divisor */
30 for(work = divisor; work; work = work->CDR)
31 stack(work->I);
32
33 vbot = sp();
34 stack(0);
35 if(*vbot < 0) {
36 negflag ^= 1;
37 dsmult(ubot-1,vbot,-1);
38 }
39
40 /* check validity of data */
41 n = ubot - vbot;
42 m = utop - ubot - n - 1;
43 if (n == 1) {
44 /* do destructive division by a single. */
45 rem = dsdiv(utop-1,ubot,*vbot);
46 if(negrem)
47 rem = -rem;
48 if(negflag)
49 dsmult(utop-1,ubot,-1);
50 if(remainder)
51 *remainder = inewint(rem);
52 if(quotient)
53 *quotient = export(utop,ubot);
54 return;
55 }
56 if (m < 0) {
57 if (remainder)
58 *remainder = dividend;
59 if(quotient)
60 *quotient = inewint(0);
61 return;
62 }
63 qbot = alloca(toint(utop) + toint(vbot) - 2 * toint(ubot));
64d1:
65 d = b /(*vbot +1);
66 dsmult(utop-1,ubot,d);
67 dsmult(ubot-1,vbot,d);
68
69d2: for(j=0,ujp=ubot; j <= m; j++,ujp++) {
70
71 d3:
72 qhat = calqhat(ujp,vbot);
73 d4:
74 if((borrow = mlsb(ujp + n, ujp, ubot, -qhat)) < 0) {
75 adback(ujp + n, ujp, ubot);
76 qhat--;
77 }
78 qbot[j] = qhat;
79 }
80d8: if(remainder) {
81 dsdiv(utop, utop - n, d);
82 if(negrem) dsmult(utop-1,utop-n,-1);
83 *remainder = export(utop,utop-n);
84 }
85 if(quotient) {
86 if(negflag)
87 dsmult(qbot+m,qbot,-1);
88 *quotient = export(qbot + m + 1, qbot);
89 }
90}
91/*static*/ calqhat(ujp,v1p)
92register int *ujp, *v1p;
93{
94asm(" movl $0x3fffffff,r0");
95asm(" cmpl (r10),(r11)");
96asm(" beql on1");
97asm(" emul (r11),$0x40000000,4(r11),r1");
98asm(" ediv (r10),r1,r0,r5");
99asm("on1:");
100asm(" emul r0,4(r10),$0,r1");
101asm(" emul r5,$0x40000000,8(r11),r3");
102asm(" subl2 r3,r1");
103asm(" sbwc r4,r2");
104asm(" bleq out1");
105asm(" decl r0");
106asm("out1:");
107}
108/*static*/ mlsb(utop,ubot,vtop,nqhat)
109register int *utop, *ubot, *vtop;
110register int nqhat;
111{
112asm(" clrl r0");
113asm("loop2: addl2 (r11),r0");
114asm(" emul r8,-(r9),r0,r2");
115asm(" extzv $0,$30,r2,(r11)");
116asm(" extv $30,$32,r2,r0");
117asm(" acbl r10,$-4,r11,loop2");
118}
119/*static*/ adback(utop,ubot,vtop)
120register int *utop, *ubot, *vtop;
121{
122asm(" clrl r0");
123asm("loop3: addl2 -(r9),r0");
124asm(" addl2 (r11),r0");
125asm(" extzv $0,$30,r0,(r11)");
126asm(" extv $30,$2,r0,r0");
127asm(" acbl r10,$-4,r11,loop3");
128}
129/*static*/ dsdiv(top,bot,div)
130register int* bot;
131{
132asm(" clrl r0");
133asm("loop4: emul r0,$0x40000000,(r11),r1");
134asm(" ediv 12(ap),r1,(r11),r0");
135asm(" acbl 4(ap),$4,r11,loop4");
136}
137/*static*/ dsmult(top,bot,mult)
138register int* top;
139{
140asm(" clrl r0");
141asm("loop5: emul 12(ap),(r11),r0,r1");
142asm(" extzv $0,$30,r1,(r11)");
143asm(" extv $30,$32,r1,r0");
144asm(" acbl 8(ap),$-4,r11,loop5");
145asm(" movl r1,4(r11)");
146}
147/*static*/ lispval export(top,bot)
148register lispval bot;
149{
150 register r10, r9, r8, r7, r6;
151asm(" movl 4(ap),r10");
152asm(" movl $0xC0000000,r4");
153asm(" jmp Bexport");
154}
155
156#define MAXINT 0x8000000L
157
158Ihau(fix)
159register int fix;
160{
161 register count;
162 if(fix==MAXINT)
163 return(32);
164 if(fix < 0)
165 fix = -fix;
166 for(count = 0; fix; count++)
167 fix /= 2;
168 return(count);
169}
170lispval
171Lhau()
172{
173 register count;
174 register lispval handy;
175 register dum1,dum2;
176 register struct argent *lbot, *np;
177 lispval Labsval();
178
179 handy = lbot->val;
180top:
181 switch(TYPE(handy)) {
182 case INT:
183 count = Ihau(handy->i);
184 break;
185 case SDOT:
186 lbot->val = Labsval();
187 for(count = 0; handy->CDR!=((lispval) 0); handy = handy->CDR)
188 count += 30;
189 count += Ihau(handy->I);
190 break;
191 default:
192 handy = errorh(Vermisc,"Haulong: bad argument",nil,
193 TRUE,997,handy);
194 goto top;
195 }
196 return(inewint(count));
197}
198lispval
199Lhaipar()
200{
201 int *sp();
202 register lispval work;
203 register n;
204 register int *top = sp() - 1;
205 register int *bot;
206 register struct argent *lbot, *np;
207 int mylen;
208
209 /*chkarg(2);*/
210 work = lbot->val;
211 /* copy data onto stack */
212on1:
213 switch(TYPE(work)) {
214 case INT:
215 stack(work->i);
216 break;
217 case SDOT:
218 for(; work!=((lispval) 0); work = work->CDR)
219 stack(work->I);
220 break;
221 default:
222 work = errorh(Vermisc,"Haipart: bad first argument",nil,
223 TRUE,996,work);
224 goto on1;
225 }
226 bot = sp();
227 if(*bot < 0) {
228 stack(0);
229 dsmult(top,bot,-1);
230 bot--;
231 }
232 for(; *bot==0 && bot < top; bot++);
233 /* recalculate haulong internally */
234 mylen = (top - bot) * 30 + Ihau(*bot);
235 /* get second argument */
236 work = lbot[1].val;
237 while(TYPE(work)!=INT)
238 work = errorh(Vermisc,"Haipart: 2nd arg not int",nil,
239 TRUE,995,work);
240 n = work->i;
241 if(n >= mylen || -n >= mylen)
242 goto done;
243 if(n >= 0) {
244 /* Here we want n most significant bits
245 so chop off mylen - n bits */
246 stack(0);
247 n = mylen - n;
248 for(n; n >= 30; n -= 30)
249 top--;
250 if(top < bot)
251 error("Internal error in haipart #1",FALSE);
252 dsdiv(top,bot,1<<n);
253
254 } else {
255 /* here we want abs(n) low order bits */
256 stack(0);
257 bot = top + 1;
258 for(; n <= 0; n += 30)
259 bot--;
260 n = 30 - n;
261 *bot &= ~ (-1<<n);
262 }
263done:
264 return(export(top + 1,bot));
265}