"$Header: divbig.c,v 1.4 83/11/26 12:10:16 sklower Exp $";
/* -[Sat Jan 29 12:22:36 1983 by jkf]-
* (c) copyright 1982, Regents of the University of California
#define toint(p) ((int) (p))
divbig(dividend
, divisor
, quotient
, remainder
)
lispval dividend
, divisor
, *quotient
, *remainder
;
int *alloca(), d
, negflag
= 0, m
, n
, carry
, rem
, qhat
, j
;
long *utop
= sp(), *ubot
, *vbot
, *qbot
;
register lispval work
; lispval
export();
for(work
= dividend
; work
; work
= work
->s
.CDR
)
if(*ubot
< 0) { /* knuth's division alg works only for pos
for(work
= divisor
; work
; work
= work
->s
.CDR
)
/* check validity of data */
/* do destructive division by a single. */
rem
= dsdiv(utop
-1,ubot
,*vbot
);
*remainder
= inewint(rem
);
*quotient
= export(utop
,ubot
);
qbot
= alloca(toint(utop
) + toint(vbot
) - 2 * toint(ubot
));
d2
: for(j
=0,ujp
=ubot
; j
<= m
; j
++,ujp
++) {
qhat
= calqhat(ujp
,vbot
);
if((borrow
= mlsb(ujp
+ n
, ujp
, ubot
, -qhat
)) < 0) {
adback(ujp
+ n
, ujp
, ubot
);
dsdiv(utop
-1, utop
- n
, d
);
if(negrem
) dsmult(utop
-1,utop
-n
,-1);
*remainder
= export(utop
,utop
-n
);
*quotient
= export(qbot
+ m
+ 1, qbot
);
* asm code commented out due to optimizer bug
* also, this file is now shared with the 68k version!
asm(" cmpl (r10),(r11) # v[1] == u[j] ??");
asm(" # calculate qhat and rhat simultaneously,");
asm(" emul (r11),$0x40000000,4(r11),r4 # u[j]b+u[j+1] into r4,r5");
asm(" ediv (r10),r4,r0,r1 # qhat = ((u[j]b+u[j+1])/v[1]) into r0");
asm(" # (u[j]b+u[j+1] -qhat*v[1]) into r1");
asm(" # check if v[2]*qhat > rhat*b+u[j+2]");
asm(" emul r0,4(r10),$0,r2 # qhat*v[2] into r3,r2");
asm(" emul r1,$0x40000000,8(r11),r8 #rhat*b + u[j+2] into r9,r8");
asm(" # give up if r3,r2 <= r9,r8, otherwise iterate");
asm(" subl2 r8,r2 # perform r3,r2 - r9,r8");
asm(" bleq 3f # give up if negative or equal");
asm(" decl r0 # otherwise, qhat = qhat - 1");
asm(" addl2 (r10),r1 # since dec'ed qhat, inc rhat by v[1]");
asm(" # get here if v[1]==u[j]");
asm(" # set qhat to b-1");
asm(" # rhat is easily calculated since if we substitute b-1 for qhat in");
asm(" # the formula, then it simplifies to (u[j+1] + v[1])");
asm(" addl3 4(r11),(r10),r1 # rhat = u[j+1] + v[1]");
asm(" movl $0x3fffffff,r0 # qhat = b-1");
mlsb(utop,ubot,vtop,nqhat)
register int *utop, *ubot, *vtop;
asm("loop2: addl2 (r11),r0");
asm(" emul r8,-(r9),r0,r2");
asm(" extzv $0,$30,r2,(r11)");
asm(" extv $30,$32,r2,r0");
asm(" acbl r10,$-4,r11,loop2");
register int *utop, *ubot, *vtop;
asm("loop3: addl2 -(r9),r0");
asm(" extzv $0,$30,r0,(r11)");
asm(" extv $30,$2,r0,r0");
asm(" acbl r10,$-4,r11,loop3");
asm("loop4: emul r0,$0x40000000,(r11),r1");
asm(" ediv 12(ap),r1,(r11),r0");
asm(" acbl 4(ap),$4,r11,loop4");
asm("loop5: emul 12(ap),(r11),r0,r1");
asm(" extzv $0,$30,r1,(r11)");
asm(" extv $30,$32,r1,r0");
asm(" acbl 8(ap),$-4,r11,loop5");
register long *top
, *bot
;
top
--; /* screwey convention matches original
vax assembler convenience */
if(bot
==top
) return(inewint(*bot
));
#define MAXINT 0x80000000L
for(count
= 0; fix
; count
++)
for(count
= 0; handy
->s
.CDR
!=((lispval
) 0); handy
= handy
->s
.CDR
)
count
+= Ihau(handy
->s
.I
);
handy
= errorh1(Vermisc
,"Haulong: bad argument",nil
,
register int *top
= sp() - 1;
/* copy data onto stack */
for(; work
!=((lispval
) 0); work
= work
->s
.CDR
)
work
= errorh1(Vermisc
,"Haipart: bad first argument",nil
,
for(; *bot
==0 && bot
< top
; bot
++);
/* recalculate haulong internally */
mylen
= (top
- bot
) * 30 + Ihau(*bot
);
/* get second argument */
work
= errorh1(Vermisc
,"Haipart: 2nd arg not int",nil
,
if(n
>= mylen
|| -n
>= mylen
)
if(n
==0) return(inewint(0));
/* Here we want n most significant bits
so chop off mylen - n bits */
error("Internal error in haipart #1",FALSE
);
/* here we want abs(n) low order bits */
return(export(top
+ 1,bot
));
Ibiglsh(bignum
,count
,mode
)
register int *top
= sp() - 1;
int mylen
, guard
= 0, sticky
= 0, round
= 0;
/* get second argument */
work
= errorh1(Vermisc
,"Bignum-shift: 2nd arg not int",nil
,
for(; n
>= 30; n
-= 30) {/* Here we want to multiply by 2^n
so start by copying n/30 zeroes
work
= bignum
; /* copy data onto stack */
for(; work
!=((lispval
) 0); work
= work
->s
.CDR
)
work
= errorh1(Vermisc
,"Bignum-shift: bad bignum argument",nil
,
/* Trimming will only work without leading
zeroes without my having to think
a lot harder about it, if the inputs
for(n
= -n
; n
> 30; n
-= 30) {
round
= dsrsh(top
,bot
,-n
,-1<<n
);
stack(0); /*so that dsadd1 will work;*/
if(((*top
&1)==0) && (round
| guard
| sticky
))
} else if (mode
==TOEVEN
) {
if(! (round
& mask
) ) goto chop
;
&& (*top
&1)==0 ) goto chop
;
work
= export(top
+ 1,bot
);
/*From drb Mon Jul 27 01:25:56 1981
The idea is that the answer/2
is equal to the exact answer/2 rounded towards - infinity. The final bit
of the answer is the "or" of the true final bit, together with all true
bits after the binary point. In other words, the 1's bit of the answer
is almost always 1. THE FINAL BIT OF THE ANSWER IS 0 IFF n*2^i = THE
ANSWER RETURNED EXACTLY, WITH A 0 FINAL BIT.
To try again, more succintly: the answer is correct to within 1, and
the 1's bit of the answer will be 0 only if the answer is exactly
register struct argent
*mylbot
= lbot
;
chkarg(2,"sticky-bignum-leftshift");
return(Ibiglsh(lbot
->val
,lbot
[1].val
,STICKY
));
register struct argent
*mylbot
= lbot
;
chkarg(2,"bignum-leftshift");
return(Ibiglsh(lbot
->val
,lbot
[1].val
,TOEVEN
));
HackHex() /* this is a one minute function so drb and kls can debug biglsh */
/* (HackHex i) returns a string which is the result of printing i in hex */
register struct argent
*mylbot
= lbot
;
sprintf(buf
,"%lx",lbot
->val
->i
);
return((lispval
)inewstr(buf
));