Floating point 多平台支持扩展类型的二进制数据文件

Floating point 多平台支持扩展类型的二进制数据文件,floating-point,delphi-10.2-tokyo,Floating Point,Delphi 10.2 Tokyo,我目前有以下代码来支持从Win32保存在二进制文件中的10字节扩展值,并在其他平台上加载这些扩展值。但是,对于Android(它是ARM,而不是INTEL),我需要一些代码在10字节内存中与10字节IEEE格式和编译器中的“扩展”类型(实际上是8字节双精度)进行转换 如果可能,我还希望能够从MacOS/Linux转换为16字节的“扩展”类型(除非16字节大小“只是”一个对齐方式,即10字节填充为16字节)。在David的帮助下,我在上面的评论中提出了这一点,并在这里提供它以供将来参考: TYPE

我目前有以下代码来支持从Win32保存在二进制文件中的10字节扩展值,并在其他平台上加载这些扩展值。但是,对于Android(它是ARM,而不是INTEL),我需要一些代码在10字节内存中与10字节IEEE格式和编译器中的“扩展”类型(实际上是8字节双精度)进行转换


如果可能,我还希望能够从MacOS/Linux转换为16字节的“扩展”类型(除非16字节大小“只是”一个对齐方式,即10字节填充为16字节)。

在David的帮助下,我在上面的评论中提出了这一点,并在这里提供它以供将来参考:

TYPE
  TExtended     = TExtended80Rec;
  PExtended     = ^TExtended;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
PROCEDURE ExtendedToIntel(VAR D : Extended ; VAR E : TExtended); INLINE;
  BEGIN
    D:=Extended(E)
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended); INLINE;
  BEGIN
    E:=TExtended(D)
  END;
{$ELSEIF DEFINED(WIN64) }
PROCEDURE ExtendedToIntel(VAR D : Extended {Double} ; VAR E : TExtended); ASSEMBLER;
  ASM
                FLD     QWORD PTR [RCX]
                FSTP    TBYTE PTR [RDX]
                FWAIT
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended {Double} ); ASSEMBLER;
  ASM
                FLD     TBYTE PTR [RCX]
                FSTP    QWORD PTR [RDX]
                FWAIT
  END;
{$ELSE }
PROCEDURE ExtendedToIntel(D : Extended ; VAR E : TExtended);
  BEGIN
    PExtended(@E)^:=TExtended(D)
  END;

PROCEDURE IntelToExtended(CONST E : TExtended ; VAR D : Extended);
  BEGIN
    D:=Double(PExtended(@E)^)
  END;
{$ENDIF }

TYPE
  TStreamHelper = CLASS HELPER FOR TStream
                    FUNCTION ReadExtended : Extended;
                    PROCEDURE WriteExtended(E : Extended);
                  END;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
FUNCTION TStreamHelper.ReadExtended : Extended;
  BEGIN
    Read(Result,SizeOf(Extended))
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  BEGIN
    Write(E,SizeOf(Extended))
  END;
{$ELSE }
FUNCTION TStreamHelper.ReadExtended : Extended;
  VAR
    EX  : TExtended;

  BEGIN
    Read(EX,SizeOf(TExtended));
    IntelToExtended(EX,Result)
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  VAR
    EX  : TExtended;

  BEGIN
    ExtendedToIntel(E,EX);
    Write(EX,SizeOf(EX))
  END;
{$ENDIF }

如果您指的是使用80位的英特尔“双扩展精度”浮点格式,那是一种英特尔格式,而不是IEEE格式。@EricPostChil:我是-我不知道它不是IEEE格式。我将重命名代码中的函数。但问题依然存在:-)
SysUtils
中的
TExtendedHelper
包含您需要的所有逻辑。基本上,从80位值中提取符号、尾数和指数的逻辑,然后将这些值反馈给
Double.building
@DavidHeffernan:但是textendeHelper在非扩展目标中不处理8字节的Double吗?我没有说直接使用它。我说把逻辑从中拉出来。else分支中的ExtendedToIntel似乎没有任何用处。我也怀疑在win64中使用x87单元。你不知道它将处于什么状态。@DavidHeffernan:ELSE分支是整个“魔法”。它使用Embarcadero已有的隐式/显式运算符重载,在10字节到8字节的双字节格式之间来回转换。所有其他分支只是为了兼容性(以及x64的速度)。
$ELSE
分支中的函数
ExtendedToIntel
接受一个名为
D
的参数,该参数从未使用过。至于x64的速度,您如何知道x87单元处于什么状态?是否已草签?CW的价值是多少?我想CW的价值是42美元。如果不是,你就靠你自己了。。。DE是一个拼写错误,已经纠正了。谢谢你的关注…为什么你认为它会有那个价值?在Win64上,Delphi RTL不会维护x87控制字。为什么会这样?
TYPE
  TExtended     = TExtended80Rec;
  PExtended     = ^TExtended;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
PROCEDURE ExtendedToIntel(VAR D : Extended ; VAR E : TExtended); INLINE;
  BEGIN
    D:=Extended(E)
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended); INLINE;
  BEGIN
    E:=TExtended(D)
  END;
{$ELSEIF DEFINED(WIN64) }
PROCEDURE ExtendedToIntel(VAR D : Extended {Double} ; VAR E : TExtended); ASSEMBLER;
  ASM
                FLD     QWORD PTR [RCX]
                FSTP    TBYTE PTR [RDX]
                FWAIT
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended {Double} ); ASSEMBLER;
  ASM
                FLD     TBYTE PTR [RCX]
                FSTP    QWORD PTR [RDX]
                FWAIT
  END;
{$ELSE }
PROCEDURE ExtendedToIntel(D : Extended ; VAR E : TExtended);
  BEGIN
    PExtended(@E)^:=TExtended(D)
  END;

PROCEDURE IntelToExtended(CONST E : TExtended ; VAR D : Extended);
  BEGIN
    D:=Double(PExtended(@E)^)
  END;
{$ENDIF }

TYPE
  TStreamHelper = CLASS HELPER FOR TStream
                    FUNCTION ReadExtended : Extended;
                    PROCEDURE WriteExtended(E : Extended);
                  END;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
FUNCTION TStreamHelper.ReadExtended : Extended;
  BEGIN
    Read(Result,SizeOf(Extended))
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  BEGIN
    Write(E,SizeOf(Extended))
  END;
{$ELSE }
FUNCTION TStreamHelper.ReadExtended : Extended;
  VAR
    EX  : TExtended;

  BEGIN
    Read(EX,SizeOf(TExtended));
    IntelToExtended(EX,Result)
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  VAR
    EX  : TExtended;

  BEGIN
    ExtendedToIntel(E,EX);
    Write(EX,SizeOf(EX))
  END;
{$ENDIF }