mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 13:09:32 +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
|
||||
begin
|
||||
paratype:=tassignmentnode(thenstmnt).left.resultdef;
|
||||
if (left.nodetype in [gtn,gten]) and
|
||||
(tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right))) then
|
||||
if ((left.nodetype in [gtn,gten]) and
|
||||
tassignmentnode(thenstmnt).right.isequal(taddnode(left).left)) or
|
||||
((left.nodetype in [ltn,lten]) and
|
||||
tassignmentnode(thenstmnt).right.isequal(taddnode(left).right)) then
|
||||
begin
|
||||
if is_double(paratype) then
|
||||
in_nr:=in_max_double
|
||||
@ -1637,9 +1639,14 @@ implementation
|
||||
else if is_s32bitint(paratype) then
|
||||
in_nr:=in_min_longint;
|
||||
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,
|
||||
cinlinenode.create(in_nr,false,ccallparanode.create(taddnode(left).right.getcopy,
|
||||
ccallparanode.create(taddnode(left).left.getcopy,nil)))
|
||||
cinlinenode.create(in_nr,false,ccallparanode.create(tassignmentnode(elsestmnt).right.getcopy,
|
||||
ccallparanode.create(tassignmentnode(thenstmnt).right.getcopy,nil)))
|
||||
);
|
||||
end;
|
||||
{$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}
|
||||
uses
|
||||
Math;
|
||||
|
||||
procedure TestSingle;
|
||||
|
||||
function Min1(a, b: Single): Single; inline;
|
||||
@ -36,7 +41,7 @@ procedure TestSingle;
|
||||
end;
|
||||
|
||||
var
|
||||
v1,v3 : Single;
|
||||
v1,v3,vNaN : Single;
|
||||
|
||||
begin
|
||||
v1:=1;
|
||||
@ -73,6 +78,25 @@ procedure TestSingle;
|
||||
halt(33);
|
||||
if Max2(v1,v3)<>v3 then
|
||||
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;
|
||||
|
||||
procedure TestDouble;
|
||||
@ -112,7 +136,7 @@ procedure TestDouble;
|
||||
end;
|
||||
|
||||
var
|
||||
v1,v3 : Double;
|
||||
v1,v3,vNaN : Double;
|
||||
|
||||
begin
|
||||
v1:=1;
|
||||
@ -149,6 +173,25 @@ procedure TestDouble;
|
||||
halt(133);
|
||||
if Max2(v1,v3)<>v3 then
|
||||
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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user