mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 12:07:58 +02:00
166 lines
3.3 KiB
ObjectPascal
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.
|
|
|