TFloatHelper.BuildUp() question

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

TFloatHelper.BuildUp() question

Bart-48
Hi,

I think I misunderstand what this procedure is for?

Procedure BuildUp(const ASignFlag: Boolean; const AMantissa: QWord;
const AExponent: Integer);

From it's signature I would expect that it constructs a float from the
supplied parameters.
I also assumed that this would be reciprocal: if I query Sign,
Mantissa and Exponent from a given float, then uses BuildUp with these
parameters, I would get a float with the original value back:

This however seems not to be the case.

======================
program fl;
{$mode objfpc}
{$h+}

uses
  SysUtils;

const
  Signs: Array[Boolean] of Char = ('+','-');

  function DbgS(E: Extended): String; overload;
  begin
    Result := 'Sign: ' + Signs[E.Sign] +
              ' Mantissa: ' + IntToHex(E.Mantissa, SizeOf(E.Mantissa)*2) +
              ' Exp: ' + IntToHex(E.Exp, SizeOf(E.Exp)*2) +
              ' Frac: ' + IntToHex(E.Frac, SizeOf(E.Frac)*2);
  end;

function DbgS(D: Double): String; overload;
begin
  Result := 'Sign: ' + Signs[D.Sign] +
            ' Mantissa: ' + IntToHex(D.Mantissa, SizeOf(D.Mantissa)*2) +
            ' Exp: ' + IntToHex(D.Exp, SizeOf(D.Exp)*2) +
            ' Frac: ' + IntToHex(D.Frac, SizeOf(D.Frac)*2);
end;

function DbgS(S: Single): String; overload;
begin
  Result := 'Sign: ' + Signs[S.Sign] +
            ' Mantissa: ' + IntToHex(S.Mantissa, SizeOf(S.Mantissa)*2) +
            ' Exp: ' + IntToHex(S.Exp, SizeOf(S.Exp)*2) +
            ' Frac: ' + IntToHex(S.Frac, SizeOf(S.Frac)*2);
end;


var
  E: Extended;
  ESign, SSign, DSign: Boolean;
  EMant, EExp, EFrac, SMant, SExp, SFrac, DMant, DExp, DFrac: QWord;
  S: Single;
  D: Double;
begin
  writeln('Extended (',SizeOf(Extended),' bytes)');
  E := 1.0;
  writeln('E = ',E,#32,DbgS(E));
  ESign := E.Sign;
  EMant := E.Mantissa;
  EExp := E.Exp;
  EFrac := E.Frac;
  E.BuildUp(ESign, EMant, EExp);
  writeln('E = ',E,#32,DbgS(E));
  writeln;

  writeln('Double (',SizeOf(Double),' bytes)');
  D := 1.0;
  writeln('D = ',D,#32,DbgS(D));
  DSign := D.Sign;
  DMant := D.Mantissa;
  DExp := D.Exp;
  DFrac := D.Frac;
  D.BuildUp(DSign, DMant, DExp);
  writeln('D = ',E,#32,DbgS(D));
  writeln;

  writeln('Single (',SizeOf(Single),' bytes)');
  S := 1.0;
  writeln('S = ',S,#32,DbgS(S));
  SSign := S.Sign;
  SMant := S.Mantissa;
  SExp := S.Exp;
  SFrac := S.Frac;
  S.BuildUp(SSign, SMant, SExp);
  writeln('S = ',S,#32,DbgS(S));
  writeln;


end.
===========================

Output (tested with 3.0.4 and trunk):

Extended (10 bytes)
E =  1.00000000000000000000E+0000 Sign: + Mantissa: 0000000000000000
Exp: 0000000000003FFF Frac: 8000000000000000
E = Nan Sign: + Mantissa: 0000000000000000 Exp: 00000000000043FE Frac:
0000000000000000

Double (8 bytes)
D =  1.0000000000000000E+000 Sign: + Mantissa: 0000000000000000 Exp:
00000000000003FF Frac: 0010000000000000
D = Nan Sign: + Mantissa: 0000000000000000 Exp: 00000000000007FE Frac:
0010000000000000

Single (4 bytes)
S =  1.000000000E+00 Sign: + Mantissa: 0000000000000000 Exp:
000000000000007F Frac: 0000000008000000
S =  5.000000000E-01 Sign: + Mantissa: 0000000000000000 Exp:
000000000000007E Frac: 0000000008000000

What am I doing wrong here?

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TFloatHelper.BuildUp() question

vojtech.cihak

Hi,

 

it seems there is something wrong with helpers or Lazarus is fooled from directives.

 

When I find procedure TExtendedHelper.BuidUp() in syshelph.inc and hit Ctrl+Shift+Up, it takes me to TFLOATHELPER.BuildUp() implementation in syshelpf.inc.

And when I hit Alt+Up, it takes me back to declaration in syshelph.inc, but to TSingleHelper!

 

I tested 3.0.4 only.

 

V.

______________________________________________________________
> Od: Bart <[hidden email]>
> Komu: FPC-Pascal users discussions <[hidden email]>
> Datum: 15.12.2017 13:36
> Předmět: [fpc-pascal] TFloatHelper.BuildUp() question
>


What am I doing wrong here?

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TFloatHelper.BuildUp() question

Bart-48
On Fri, Dec 15, 2017 at 2:51 PM, Vojtěch Čihák <[hidden email]> wrote:

> it seems there is something wrong with helpers or Lazarus is fooled from
> directives.
>
> When I find procedure TExtendedHelper.BuidUp() in syshelph.inc and hit
> Ctrl+Shift+Up, it takes me to TFLOATHELPER.BuildUp() implementation in
> syshelpf.inc.
>
> And when I hit Alt+Up, it takes me back to declaration in syshelph.inc, but
> to TSingleHelper!


Yep, it does not like the clever implementation (defining types and
then using the same code by including the same includefile multiple
times).

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TFloatHelper.BuildUp() question

Bart-48
In reply to this post by Bart-48
On Fri, Dec 15, 2017 at 1:36 PM, Bart <[hidden email]> wrote:

> Procedure BuildUp(const ASignFlag: Boolean; const AMantissa: QWord;
> const AExponent: Integer);


Basically the current implementation does this:

    Self :=  0.0;
    TExtended80Rec(Self)._Exp:=(TExtended80Rec(Self)._Exp and $7FFF)
or (ord(AsignFlag) shl 15); //which is what TExtended80Rec(Self).Sign
:= ASignFlag does
    TExtended80Rec(Self).Frac := AMantissa and $000FFFFFFFFFFFFF;
    TExtended80Rec(Self)._Exp:=(TExtended80Rec(Self)._Exp and $8000)
or ((AExponent+$3FF) and $7FFF);   //where does the +$3FF come from?

Possibly this should be:

   Self :=  0.0;
   TExtended80Rec(Self)._Exp:=(TExtended80Rec(Self)._Exp and $7FFF) or
(ord(AsignFlag) shl 15);
   TExtended80Rec(Result).Frac := AMantissa or $8000000000000000;
   TExtended80Rec(Result)._Exp := (Textended80Rec(Result)._Exp and
$8000) or (AExp and $7FFFF);

I'm not very good with bit manipulation, so I may be way off here.

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal