Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2017-12

TFloatHelper.BuildUp() question

4 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

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

Reply by email

Vojtěch Čihák

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.
______________________________________________________________

Show quoted text 5 lines
Od: Bart Komu: FPC-Pascal users discussions Datum: 15.12.2017 13:36 Předmět: [fpc-pascal] TFloatHelper.BuildUp() question

What am I doing wrong here?

Bart

Reply by email

Bart
to Vojtěch Čihák
Vojtěch Čihák wrote 9 lines
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

Reply by email

Bart
to Bart: I think I misunderstand what this procedure is for? Procedure BuildUp(const ASignFlag:…
Bart 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

Reply by email