approximate-0.2.2.2: src/Data/Approximate/Numerics.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------
-- |
-- Copyright : (c) Edward Kmett 2013
-- License : BSD3
-- Maintainer: Edward Kmett <ekmett@gmail.com>
-- Stability : experimental
-- Portability: non-portable
--
-- These functions provide wildly inaccurate but very fast
-- approximations to common transcendental functions.
--
-- The algorithms here are based on Martin Ankerl's optimized 'pow',
-- <http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/>
-- which is in turn based on
-- <http://nic.schraudolph.org/pubs/Schraudolph99.pdf>
--------------------------------------------------------------------
module Data.Approximate.Numerics
( Fast(..)
, blog
) where
class Floating a => Fast a where
-- | Calculate an approximate log.
flog :: a -> a
flog_lb :: a -> a
flog_ub :: a -> a
-- | Calculate an approximate exp.
fexp :: a -> a
fexp_lb :: a -> a
fexp_ub :: a -> a
-- | Calculate an approximate pow.
fpow :: a -> a -> a
fpow_lb :: a -> a -> a
fpow_ub :: a -> a -> a
instance Fast Float where
flog = logf_fast
flog_lb = logf_fast_lb
flog_ub = logf_fast_ub
fexp = better_expf_fast
fexp_lb = expf_fast_lb
fexp_ub = expf_fast_ub
fpow = better_powf_fast_precise
fpow_lb = powf_fast_lb
fpow_ub = powf_fast_ub
instance Fast Double where
flog = log_fast
flog_lb = log_fast_lb
flog_ub = log_fast_ub
fexp = better_exp_fast
fexp_lb = exp_fast_lb
fexp_ub = exp_fast_ub
fpow = better_pow_fast_precise
fpow_lb = pow_fast_lb
fpow_ub = pow_fast_ub
-- | Borchardt’s Algorithm from “Dead Reckoning: Calculating without instruments”.
--
-- This is a remarkably bad approximate logarithm.
--
-- 'flog' had better outperform it! It is provided merely for comparison.
blog :: Floating a => a -> a
blog x = 6 * (x - 1) / (x + 1 + 4 * sqrt x)
-- 6 / (x + 1 + 4 * sqrt x) / (x-1) -- herbie's suggested replacement.
#ifdef HERBIE
{-# ANN blog "NoHerbie" #-}
#endif
foreign import ccall unsafe pow_fast_lb :: Double -> Double -> Double
foreign import ccall unsafe pow_fast_ub :: Double -> Double -> Double
foreign import ccall unsafe better_pow_fast_precise :: Double -> Double -> Double
foreign import ccall unsafe powf_fast_lb :: Float -> Float -> Float
foreign import ccall unsafe powf_fast_ub :: Float -> Float -> Float
foreign import ccall unsafe better_powf_fast_precise :: Float -> Float -> Float
foreign import ccall unsafe better_exp_fast :: Double -> Double
foreign import ccall unsafe exp_fast_lb :: Double -> Double
foreign import ccall unsafe exp_fast_ub :: Double -> Double
foreign import ccall unsafe better_expf_fast :: Float -> Float
foreign import ccall unsafe expf_fast_lb :: Float -> Float
foreign import ccall unsafe expf_fast_ub :: Float -> Float
foreign import ccall unsafe log_fast :: Double -> Double
foreign import ccall unsafe log_fast_lb :: Double -> Double
foreign import ccall unsafe log_fast_ub :: Double -> Double
foreign import ccall unsafe logf_fast :: Float -> Float
foreign import ccall unsafe logf_fast_lb :: Float -> Float
foreign import ccall unsafe logf_fast_ub :: Float -> Float