mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 05:29:22 +02:00
* handle min/max properly if it is applied to NaNs
* test extended git-svn-id: trunk@47729 -
This commit is contained in:
parent
8fd3beb35b
commit
3707cb4b1e
@ -1614,8 +1614,10 @@ implementation
|
|||||||
(tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left)))) then
|
(tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left)))) then
|
||||||
begin
|
begin
|
||||||
paratype:=tassignmentnode(thenstmnt).left.resultdef;
|
paratype:=tassignmentnode(thenstmnt).left.resultdef;
|
||||||
if (left.nodetype in [gtn,gten]) and
|
if ((left.nodetype in [gtn,gten]) and
|
||||||
(tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right))) then
|
tassignmentnode(thenstmnt).right.isequal(taddnode(left).left)) or
|
||||||
|
((left.nodetype in [ltn,lten]) and
|
||||||
|
tassignmentnode(thenstmnt).right.isequal(taddnode(left).right)) then
|
||||||
begin
|
begin
|
||||||
if is_double(paratype) then
|
if is_double(paratype) then
|
||||||
in_nr:=in_max_double
|
in_nr:=in_max_double
|
||||||
@ -1637,9 +1639,14 @@ implementation
|
|||||||
else if is_s32bitint(paratype) then
|
else if is_s32bitint(paratype) then
|
||||||
in_nr:=in_min_longint;
|
in_nr:=in_min_longint;
|
||||||
end;
|
end;
|
||||||
|
{ for inline nodes, the first parameter is the last one in the linked list
|
||||||
|
|
||||||
|
Due to the defined behaviour for the min/max intrinsics that in case of a NaN
|
||||||
|
the second parameter is taken, we have to put the else part into the second parameter
|
||||||
|
thus pass it to the first callparanode call }
|
||||||
Result:=cassignmentnode.create_internal(tassignmentnode(thenstmnt).left.getcopy,
|
Result:=cassignmentnode.create_internal(tassignmentnode(thenstmnt).left.getcopy,
|
||||||
cinlinenode.create(in_nr,false,ccallparanode.create(taddnode(left).right.getcopy,
|
cinlinenode.create(in_nr,false,ccallparanode.create(tassignmentnode(elsestmnt).right.getcopy,
|
||||||
ccallparanode.create(taddnode(left).left.getcopy,nil)))
|
ccallparanode.create(tassignmentnode(thenstmnt).right.getcopy,nil)))
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
{$endif defined(i386) or defined(x86_64) or defined(xtensa)}
|
{$endif defined(i386) or defined(x86_64) or defined(xtensa)}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
|
{ %opt=-O- -Oonofastmath } { with fast math, the operands of min/max might be swapped and this breaks the tests using NaN }
|
||||||
|
|
||||||
{$mode objfpc}
|
{$mode objfpc}
|
||||||
|
uses
|
||||||
|
Math;
|
||||||
|
|
||||||
procedure TestSingle;
|
procedure TestSingle;
|
||||||
|
|
||||||
function Min1(a, b: Single): Single; inline;
|
function Min1(a, b: Single): Single; inline;
|
||||||
@ -36,7 +41,7 @@ procedure TestSingle;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
v1,v3 : Single;
|
v1,v3,vNaN : Single;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
v1:=1;
|
v1:=1;
|
||||||
@ -73,6 +78,25 @@ procedure TestSingle;
|
|||||||
halt(33);
|
halt(33);
|
||||||
if Max2(v1,v3)<>v3 then
|
if Max2(v1,v3)<>v3 then
|
||||||
halt(34);
|
halt(34);
|
||||||
|
SetExceptionMask([exInvalidOp]);
|
||||||
|
vNaN:=NaN;
|
||||||
|
if not(IsNaN(Min1(v1,vNaN))) then
|
||||||
|
halt(41);
|
||||||
|
if Min1(NaN,v1)<>v1 then
|
||||||
|
halt(42);
|
||||||
|
if not(IsNaN(Max1(v1,vNaN))) then
|
||||||
|
halt(43);
|
||||||
|
if Max1(vNaN,v3)<>v3 then
|
||||||
|
halt(44);
|
||||||
|
if not(IsNaN(Min2(v1,vNaN))) then
|
||||||
|
halt(45);
|
||||||
|
if Min2(vNaN,v3)<>v3 then
|
||||||
|
halt(46);
|
||||||
|
if not(IsNaN(Max2(v1,vNaN))) then
|
||||||
|
halt(47);
|
||||||
|
if Max2(vNaN,v3)<>v3 then
|
||||||
|
halt(48);
|
||||||
|
SetExceptionMask([]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TestDouble;
|
procedure TestDouble;
|
||||||
@ -112,7 +136,7 @@ procedure TestDouble;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
v1,v3 : Double;
|
v1,v3,vNaN : Double;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
v1:=1;
|
v1:=1;
|
||||||
@ -149,6 +173,25 @@ procedure TestDouble;
|
|||||||
halt(133);
|
halt(133);
|
||||||
if Max2(v1,v3)<>v3 then
|
if Max2(v1,v3)<>v3 then
|
||||||
halt(134);
|
halt(134);
|
||||||
|
SetExceptionMask([exInvalidOp]);
|
||||||
|
vNaN:=NaN;
|
||||||
|
if not(IsNaN(Min1(v1,vNaN))) then
|
||||||
|
halt(141);
|
||||||
|
if Min1(NaN,v1)<>v1 then
|
||||||
|
halt(142);
|
||||||
|
if not(IsNaN(Max1(v1,vNaN))) then
|
||||||
|
halt(143);
|
||||||
|
if Max1(vNaN,v3)<>v3 then
|
||||||
|
halt(144);
|
||||||
|
if not(IsNaN(Min2(v1,vNaN))) then
|
||||||
|
halt(145);
|
||||||
|
if Min2(vNaN,v3)<>v3 then
|
||||||
|
halt(146);
|
||||||
|
if not(IsNaN(Max2(v1,vNaN))) then
|
||||||
|
halt(147);
|
||||||
|
if Max2(vNaN,v3)<>v3 then
|
||||||
|
halt(148);
|
||||||
|
SetExceptionMask([]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user