From e01925c580bf11da70dc0faed8668c09cffa0d40 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Wed, 13 Oct 2010 18:38:54 -0400 Subject: [PATCH] fenv: Add appropriate #ifdef's to rounding direction helpers. An implementation need not support all of the rounding modes, so only compile in support for those that are available. --- Data/Floating/Environment.hs | 20 ++++++++++---------- cfloat.c | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Data/Floating/Environment.hs b/Data/Floating/Environment.hs index c90ee11..ccc38d8 100644 --- a/Data/Floating/Environment.hs +++ b/Data/Floating/Environment.hs @@ -70,10 +70,14 @@ import Debug.Trace import Foreign.C import Foreign -foreign import ccall unsafe "set_roundmode" - set_roundmode :: CInt -> IO CInt -foreign import ccall unsafe "get_roundmode" - get_roundmode :: IO CInt +foreign import ccall unsafe "fenv_set_roundmode" + fenv_set_roundmode :: CInt -> IO CInt +foreign import ccall unsafe "fenv_get_roundmode" + fenv_get_roundmode :: IO CInt +foreign import ccall unsafe "fenv_test_excepts" + fenv_test_excepts :: IO CUInt +foreign import ccall unsafe "fenv_raise_excepts" + fenv_raise_excepts :: CUInt -> IO CInt foreign import ccall unsafe "fegetenv" c_fegetenv :: Ptr FEnvState -> IO CInt @@ -81,10 +85,6 @@ foreign import ccall unsafe "fesetenv" c_fesetenv :: Ptr FEnvState -> IO CInt foreign import ccall unsafe "feholdexcept" c_feholdexcept :: Ptr FEnvState -> IO CInt -foreign import ccall unsafe "fenv_test_excepts" - fenv_test_excepts :: IO CUInt -foreign import ccall unsafe "fenv_raise_excepts" - fenv_raise_excepts :: CUInt -> IO CInt data RoundingMode = ToNearest | Upward | Downward | TowardZero deriving (Show, Read, Enum, Bounded) @@ -227,12 +227,12 @@ unsafeRaiseExceptions ex = do unsafeSetRoundingMode :: RoundingMode -> IO () unsafeSetRoundingMode mode = do - rc <- set_roundmode (fromIntegral (fromEnum mode)) + rc <- fenv_set_roundmode (fromIntegral (fromEnum mode)) unless (rc == 0) $ fail "Error setting rounding mode" getRoundingMode :: IO RoundingMode getRoundingMode = do - rc <- get_roundmode + rc <- fenv_get_roundmode unless (rc >= 0) $ fail "Error getting rounding mode" return . toEnum . fromIntegral $ rc diff --git a/cfloat.c b/cfloat.c index 58af4b9..6fd13d5 100644 --- a/cfloat.c +++ b/cfloat.c @@ -104,23 +104,31 @@ int float_compare(float a, float b) return -1; } -int set_roundmode(int mode) +int fenv_set_roundmode(int mode) { int cmode; switch (mode) { +#ifdef FE_TONEAREST case 0: cmode = FE_TONEAREST; break; +#endif +#ifdef FE_UPWARD case 1: cmode = FE_UPWARD; break; +#endif +#ifdef FE_DOWNWARD case 2: cmode = FE_DOWNWARD; break; +#endif +#ifdef FE_TOWARDZERO case 3: cmode = FE_TOWARDZERO; break; +#endif default: return -1; } @@ -128,19 +136,27 @@ int set_roundmode(int mode) return fesetround(cmode); } -int get_roundmode(void) +int fenv_get_roundmode(void) { int cmode = fegetround(); switch (cmode) { +#ifdef FE_TONEAREST case FE_TONEAREST: return 0; +#endif +#ifdef FE_UPWARD case FE_UPWARD: return 1; +#endif +#ifdef FE_DOWNWARD case FE_DOWNWARD: return 2; +#endif +#ifdef FE_TOWARDZERO case FE_TOWARDZERO: return 3; +#endif default: return -1; } -- 2.11.4.GIT