Entwickler-Ecke
Algorithmen, Optimierung und Assembler - Optimierung: Zerlegung von Fliesskommazahl in int und real
Spaceguide - Fr 19.08.05 13:50
Titel: Optimierung: Zerlegung von Fliesskommazahl in int und real
Gerade bei Grafikprogrammierung braucht man oft eine Funktion, die eine Fliesskommazahl in einen Integer-Wert und den Wert "hinter dem Komma" zerlegt. Um Funktionsaufrufe gering zu halten, habe ich folgendes zusammengepfuscht:
const value_shifter : double = -0.5;
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure FracTruncXYZ(const x,y,z : double; var ix,iy,iz: integer; var fx,fy,fz: double); var i: integer; begin asm fld x fadd value_shifter fistp i end;
ix := i; fx := x - i;
asm fld y fadd value_shifter fistp i end;
iy := i; fy := y - i;
asm fld z fadd value_shifter fistp i end;
iz := i; fz := z - i; end; |
Da kann man doch bestimmt noch einiges rausholen, oder?
Allesquarks - Fr 19.08.05 17:38
Da Du Value Shifter dreimal verwendest würde ich ihn für besser auf dem FPU-Stack halten. Da Du ja sonst drei Speicherzugriffe brauchst.
fx = x - i = x - (x + valueshifter) = -valueshifter = 0,5 ??????? Und das dreimal!! Vielleicht hab ich aber auch was übersehen!
P.S. Bekommst Du Überhaupt die Ergebnisse, die Du haben willst?
Spaceguide - Sa 20.08.05 19:37
Ja das Teil funktioniert schon, zumindest bei positiven Zahlen.
BenBE - So 21.08.05 10:44
Ihr meint sowas hier?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| type TFloatValue = packed record Int: Extended; Float: Extended; end;
Function SplitInt(Var X: Extended): TFloatValue; asm FLD TBYTE PTR [X]
PUSH $1F72 FLD ST(0) FNSTCW WORD PTR [ESP+2] FLDCW WORD PTR [ESP] FRNDINT FLDCW WORD PTR [ESP+2] POP ECX
FLD ST(0) FSTP TBYTE PTR [Result.TFloatValue.Int] FSUBP FSTP TBYTE PTR [Result.TFloatValue.Float] end; |
Für den speziellen Fall auch:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| type TFloatValue = packed record Int: Integer; Float: Extended; end;
Function SplitInt(Var X: Extended): TFloatValue; asm FLD TBYTE PTR [X]
PUSH $1F72 FLD ST(0) FNSTCW WORD PTR [ESP+2] FLDCW WORD PTR [ESP] FRNDINT
FIST DWORD PTR [Result.TFloatValue.Int] FSUBP FSTP TBYTE PTR [Result.TFloatValue.Float]
FLDCW WORD PTR [ESP+2] POP ECX end; |
Erstere Variante ist getestet und funzt. Auch für negative Zahlen. Jedoch wird der Nachkommateil bei Negativen Zahlen auch negativ angegeben. Um dies zu beheben, braucht man einfach hinter dem
FSUBP ein
FABS zu ergänzen oder Bits 6 & 7 des ersten Bytes in Float auf 0 zu setzen. Da man aber eh auf die FPU warten muss, ist erstere Möglichkeit IMHO schneller.
Spaceguide - So 21.08.05 17:13
Gibt's das auch für Double-Precision? Mit Extended ist es langsamer als meine Routine.
BenBE - So 21.08.05 21:48
Jup. Müsste ich mir nochmal angucken, geht aber sicherlich.
Meine Routinen vermeiden Integer-Überläufe, da der Integer in der FPU gehalten wird.
Da Du das aber für Batch-Verarbeitung zu nutzen scheinst, wäre sicherlich die Verwendung von SIMD (z.B. SSE oder SSE2) eine Idee. Allerdings geht bei SSE nur Single-Precision zu verwenden, bei SSE2 zwar auch Dbl, aber nur halbe Datenmenge. Da ich aber mit beidem noch nicht gearbeitet hab, müsste ich das anderen überlassen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!