Newsgroups : Borland : borland.public.delphi.rtl.win32 : 2005 Aug : Division of Quad by Double...

www.cryer.info
Managed Newsgroup Archive

Division of Quad by Double...

Subject:Division of Quad by Double...
Posted by:"Ian Boyd" (ian.borlandnews008@zunblvlda1.dyndns.org.spamsucks)
Date:Tue, 9 Aug 2005 22:49:40

i'm doing multiprecision division. At it's basic level, i must concatenate
two unsigned 32-bit values (LongWords) and
divided by another 32-bit unsigned value (LongWord).

It is guaranteed that the result of the division will be <= 32 bits
(LongWord)


So, my pseudo code is:

function QuadDivDouble(x1, x0: LongWord; y: LongWord): LongWord;
{ Unsigned divide x1:x0 by y }
begin
{$RANGECHECKS OFF}
    Result := ((Int64(x1) shl 32) or x0) div y;
{$RANGECHECKS ON}
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    x1, x0, y, R: LongWord;
begin
    {calculate $FFFFFFFE00000001 div $FFFFFFFF }
    x1 := $FFFFFFFE;
    x0 := $00000001;
    y :=  $FFFFFFFF;

    R := QuadDivDouble(x1, x0, y);

    //Correct answer is $FFFFFFFF
    //Delphi gives answer $FFFFFFFE
    Assert(R = $FFFFFFFF, 'Nope.');
end;

But this doesn't work, i assume because Int64 is signed. But i don't know
how to how to fool Delphi into doing the division unsigned.  i'm sure it
cannot be done in Delphi, and you have to use assember.

i have no practical experience with asm, but i'll pretend it's something
like this:

procedure QuadDivMod(var x0, x1: LongWord; y: LongWord);
{    Unsigned divide x1:x0 by doubleword y
    x0 := Quotient
    x1 := Remainder

    Intel says:
    DIV is Unsigned divide EDX:EAX by r/m32 doubleword;
    EAX <- Quotient, EDX <- Remainder }
asm
{   i assume
        x0 is passed in EAX
        x1 is passed in EDX,
        my syntax is valid}

    DIV y
end;

and call it with

procedure TfrmMain.Button1Click(Sender: TObject);
var
    x1, x0, y, R: LongWord;
begin
    {calculate $FFFFFFFE00000001 div $FFFFFFFF = $FFFFFFFF

    i.e. 18446744065119617025 div 4294967295 = 4294967295}
    x1 := $FFFFFFFE;
    x0 := $00000001;
    y :=  $FFFFFFFF;

    QuadDivMod(x0, x1, y);

    //answer is $FFFFFFFF
    Assert(x1 = $FFFFFFFF, 'Nope.');
end;

Which, amazingly enough, compiles; but is wrong. Passing x1 and x0 as var
causes
EAX and EDX to contain the pointers to the values. And i don't know the
proper
techniques for asm.

So can someone help me out here?

Replies:

www.cryer.info
Managed Newsgroup Archive