Autor Beitrag
Spaceguide
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: 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;

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: Sa 20.08.05 19:37 
Ja das Teil funktioniert schon, zumindest bei positiven Zahlen.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 21.08.05 10:44 
Ihr meint sowas hier?

ausblenden 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   //0001 [11]11 0111 0010   //Round control to truncate fraction

    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:

ausblenden 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   //0001 [11]11 0111 0010   //Round control to truncate fraction

    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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 552


(D3/D7/D8) Prof.
BeitragVerfasst: So 21.08.05 17:13 
Gibt's das auch für Double-Precision? Mit Extended ist es langsamer als meine Routine.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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.