Autor |
Beitrag |
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Fr 19.08.05 13:50
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
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: 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 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Sa 20.08.05 19:37
Ja das Teil funktioniert schon, zumindest bei positiven Zahlen.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: 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.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Spaceguide 
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.08.05 17:13
Gibt's das auch für Double-Precision? Mit Extended ist es langsamer als meine Routine.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: 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.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|