Datentyp extended
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Datentyp extended
Aus einer Appledatei müssen Daten ausgelesen werden, die Datei ist im Motorola 68000 Format also Big Endian.
Alles klappt fehlerfrei mit SwapEndian solange es sich um integer, word, longword usw dreht.
Beim Datentyp Extended aber kommen nur falsche Werte heraus obwohl ich die zehn byte auch "geswappt" habe.
Hat jemand dazu eine Idee ?
Alles klappt fehlerfrei mit SwapEndian solange es sich um integer, word, longword usw dreht.
Beim Datentyp Extended aber kommen nur falsche Werte heraus obwohl ich die zehn byte auch "geswappt" habe.
Hat jemand dazu eine Idee ?
- photor
- Beiträge: 445
- Registriert: Mo 24. Jan 2011, 21:38
- OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
- CPU-Target: 64Bit
Re: Datentyp extended
Hallo,Lincoln Six Echo hat geschrieben: ↑Mi 11. Okt 2023, 20:01Aus einer Appledatei müssen Daten ausgelesen werden, die Datei ist im Motorola 68000 Format also Big Endian.
Alles klappt fehlerfrei mit SwapEndian solange es sich um integer, word, longword usw dreht.
Beim Datentyp Extended aber kommen nur falsche Werte heraus obwohl ich die zehn byte auch "geswappt" habe.
Hat jemand dazu eine Idee ?
ist schon ewig her, dass ich mit Motorola 68000 zu tun hatte (ATARI ST) - daher mit Vorsicht genießen.
Aber bist du sicher, dass die Float-Daten im Extended-Format (10 Byte) gespeicher werden und nicht als "normale" Double (8-Byte)? Ich weiß nicht, ob die 68000 damit ordentlich umgehen konnten. Und das Extended-Format war - soweit ich weiß - ein rein internes Format, das nicht zum Datenaustausch gedacht war.
Vielleicht versuchst du mal mit dem "Double", ob das sinnvollere Zahlen ergibt.
Ciao,
Photor
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Re: Datentyp extended
Es sind tatsächlich 10 byte denn die Werte die ich danach auslese sind wieder korrekt.
Die Dateien stammen übrigens aus dem Jahr 1988.
Hier steht unter "extended" 80 Bit. Das sind ja 10 byte.
https://wiki.freepascal.org/IEEE_754_formats
Die Dateien stammen übrigens aus dem Jahr 1988.
Hier steht unter "extended" 80 Bit. Das sind ja 10 byte.
https://wiki.freepascal.org/IEEE_754_formats
-
- Lazarusforum e. V.
- Beiträge: 191
- Registriert: Sa 26. Mai 2012, 17:31
- OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
- CPU-Target: 64Bit
Re: Datentyp extended
Da du beide Daten hast:
- Rohdaten 10bit und
- Integerwerte(soll),
sollten doch ein paar Beispiele reichen, um das tatsächlich gespeicherte Format herauszubekommen.
z.B.: 0000101011 soll 137 dezimal ergeben
- Rohdaten 10bit und
- Integerwerte(soll),
sollten doch ein paar Beispiele reichen, um das tatsächlich gespeicherte Format herauszubekommen.
z.B.: 0000101011 soll 137 dezimal ergeben
just my two Beer
-
- Lazarusforum e. V.
- Beiträge: 3158
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Datentyp extended
Dort steht auch, dass extended nicht auf allen Plattformen unterstützt wird. Konkret ist das meines Wissens nach nur Intel x86. Wenn du auf einer anderen CPU-Archtitektur unterwegs bist - dazu zählt auch x86_64 - hast du kein 10-Bit Extended.Lincoln Six Echo hat geschrieben: ↑Mi 11. Okt 2023, 20:41Hier steht unter "extended" 80 Bit. Das sind ja 10 byte.
https://wiki.freepascal.org/IEEE_754_formats
Wie Joh schon schreibt stellst du am besten ein paar Beispieldaten und deinen Code zum Umformung bereit. Im besten Fall hast du auch die erwarteten Zahlen im Dezimalformat.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Re: Datentyp extended
Das der Datentyp extended keine 10 byte hat ist klar, vielleicht habe ich es falsch ausgedrückt.
Der Datentyp "Extended" mit 10 byte bezieht sich auf die Notation in der Datei, d.h. in der Datei wird der Wert als 10 byte (80 bit) Float gespeichert, das ganze dann im Motorola 68000 Format.
SFX, CHS, ANC und BSX liefern so korrekte Werte. Nur mit Ext kann ich machen was ich will, es kommen immer nur falsch Werte.
Apple sagt: "extended = 80 bit IEEEE Standard 754 floating point number"
https://de.wikipedia.org/wiki/IEEE_754
Auch beim Schreiben einer solchen Datei ist das Problem wie den Wert in die 10 byte zu bekommen das auch andere Programme die Daten korrekt lesen.
Der Datentyp "Extended" mit 10 byte bezieht sich auf die Notation in der Datei, d.h. in der Datei wird der Wert als 10 byte (80 bit) Float gespeichert, das ganze dann im Motorola 68000 Format.
Code: Alles auswählen
TData = record
SFX : word;
CHS : longword;
Ext : array[0..9] of byte;
ANC : word;
BSX : word;
end;
SFX := SwapEndian(SFX);
CHS := SwapEndian(CHS);
ANC := SwapEndian(ANC);
BSX := SwapEndian(BSX);
Apple sagt: "extended = 80 bit IEEEE Standard 754 floating point number"
https://de.wikipedia.org/wiki/IEEE_754
Auch beim Schreiben einer solchen Datei ist das Problem wie den Wert in die 10 byte zu bekommen das auch andere Programme die Daten korrekt lesen.
-
- Beiträge: 1913
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Datentyp extended
Das Problem mit extended ist, es gibt nicht das Extended Format. Extended bedeutet einfach nur mehr als Double aber weniger als Quadruple (128 bit float). Der Grund ist relativ simpel, als die Spec geschrieben wurde war es technisch einfach nicht wirklich möglich effiziente FPUs für Quadruple Precision Floats zu bauen, die 112 bit Mantissen effizient berechnen können. Daher war dann der Kompromiss, es wir ein spezialtyp "Extended" engeführt, der mindestens Double ist, bei dem die Prozessorhersteller dann das beste bereitstellen können was sie Bauen können.
Intel hat mantissen bis zu 64 bit hinbekommen, also ist auf intel x86 Extended 64 bit Mantisse + 15 bit Exponent + 1 Sign bit = 80 bit.
Das ist aber nur intel x86, die IEE 754 Spec sieht explizit keine Interoperabilität von Extended vor, da diese eigentlich nur eine Übergangslösung sein sollten. Eigentlich war der Plan das Programmierer keine Annahmen über das Speicherlayout treffen sollten, damit dann über die Zeit die Prozessorhersteller immer größere Extended bauen können bis sie irgendwann Quadruples erreicht haben, welche dann wieder Wohlspezifiziert sind.
Jetzt ist aber natürlich das Problem, das wenn Programmierer eins können, dann denken das sie es besser wissen als die Spec, und wenn in der Spec steht das man keine Annahmen treffen soll, sie denken "Ich weis doch auf was für einer CPU das läuft" und dann trozdem Annahmen treffen. Deshalb ist das konzept "Extended" gescheitert, und wird Grundsätzlich auch nicht weiter verfolgt. Das führt dann dazu das Extended ein Relikt von ein paar spezifischen Architekturen ist, die obwohl es alle "Extended" nennen, miteinander nicht kompatibel sein müssen. Um ein Beispiel von WIkipedia zu nennen:
Langer Rede kurzer Sinn, das bedeutet vor allem das es keinen einfachen weg gibt 1. "big endian extended" überhaupt einzulesen, und 2. in ein system natives format zu konvertieren.
Was du also machen musst ist dir das entsprechende Manual von dem CPU typen den du da vor dir hast rauszusuchen, und dort genau nachlesen was die für ein Format verwendet haben für extended. Und schließlich das dann in das Native format deiner CPU umrechnen.
Ein beispiel wie man Intel like 80 bit Extended im Big Endian format Arithmetisch umrechnen kann (nicht getestet):
Intel hat mantissen bis zu 64 bit hinbekommen, also ist auf intel x86 Extended 64 bit Mantisse + 15 bit Exponent + 1 Sign bit = 80 bit.
Das ist aber nur intel x86, die IEE 754 Spec sieht explizit keine Interoperabilität von Extended vor, da diese eigentlich nur eine Übergangslösung sein sollten. Eigentlich war der Plan das Programmierer keine Annahmen über das Speicherlayout treffen sollten, damit dann über die Zeit die Prozessorhersteller immer größere Extended bauen können bis sie irgendwann Quadruples erreicht haben, welche dann wieder Wohlspezifiziert sind.
Jetzt ist aber natürlich das Problem, das wenn Programmierer eins können, dann denken das sie es besser wissen als die Spec, und wenn in der Spec steht das man keine Annahmen treffen soll, sie denken "Ich weis doch auf was für einer CPU das läuft" und dann trozdem Annahmen treffen. Deshalb ist das konzept "Extended" gescheitert, und wird Grundsätzlich auch nicht weiter verfolgt. Das führt dann dazu das Extended ein Relikt von ein paar spezifischen Architekturen ist, die obwohl es alle "Extended" nennen, miteinander nicht kompatibel sein müssen. Um ein Beispiel von WIkipedia zu nennen:
Die haben also einen 80 bit Extended, der aber in 96 bit gespeichert wird, denn wie bereits gesagt, jeder Prozessorhersteller darf hier sein eigenes Bier brauen.The Motorola 6888x math coprocessors and the Motorola 68040 and 68060 processors support this same 64-bit significand extended precision type (similar to the Intel format although padded to a 96-bit format with 16 unused bits inserted between the exponent and significand fields[9]). The follow-on Coldfire processors do not support this 96-bit extended precision format.
Langer Rede kurzer Sinn, das bedeutet vor allem das es keinen einfachen weg gibt 1. "big endian extended" überhaupt einzulesen, und 2. in ein system natives format zu konvertieren.
Was du also machen musst ist dir das entsprechende Manual von dem CPU typen den du da vor dir hast rauszusuchen, und dort genau nachlesen was die für ein Format verwendet haben für extended. Und schließlich das dann in das Native format deiner CPU umrechnen.
Ein beispiel wie man Intel like 80 bit Extended im Big Endian format Arithmetisch umrechnen kann (nicht getestet):
Code: Alles auswählen
TExtRecordBE=record
// 1. bit sign bit 15 rest bits exponent
exp: Word;
// 64 bit mantisse
Mantissa:QWord;
end;
function toExtended(extData:TExtRecordBE):Extended;
var
exp: Integer;
begin
// Exponent nehmen, endianess swappen und sign bit entfernen
exp:=ntohs(extData.exp) And $7FFF;
// Exponent auf negativ range normalisieren
exp:=exp-$3FFF;
// Ergebnis ist mantisse * 2^-63 * 2^exp = m*2^(exp-63)
Result:=ntohll(extData.Mantissa)*pow(2, exp-63);
// Sign drauf multiplizieren
if (ntohs(extData.exp) And $8000) = 1 then
Result *= -1;
end;
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Re: Datentyp extended
Wie und in welchem Format genau diese 10 byte aussehen ist lediglich mit dem Hinweis auf IEEE 754 usw. abgetan.
Das Code-Beispiel funktioniert nicht.
ntohs usw gibt es meines Wissens in Pascal nicht.
Die 10 byte aus der Datei gelesen sehen so aus: (decimal)
64 14 172 68 0 0 0 0 0 0
Ich weiß das es 44100,0 ergeben muß weil alle Programme mir das so anzeigen.
Das Code-Beispiel funktioniert nicht.
ntohs usw gibt es meines Wissens in Pascal nicht.
Die 10 byte aus der Datei gelesen sehen so aus: (decimal)
64 14 172 68 0 0 0 0 0 0
Ich weiß das es 44100,0 ergeben muß weil alle Programme mir das so anzeigen.
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Re: Datentyp extended
Das soll die Lösung sein, ich kann leider zu wenig C um das umzusetzen.
Re: Datentyp extended
Das folgende Programm spuckt dafür etwas sinnvolles aus:
(Muss als 32-bit Anwendung unter Windows laufen, denn dort gibt es den Typ Extended).
Demnach ist die oben genannte Bytefolge (von links nach rechts gelesen) tatsächlich Extended und im Little-Endian Format.
Code: Alles auswählen
program project1;
uses
SysUtils;
procedure SwapBytes(var ex: Extended);
var
arr1: array[0..9] of byte;
arr2: array[0..9] of byte;
i: Integer;
begin
Move(ex, arr1, SizeOf(arr1));
for i := 0 to 9 do
arr2[9-i] := arr1[i];
Move(arr2, ex, sizeOf(arr2));
end;
var
ex: Extended;
ex10: array[0..9] of byte absolute ex;
i: Integer;
begin
ex := 44100.0;
WriteLn('Little Endian');
WriteLn(Format('%.15g', [ex]));
for i := 0 to 9 do
Write(Format('$%.2x ', [ex10[i]]));
WriteLn;
for i := 0 to 9 do
Write(Format('%d ', [ex10[i]]));
WriteLn;
WriteLn();
WriteLn('Big Endian');
SwapBytes(ex);
WriteLn(Format('%.15g', [ex]));
for i := 0 to 9 do
Write(Format('$%.2x ', [ex10[i]]));
WriteLn;
for i := 0 to 9 do
Write(Format('%d ', [ex10[i]]));
WriteLn;
ReadLn;
end.
Demnach ist die oben genannte Bytefolge (von links nach rechts gelesen) tatsächlich Extended und im Little-Endian Format.
Re: Datentyp extended
Also meiner Meinung nach werden die Bytes eines Byte-Arrays auch im Motorola-Format so geschrieben, dass zuerst Index 0 kommt, dann Index 1, usw. Bildest du das Array[0..9] of Byte dann auf einem 10-byte Extended-Wert ab, dann ist dieser im Little-Endian Format (denn der Byte-Stream beginnt mit der niedrigsten Wertigkeit, genauso wie bei einem Little-Endian-Stream), auch wenn der Rest der Datei (SFX, CHS, ANC, BSX) Big-Endian ist.Lincoln Six Echo hat geschrieben: ↑Do 12. Okt 2023, 12:03SFX, CHS, ANC und BSX liefern so korrekte Werte. Nur mit Ext kann ich machen was ich will, es kommen immer nur falsch Werte.Code: Alles auswählen
TData = record SFX : word; CHS : longword; Ext : array[0..9] of byte; ANC : word; BSX : word; end;
Zuletzt geändert von wp_xyz am Do 12. Okt 2023, 15:46, insgesamt 1-mal geändert.
-
- Beiträge: 1913
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Datentyp extended
In der sockets unit müssten sie definiert sein. Aber ich glaube nur htonl und htons existiert, htonll fehlt.Lincoln Six Echo hat geschrieben: ↑Do 12. Okt 2023, 15:09ntohs usw gibt es meines Wissens in Pascal nicht.
Hab packed beim record vergessen, dann gehts:Lincoln Six Echo hat geschrieben: ↑Do 12. Okt 2023, 15:09Die 10 byte aus der Datei gelesen sehen so aus: (decimal)
64 14 172 68 0 0 0 0 0 0
Ich weiß das es 44100,0 ergeben muß weil alle Programme mir das so anzeigen.
Code: Alles auswählen
function ntohll(ll:QWord):QWord;
begin
Result:=0;
PByte(@Result)[0]:=PByte(@ll)[7];
PByte(@Result)[1]:=PByte(@ll)[6];
PByte(@Result)[2]:=PByte(@ll)[5];
PByte(@Result)[3]:=PByte(@ll)[4];
PByte(@Result)[4]:=PByte(@ll)[3];
PByte(@Result)[5]:=PByte(@ll)[2];
PByte(@Result)[6]:=PByte(@ll)[1];
PByte(@Result)[7]:=PByte(@ll)[0];
end;
type
TExtRecordBE=packed record
// 1. bit sign bit 15 rest bits exponent
exp: Word;
// 64 bit mantisse
Mantissa:QWord;
end;
function toExtended(extData:TExtRecordBE):Extended;
var
exp: Integer;
begin
// Exponent nehmen, endianess swappen und sign bit entfernen
exp:=ntohs(extData.exp) And $7FFF;
// Exponent auf negativ range normalisieren
exp:=exp-$3FFF;
// Ergebnis ist mantisse * 2^-63 * 2^exp = m*2^(exp-63)
Result:=Extended(ntohll(extData.Mantissa))*Power(2, exp-63);
// Sign drauf multiplizieren
if (ntohs(extData.exp) And $8000) = 1 then
Result *= -1;
end;
- Lincoln Six Echo
- Beiträge: 138
- Registriert: Di 26. Aug 2014, 16:42
- OS, Lazarus, FPC: Win10, Debian
- CPU-Target: I7/I9/Q9650/u.a.
- Wohnort: Hamburg
Re: Datentyp extended
Es ergibt aber etwas anderes als die in der Datei enthaltenen 64 14 172 68 0 0 0 0 0 0:
Code: Alles auswählen
Little Endian
44100
$00
$00
$00
$00
$80
$88
$E5
$40
$00
$00
0
0
0
0
128
136
229
64
0
0
Big Endian
6,98240497697302E-310
$00
$00
$40
$E5
$88
$80
$00
$00
$00
$00
0
0
64
229
136
128
0
0
0
0
-
- Beiträge: 6209
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Datentyp extended
Da habe ich jetzt nicht schlecht gestaunt, dies wird tatsächlich kompiliert.
Vor allem links vom := sieht echt merkwürdig aus.
Ich hätte sowas mit mit and, or, not, shl, etc. gelöst.
Das sowas geht hätte ich nie gedacht.
Vor allem links vom := sieht echt merkwürdig aus.
Code: Alles auswählen
function ntohll(ll:QWord):QWord;
begin
Result:=0;
PByte(@Result)[0]:=PByte(@ll)[7];
PByte(@Result)[1]:=PByte(@ll)[6];
PByte(@Result)[2]:=PByte(@ll)[5];
PByte(@Result)[3]:=PByte(@ll)[4];
PByte(@Result)[4]:=PByte(@ll)[3];
PByte(@Result)[5]:=PByte(@ll)[2];
PByte(@Result)[6]:=PByte(@ll)[1];
PByte(@Result)[7]:=PByte(@ll)[0];
end;
Das sowas geht hätte ich nie gedacht.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1913
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Datentyp extended
Was meinst du damit? Hier ist mein testprogramm:Lincoln Six Echo hat geschrieben: ↑Do 12. Okt 2023, 15:57Es ergibt aber etwas anderes als die in der Datei enthaltenen 64 14 172 68 0 0 0 0 0 0:
Code: Alles auswählen
program Project1;
{$mode objfpc}{$H+}
uses
sockets,math;
function ntohll(ll:QWord):QWord;
begin
{$IFDEF ENDIAN_LITTLE}
Result:=0;
PByte(@Result)[0]:=PByte(@ll)[7];
PByte(@Result)[1]:=PByte(@ll)[6];
PByte(@Result)[2]:=PByte(@ll)[5];
PByte(@Result)[3]:=PByte(@ll)[4];
PByte(@Result)[4]:=PByte(@ll)[3];
PByte(@Result)[5]:=PByte(@ll)[2];
PByte(@Result)[6]:=PByte(@ll)[1];
PByte(@Result)[7]:=PByte(@ll)[0];
{$Else}
Result:=ll;
{$Endif}
end;
type
PExtRecordBE=^TExtRecordBE;
TExtRecordBE=packed record
// 1. bit sign bit 15 rest bits exponent
exp: Word;
// 64 bit mantisse
Mantissa:QWord;
end;
function toExtended(extData:TExtRecordBE):Extended;
var
exp: Integer;
begin
// Exponent nehmen, endianess swappen und sign bit entfernen
exp:=ntohs(extData.exp) And $7FFF;
// Exponent auf negativ range normalisieren
exp:=exp-$3FFF;
// Ergebnis ist mantisse * 2^-63 * 2^exp = m*2^(exp-63)
Result:=Extended(ntohll(extData.Mantissa))*Power(2, exp-63);
// Sign drauf multiplizieren
if (ntohs(extData.exp) And $8000) = 1 then
Result *= -1;
end;
var
ExtData: Array[0..9] of Byte = (64, 14, 172, 68, 0, 0, 0, 0, 0, 0);
begin
WriteLn(toExtended(PExtRecordBE(@ExtData)^)); // 4.4100000000000000E+004
ReadLn;
end.
Ist getestet auf x86_64 Windows (little endian) wo Extended = Double ist (also findet hier tatsächlich auch ein Informationsverlust von 16 bit statt, da x86_64 windows kein 80 bit Extended mehr unterstützt). Sollte aber durch die nutzung von ntohs und ntohll aber theoretisch auf jedem System laufen mit jeder art von Extended typen