fpc/tests/webtbs/tw7161.pp
Jonas Maebe e95bd67f6c + added
git-svn-id: trunk@4241 -
2006-07-17 14:05:45 +00:00

166 lines
3.3 KiB
ObjectPascal

{ %opt=-Cfsse2 -O-2 }
{ %cpu=i386 }
(*
Testprogram to show sse2/sse3 bug
- works with fpu -O{1,2,3}
- works with -CfSSE{2,3} -O1
- access violation with -CfSSE{2,3} -O{2,3}
NOTE: It also works with -CfSSE3 -O3 if I
declare DMLogicToCube as global var!
Expected Output:
0.2500 -> -115.4701
0.1000 -> -247.4874
0.0500 -> -20.4124
20.0000 -> -135.5047
45.0000 -> 23.8797
*)
program ssetest;
{$mode objfpc}{$H+}
uses
Classes, SysUtils
{ add your units here }
,math, mmx;
type kfloat = double;
TPosArr = array[0..4] of kfloat;
VektorArr = Array[0..2] of kfloat;
Drehmatrix = Array[0..2] of VektorArr;
type
TCube = class
private
DMLogicToCube : Drehmatrix;
public
Procedure InitDrehmatrizen;
function LogicToCube(const apo: TPosArr) : TPosArr;
end;
Function aTanG(const x,y : kfloat) : kfloat;
Var
b : kfloat;
begin
b:=x*x+y*y;
if isZero(b) then result:=0
else begin
if IsZero(x) then
begin
if y >= 0 then result:=90 else result:=-90;
end
else begin
if IsZero(y) then result:=0
else begin;
b:=ln(abs(y))-ln(abs(x));
if (b > 230) then result:=90 else result:=180/pi*arctan(y/x);
end;
end;
if (x < 0) then result:=result+180;
if (result > 180) then result:=result-360;
end;
end;
Function SinD(const w : kfloat) : kfloat;
begin
result:=sin(w*pi/180);
end;
Function CosD(const w : kfloat) : kfloat;
begin
result:=Cos(w*pi/180);
end;
Procedure EinheitsVektor(out v : VektorArr;const ph,th : kfloat);
var cth : kfloat;
begin
cth:=cosD(th);
v[0]:=cosD(ph)*cth;
v[1]:=sinD(ph)*cth;
v[2]:=sinD(th);
end;
Function Gettheta(const v : VektorArr) : kfloat;
begin
result:=aTanG(sqrt(sqr(v[0])+sqr(v[1])),v[2]);
end;
Function Getphi(const v : VektorArr) : kfloat;
begin
result:=aTanG(v[0],v[1]);
end;
Procedure TCube.InitDrehmatrizen;
begin
DMLogicToCube[0,0]:=-cos(arctan(sqrt(2)));
DMLogicToCube[1,0]:=-1/sqrt(2);
DMLogicToCube[2,0]:=-cos(arctan(sqrt(2)))/sqrt(2);
DMLogicToCube[0,1]:= cos(arctan(sqrt(2)));
DMLogicToCube[1,1]:=-1/sqrt(2);
DMLogicToCube[2,1]:= cos(arctan(sqrt(2)))/sqrt(2);
DMLogicToCube[0,2]:=-cos(arctan(sqrt(2)));
DMLogicToCube[1,2]:= 0;
DMLogicToCube[2,2]:= sin(arctan(sqrt(2)));
end;
function TCube.LogicToCube(const apo: TPosArr) : TPosArr;
Var
s,z : Integer;
vzz,v : VektorArr;
ee : KFloat;
begin
EinheitsVektor(v,apo[3],apo[4]);
for z:=0 to 2 do
begin
result[z]:=0;
vzz[z]:=0;
for s:=0 to 2 do begin
ee:=DMLogicToCube[z,s]; //AccessViolation here
result[z]:=result[z]+ee*apo[s];
vzz[z]:=vzz[z]+ee*v[s];
end;
Result[z]:=result[z]*1000;
end;
result[3]:=Getphi(vzz);
result[4]:=Gettheta(vzz);
end;
const useInput : TPosArr=(0.25,0.10,0.05,20.0,45.0);
var
Cube : TCube;
resu : TPosArr;
i : integer;
resstr: string;
const
correctresults: array[0..4] of string[10] =
(' -115.4701',' -247.4874',' -20.4124',' -135.5047',' 23.8797');
begin
if not is_sse2_cpu then
halt(0);
Cube:=TCube.Create;
Cube.InitDrehmatrizen;
resu:=Cube.LogicToCube(useInput);
for i := 0 to High(resu) do
begin
writeln(useinput[i]:10:4,' -> ',resu[i]:10:4);
str(resu[i]:10:4,resstr);
if resstr <> correctresults[i] then
halt(1);
end;
cube.free;
end.