Skip to content

Commit

Permalink
Add some more functions to the RealExtras class
Browse files Browse the repository at this point in the history
The new functions are `floor`, `trunc`, `modf` and `remainder`

This closes ekmett/numeric-extras/#2
  • Loading branch information
Joe Hermaszewski committed Sep 27, 2015
1 parent 4e61576 commit 666b230
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
0.0.4
-----
* Added functions `floor`, `trunc`, `modf` and `remainder`
0.0.3
-----
* Marked `Numeric.Extras` `Trustworthy`.
49 changes: 49 additions & 0 deletions Numeric/Extras.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ module Numeric.Extras
( RealExtras(..)
) where

#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>), (<*>))
#endif
import Control.Arrow ((***))
import Foreign
import Foreign.C.Types
import System.IO.Unsafe (unsafeDupablePerformIO)

{-# ANN module "HLint: ignore Use camelCase" #-}

class (Storable (C a), RealFloat (C a), RealFloat a) => RealExtras a where
type C a :: *
Expand All @@ -18,6 +25,10 @@ class (Storable (C a), RealFloat (C a), RealFloat a) => RealExtras a where
hypot :: a -> a -> a
cbrt :: a -> a
erf :: a -> a
floor :: a -> a
trunc :: a -> a
modf :: a -> (a, a)
remainder :: a -> a -> a

instance RealExtras Double where
type C Double = CDouble
Expand All @@ -27,15 +38,26 @@ instance RealExtras Double where
hypot = lift2D c_hypot
cbrt = lift1D c_cbrt
erf = lift1D c_erf
floor = lift1D c_floor
trunc = lift1D c_trunc
modf = lift1D2 c_modf
remainder = lift2D c_remainder

lift1D :: (CDouble -> CDouble) -> Double -> Double
lift1D f a = realToFrac (f (realToFrac a))
{-# INLINE lift1D #-}

lift1D2 :: (CDouble -> (CDouble, CDouble)) -> Double -> (Double, Double)
lift1D2 f a = (realToFrac *** realToFrac) (f (realToFrac a))
{-# INLINE lift1D2 #-}

lift2D :: (CDouble -> CDouble -> CDouble) -> Double -> Double -> Double
lift2D f a b = realToFrac (f (realToFrac a) (realToFrac b))
{-# INLINE lift2D #-}

c_modf :: CDouble -> (CDouble, CDouble)
c_modf a = unsafeDupablePerformIO $ alloca (\i -> (,) <$> c_modf_imp a i <*> peek i)

instance RealExtras Float where
type C Float = CFloat
fmod = lift2F c_fmodf
Expand All @@ -44,15 +66,26 @@ instance RealExtras Float where
hypot = lift2F c_hypotf
cbrt = lift1F c_cbrtf
erf = lift1F c_erff
floor = lift1F c_floorf
trunc = lift1F c_truncf
modf = lift1F2 c_modff
remainder = lift2F c_remainderf

lift1F :: (CFloat -> CFloat) -> Float -> Float
lift1F f a = realToFrac (f (realToFrac a))
{-# INLINE lift1F #-}

lift1F2 :: (CFloat -> (CFloat, CFloat)) -> Float -> (Float, Float)
lift1F2 f a = (realToFrac *** realToFrac) (f (realToFrac a))
{-# INLINE lift1F2 #-}

lift2F :: (CFloat -> CFloat -> CFloat) -> Float -> Float -> Float
lift2F f a b = realToFrac (f (realToFrac a) (realToFrac b))
{-# INLINE lift2F #-}

c_modff :: CFloat -> (CFloat, CFloat)
c_modff a = unsafeDupablePerformIO $ alloca (\i -> (,) <$> c_modff_imp a i <*> peek i)

foreign import ccall unsafe "math.h fmod"
c_fmod :: CDouble -> CDouble -> CDouble
foreign import ccall unsafe "math.h expm1"
Expand All @@ -65,6 +98,14 @@ foreign import ccall unsafe "math.h cbrt"
c_cbrt :: CDouble -> CDouble
foreign import ccall unsafe "math.h erf"
c_erf :: CDouble -> CDouble
foreign import ccall unsafe "math.h floor"
c_floor :: CDouble -> CDouble
foreign import ccall unsafe "math.h trunc"
c_trunc :: CDouble -> CDouble
foreign import ccall unsafe "math.h modf"
c_modf_imp :: CDouble -> Ptr CDouble -> IO CDouble
foreign import ccall unsafe "math.h remainder"
c_remainder :: CDouble -> CDouble -> CDouble

foreign import ccall unsafe "math.h fmodf"
c_fmodf :: CFloat -> CFloat -> CFloat
Expand All @@ -78,5 +119,13 @@ foreign import ccall unsafe "math.h cbrtf"
c_cbrtf :: CFloat -> CFloat
foreign import ccall unsafe "math.h erff"
c_erff :: CFloat -> CFloat
foreign import ccall unsafe "math.h floorf"
c_floorf :: CFloat -> CFloat
foreign import ccall unsafe "math.h truncf"
c_truncf :: CFloat -> CFloat
foreign import ccall unsafe "math.h modff"
c_modff_imp :: CFloat -> Ptr CFloat -> IO CFloat
foreign import ccall unsafe "math.h remainderf"
c_remainderf :: CFloat -> CFloat -> CFloat

default (Double)
2 changes: 1 addition & 1 deletion numeric-extras.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: numeric-extras
version: 0.0.3
version: 0.0.4
synopsis: Useful tools from the C standard library
homepage: http://github.com/ekmett/numeric-extras
bug-reports: http://github.com/ekmett/numeric-extras/issues
Expand Down

0 comments on commit 666b230

Please sign in to comment.