@hackage if-instance0.2.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, despite the name of the library).

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 a b =
      let
        h = sqrt $ fma a a (b * b)
        h² = h * h
        a² = a * a
        x = fma (-b) b (h² - a²) + fma h h (-h²) - fma a a (-a²)
      in
        h - x / ( 2 * h )
    withoutFMA :: a -> a -> a
    withoutFMA a b = sqrt ( a * a + b * b )

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 \ a b c -> ( a * b ) + c in a single instruction, providing stronger guarantees about precision of the resul.

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.