Skip to content

unsafeClamp behaves incorrectly for NaN #34

@felixSchl

Description

@felixSchl

unsafeClamp is supposed to catch NaNs and return 0.

-- | Convert an integral `Number` to an `Int`, by clamping to the `Int` range.
-- | This function will return 0 if the input is `NaN` or an `Infinity`.
unsafeClamp :: Number -> Int
unsafeClamp x
| x == infinity = 0
| x == -infinity = 0
| x >= toNumber top = top
| x <= toNumber bottom = bottom
| otherwise = fromMaybe 0 (fromNumber x)

On the surface this works, however, it only works because the PureScript compiler inlines the comparison operation thereby avoiding the Ord instance for numbers and integers and doing whatever the JS runtime does, instead. This my be good enough but it cost me quite a bit of time to track down when implementing a new backend since I considered inlining of operators a mere optimization that should not impact semantics. If the backend does not implement this optimization, case 3 hits, giving you top for Int

To recap, the behavior of NaN (in Js and C) is that it does not equal itself. So maybe we could add a seemingly redundant guard:

  | x != x = 0 -- NaN

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions