
#9251: ghc does not expose branchless max/min operations as primops -------------------------------------+------------------------------------ Reporter: carter | Owner: carter Type: task | Status: new Priority: normal | Milestone: 7.10.1 Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: #9246 -------------------------------------+------------------------------------ Comment (by arotenberg): Question: What "should" the behaviors of min and max be for the special cases of negative zero and NaN? Currently GHC does this: {{{ Prelude> min 0.0 (-0.0) :: Double 0.0 Prelude> min (-0.0) 0.0 :: Double -0.0 Prelude> min 0.0 (0.0/0.0) :: Double NaN Prelude> min (0.0/0.0) 0.0 :: Double 0.0 }}} The SSE instructions, at least, [http://x86.renejeschke.de/html/file_module_x86_id_173.html work similarly if you get the order right]: If the values being compared are both 0.0s (of either sign), the value in the second operand (source operand) is returned. If a value in the second operand is an SNaN, that SNaN is returned unchanged to the destination (that is, a QNaN version of the SNaN is not returned). If only one value is a NaN (SNaN or QNaN) for this instruction, the second operand (source operand), either a NaN or a valid floating-point value, is written to the result. If instead of this behavior, it is required that the NaN source operand (from either the first or second operand) be returned, the action of MINSD can be emulated using a sequence of instructions, such as, a comparison followed by AND, ANDN and OR. However, [http://en.wikipedia.org/wiki/IEEE_754_revision#min_and_max according to Wikipedia], IEEE 754-2008 specifies The min and max operations are defined but leave some leeway for the case where the inputs are equal in value but differ in representation. In particular: min(+0,−0) or min(−0,+0) must produce something with a value of zero but may always return the first argument. In order to support operations such as windowing in which a NaN input should be quietly replaced with one of the end points, min and max are defined to select a number, x, in preference to a quiet NaN: min(x,NaN) = min(NaN,x) = x max(x,NaN) = max(NaN,x) = x In the current draft, these functions are called minNum and maxNum to indicate their preference for a number over a quiet NaN. Some further comparisons: Java's `Math.min` [http://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#min-double- double- specifies] Returns the smaller of two double values. That is, the result is the value closer to negative infinity. If the arguments have the same value, the result is that same value. If either value is NaN, then the result is NaN. Unlike the numerical comparison operators, this method considers negative zero to be strictly smaller than positive zero. If one argument is positive zero and the other is negative zero, the result is negative zero. The .NET Framework's `Math.Min` [http://msdn.microsoft.com/en- us/library/xcd487wd%28v=vs.110%29.aspx specifies] Parameter val1 or val2, whichever is smaller. If val1, val2, or both val1 and val2 are equal to NaN, NaN is returned. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9251#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler