[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[no subject]
- To: ALAN at MIT-MC, DLA at MIT-EECS
- From: JONL at MIT-MC (Jon L White)
- Date: Sun ,15 Mar 81 01:16:00 EDT
- Cc: (BUG LISP) at MIT-MC, INFO-LISPM at MIT-MC
Date: 14 March 1981 00:36-EST
From: Alan Bawden <ALAN at MIT-MC>
Date: 14 Mar 1981 0007-EST
From: David L. Andre <DLA at MIT-EECS>
Is it possible to get, in a single operation, both the quotient and
remainder in a fixnum division? I have often wanted to do something
like:
(MULTIPLE-VALUE (QUO REM)
(FLOOR A B))
So have I. Unfortunately it is rather difficult to get this to work
since arithmetic is performed in microcode, and it is difficult to get
multiple values out from microcode. . . .
I can appreciate your comments about how the hardware loses -- the IBM370
produces a floating-division result much like the PDP-10 FDVL instruction,
and then proceeds to round according to its own fixed rule. During my
time working for there, I needed to experiment with some alternate
rounding schemes, and was chagrin'd to discover that there was no
way to get the "remainder" part out of the "internal" registers and
into a place where the macro-code instructions could access it.
foo.
I've implemented some internal fixnum functions for NIL, so that
generic arithemetic can be fully-implemented in LISP -- basically they
represent the four rational operations as implemented by most 2's-
complement computers. For a real NIL, the compiler is open-coding them
"by special discernment", rather than by doing a multiple-value-returning
function call; so it only is a matter of being able to get at all the bits
implicit in the two results. I've coded up this stuff for the PDP10 too,
but the COMPLR doesn't open-compile these funs; rather, it calls some
quick, handy little LAP subrs. Below is reproduced the documentation on
them from file MC:NIL;NEWFUN >
SI:FULLADD (SI:FULLADD x y carry_in) ==> [sum.x+y+carry_in, carry_out]
SI:FULLSUB (SI:FULLSUB x y carry_in) ==> [difference.x-y+carry_in, carry_out]
Where the sum and difference indicated are two's complement results,
and the "carry"s are all restricted to -1, 0 and +1. Since true
integer addition cannot be restricted to a finite range, there must be
"wrap-around" even in these functions. Thus, let n+1 be the number
of bits in the FIXNUM (two's-complement) representation; then
mx :== 2^n - 1 ;maximum representible (positive) FIXNUM
mnx :== -2^n ;minimum representible (negative) FIXNUM
Then both (SI:FULLADD mnx mnx -1) and (SI:FULLSUB mx mnx 1) will
"wrap-around" (i.e., "overflow"). Thus a fail-safe, but slightly
pessimistic, test for "overflow" is merely to test the second argument
for being equal to "mnx". Happily, the most important system
usages of these two have an explicit 0 carry_in, but at a few places
in the BIGNUM implementation they require the full generality.
SI:FULLMUL (SI:FULLMUL x y carry_in) ==> let productsum == x*y+carry_in
[productsum.rem.by.2^n, productsum.div.by.2^n]
Note that if both x and y are equal to "mnx" as described above, the
the result will "overflow".
SI:FULLDIV (SI:FULLDIV low hi divsr) ==> [quotient, remainder]
The division indicated is (hi*2^n+low)/divsr