FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Gleiche Funktion in 32Bit und 64Bit
Delphi-Quellcode:
Dies Funktion Arbeitet unter 32Bit so wie sie soll.
procedure TBassPlayer.XFFT(FR, FI: array of single; Sign, Sample, SampleCount: Integer);
// Wave Daten glätten var Q, J, M, L, le, le1, ip: integer; tr, ti, s, ur, ur1, ui, wr, wi: single; begin J := 1; for Q := Sample to SampleCount do begin if Q < J then begin s := FR[Q]; FR[Q] := FR[J]; FR[J] := s; s := FI[Q]; FI[Q] := FI[J]; FI[J] := s; end; M := ((SampleCount + 1) div 2); while M < J do begin J := J - M; M := M div 2; end; J := J + M; end; for L := 1 to 8 do begin le := trunc(Power(2, L)); le1 := le div 2; ur := 1; ui := 0; wr := Cos(PI / le1); wi := Sign * Sin(PI / le1); for J := 1 to le1 do begin Q := J; while Q <= (SampleCount + 1) do begin ip := Q + (le1 - 1); tr := FR[ip] * ur - FI[ip] * ui; // FLOAT_INVALID_OPERATION nur 64Bit ti := FR[ip] * ui + FI[ip] * ur; FR[ip] := FR[Q] - tr; FI[ip] := FI[Q] - ti; // FLOAT_OVERFLOW nur 64Bit FR[Q] := FR[Q] + tr; FI[Q] := FI[Q] + ti; Q := Q + le; end; ur1 := ur * wr - ui * wi; ui := ur * wi + ui * wr; ur := ur1; end; end; for Q := Sample to (SampleCount + 1) do begin FR[Q] := FR[Q] * DivN; FI[Q] := FI[Q] * DivN; end; end; In 64Bit muß ich beide Fehler ignorieren. Dort bekomme ich diese beiden Fehler! FLOAT_INVALID_OPERATION, FLOAT_OVERFLOW Wieder irgend so ein Ding mit Daten Typen? |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Den Einzigen Typ-Unterschied gibt es beim Extended, welchen man eigentlich eh hätte nie direkt verwenden sollen.
Extended gibt es unter 64 Bit nicht, das ist dort bloß noch ein Alias für Double. Aber eventuell sieht die Exception-Maske unterschiedlich aus? FGetExceptMask FSetExceptMask [EDIT] besser Folgenes verwenden GetExceptionMask SetExceptionMask (welches unter 64 Bit auf GetSSEExceptionMask umgeleitet wird) [/EDIT] Zitat:
Single ist und bleibt auch unter 64 Bit Single und Integer war mal als platformabhängiger Typ definiert (unter 16 Bit war er noch 16 Bit), aber für/vor 64 Bit wurde er auf 32 Bit eingefroren (von den CPU-Entwicklern und alle Softwaretools machten mit) und stattdessen ein neuer Typ erfunden (nennt sich in Delphi NativeInt), also Integer (LongInt) bleibt auch unverändert. [EDIT] Unter 64 Bit dürften die Floats über SSE behandelt werden (GetMXCSR), wärend es unter 32 Bit noch die FPU machte (Get8087CW). |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Zitat:
Zitat:
Wie gesagt 32Bit macht keinen Ärger. Im Moment habe ich nur die Möglichkeit diese Exzeption von der Anwendung auswerten zu lassen anstelle vom Debugger. Denke das ist legitim sonst würde man diese Möglichkeit nicht anbieten oder? Das ist doch kein Rumpfuschen. |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Zitat:
* oder es gibt Überläufe, aber es werden keine Exceptions ausgelöst Das muß erstmal eklärt werden. (darum eben mal schnell nachsehn, ob sich die Masken unterscheiden .... ich hab auch schon Fremdkompnenten gesehn, welche grob fahrlässig heimlich dauerhaft die Fehlermasken verändern) Rein rechnerisch sollte FPU und SSE die gleichen Ergebnisse liefern, also dürfte es da eigentlich keinen (großen) Unterschied geben. https://xem.github.io/minix86/manual...5b67a-276.html "Damals" war die Floating Point Unit "8087" ein eigener Chip, neben der Central Processing Unit "8086" ... schon länger ist der Teil in die CPU integriert, ähnlich wie inzwischen oftmals auch GPU und andere "Chips". Und nun hatte man sich halt gedacht diesen "alten" Teil mal zu ensorgen. Zitat:
* ist es vorgesehn, daß mit Überläufen "gerechnet" wird (z.B. bei Verschlüssels-Algorithmen oft gern ausgenutzt) * sollte es eigentlich garkeine Überläufe geben, dann wäre es doch bissl blöd nur die "Fehlermeldung" abzuschalten, anstatt den eigentlichen Fehler zu beheben |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Zitat:
Aber es gibt keines. Habe das hier mal getestet bringt aber keine Änderung
Delphi-Quellcode:
type
TFPControlState = record _8087CW: Word; MXCSR: UInt32; end; function GetFPControlState: TFPControlState; begin Result._8087CW := Get8087CW; Result.MXCSR := GetMXCSR; end; procedure RestoreFPControlState(const State: TFPControlState); begin Set8087CW(State._8087CW); SetMXCSR(State.MXCSR); end; var FPControlState: TFPControlState; .... FPControlState := GetFPControlState; try // call into external library that changes FP control state finally RestoreFPControlState(FPControlState); end; Zitat:
Muß halt mal schauen wie ich das lösen kann. |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Es geht nur Fehlerfrei mit Extended unter 64Bit
Auch wenn du sagst Zitat:
|
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
@venice2:
Ohne mich wirklich intensiv damit befasst zu haben:
Delphi-Quellcode:
sollte m.E. heißen
while Q <= (SampleCount + 1) do
Delphi-Quellcode:
.
while Q < SampleCount
Du greifst mit FR[Q] und FI[Q] auf die Arrays FR und FI zu. Die Arrays sind als Array of Single deklariert und ich vermute, sie enthalten SampleCount Einträge, also die Indizes 0..SampleCount-1. Wenn Q der Wert SampleCount erreicht, wird der Zugriff FR[Q] und FI[Q] je nach Compiler-Einstellung entweder eine Exception auslösen oder aber irgendwelche Daten liefern, die nicht aus den Arrays stammen. Weiß nicht, ab das das Problem ist. |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Es setzt sich so zusammen.
In Create erstelle ich einen Temporären DC
Delphi-Quellcode:
TempBufferDC := gSprVizC.GI_Create32bitDC(255, 60, $00000000);
Delphi-Quellcode:
procedure TBassPlayer.DrawData;
var k: integer; TRA: array[1..512] of single; TIA: array[1..512] of single; begin // Fülle das Array mit den Wave Daten for k := 0 to 511 do TRA[k + 1] := WaveData[k] / 1.50; XFFT(TRA, TIA, -1, 1, 512); // Wave Daten glätten for k := 1 to 512 do // PicFlame auf den TempBufferDC Blitten begin if TRA[k] < 0 then TRA[k] := 0; BitBlt(TempBufferDC, k - 1, trunc(Abs(FHeight - TRA[k])), 1, FHeight, PicFlame[FCurentFlame].Canvas.Handle, 0, 0, SRCCOPY); end; FadeBackBuffer(TempBufferDC); // Inhalt vom TempBufferDC Faden BitBlt(PaintDC, 0, 0, FWidth, FHeight, TempBufferDC, 0, 0, SRCCOPY);
Delphi-Quellcode:
procedure TBassPlayer.XFFT(FR, FI: array of single; Sign, Sample, SampleCount: Integer);
Zitat:
Delphi-Quellcode:
for Q := Sample to (SampleCount) do
Zitat:
Wenn es jemand testen möchte schicke ich ihm gern den Quelltext zu. |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
Bei mir läuft der bei deinen Angaben schon direkt in eine Endlosschleife, weil M irgendwann 0 ist:
Delphi-Quellcode:
Da in der zweiten Schleife le1 immer größer wird
M := ((SampleCount + 1) div 2);
while M < J do begin J := J - M; M := M div 2; end; J := J + M;
Delphi-Quellcode:
und dann irgendwann
le := trunc(Power(2, L));
le1 := le div 2;
Delphi-Quellcode:
ip := Q + (le1 - 1);
// mit while Q <= (SampleCount + 1) do auf außerhalb des arrays Zugegriffen wird
Delphi-Quellcode:
kann nur murks bei rumkommen. Das wird auch unter 32Bit keine korrekten Ergebnisse liefern, sondern nur zufällig laufen, je nachdem was gerade auf dem Heap ist.tr := FR[ip] * ur - FI[ip] * ui; // FLOAT_INVALID_OPERATION nur 64Bit ti := FR[ip] * ui + FI[ip] * ur; Bau mal ein:
Delphi-Quellcode:
ein
ip := Q + (le1 - 1);
if ip > High(fi) then raise Exception.Create('Fehler'); if ip > High(FR) then raise Exception.Create('Fehler'); tr := FR[ip] * ur - FI[ip] * ui; // FLOAT_INVALID_OPERATION nur 64Bit ti := FR[ip] * ui + FI[ip] * ur; |
AW: FLOAT_INVALID_OPERATION und FLOAT_OVERFLOW nur 64Bit
@venice2:
Ich glaube da machst du einen Denkfehler. In "TBassPlayer.DrawData" sind TRA und TIA zwar als Array[1..512] of Single, also statische Arrays deklariert. Aber an
Delphi-Quellcode:
.
procedure TBassPlayer.XFFT(FR, FI: array of single; Sign, Sample, SampleCount: Integer);
werden die TRA und TIA als dynamische Arrays übergeben und haben dort die Indizes 0..511, SampleCount jedoch hat den Wert 512. Wenn du in "TBassPlayer.XFFT" das
Delphi-Quellcode:
abarbeitest kommt es 2 mal zu Bereichsüberschreitungen.
while Q <= (SampleCount + 1) do
Das erste mal wenn Q = 512 ist. Das zweite mal wenn Q = 513 ist, denn die while Schleife arbeitet ja nicht nur bis SampleCount sondern sogar bis SampleCount+1. In beiden Fällen wird nicht auf Inhalte der Arrays zugegriffen, sondern auf irgendwelche Daten, die zufälligerweise an den Adressen stehen, auf die zugegriffen wird Die Fehlermeldung FLOAT_INVALID_OPERATION deutet darauf hin, dass mit einer ungültigen Fließkommazahl, z.B. einer NaN irgendetwas gerechnet wird. Die Fehlermeldung FLOAT_OVERFLOW sagt, dass das Rechenergebnis außerhalb des für Singles gültigen Bereiches ist. Richtig wäre also, wie bereits in #7 gesagt:
Delphi-Quellcode:
.
while Q < SampleCount
Zitat:
Dann hättest du unter 32 Bit zwar fehlerhafte Ergebnisse aber keine Exeptions, unter 64 Bit dagegen würden dann Exceptions ausgelöst. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz