@hackage if-instance0.5.1.0

Branch on whether a constraint is satisfied

This library provides a mechanism that can be used to branch on whether a constraint is satisfied (not limited to typeclass instances).

Usage example:

{-# OPTIONS_GHC -fplugin=IfSat.Plugin #-}

module MyModule where

import Data.Constraint.If ( IfSat(ifSat) )

hypot :: forall a. ( Floating a, IfSat (FMA a) ) => a -> a -> a
hypot = ifSat @(FMA a) withFMA withoutFMA
  where
    withFMA :: FMA a => a -> a -> a
    withFMA x y =
      let
        h = sqrt $ fma x x (y * y)
        h² = h * h
        x² = x * x
        u = fma (-y) y (h² - x²) + fma h h (-h²) - fma x x (-x²)
      in
        h - u / ( 2 * h )
    withoutFMA :: a -> a -> a
    withoutFMA x y = sqrt ( x * x + y * y )

Here we select between two ways of computing the hypotenuse function based on whether we have access to the fused multiply-add operation

 fma :: FMA a => a -> a -> a -> a

which computes \ x y z -> ( x * y ) + z in a single instruction, providing stronger guarantees about precision of the result.

A call of the form hypot @MyNumberType will either use the robust withFMA function when an FMA MyNumberType instance is available, or will fallback to the simple withoutFMA implementation when no such instance can be found.