libBF 0.6.8 → 0.6.9
raw patch · 5 files changed
+199/−6 lines, 5 filesdep +math-functionsnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: math-functions
API changes (from Hackage documentation)
+ LibBF: bfAcos :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfAsin :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfAtan :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfAtan2 :: BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status)
+ LibBF: bfConstPi :: BFOpts -> (BigFloat, Status)
+ LibBF: bfCos :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfExp :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfLog :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfSin :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF: bfTan :: BFOpts -> BigFloat -> (BigFloat, Status)
+ LibBF.Mutable: facos :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: fasin :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: fatan :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: fatan2 :: BFOpts -> BF -> BF -> BF -> IO Status
+ LibBF.Mutable: fconst_pi :: BFOpts -> BF -> IO Status
+ LibBF.Mutable: fcos :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: fexp :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: flog :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: fsin :: BFOpts -> BF -> BF -> IO Status
+ LibBF.Mutable: ftan :: BFOpts -> BF -> BF -> IO Status
Files
- CHANGELOG.md +5/−0
- libBF.cabal +3/−2
- src/LibBF.hs +52/−0
- src/LibBF/Mutable.hsc +81/−1
- tests/RunUnitTests.hs +58/−3
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for libBF-hs +## 0.6.9 -- 2026-08-26++* Add `bfConstPi`, `bfExp`, `bfLog`, `bfSin`, `bfCos`, `bfTan`, `bfAsin`,+ `bfAcos`, `bfAtan`, and `bfAtan2`.+ ## 0.6.8 -- 2024.06.05 * Fix a bug that would cause `(>)` and `(>=)` (in the `Ord BigFloat` instance)
libBF.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2 name: libBF-version: 0.6.8+version: 0.6.9 synopsis: A binding to the libBF library. description: LibBF is a C library for working with arbitray precision IEEE 754 floating point numbers.@@ -12,7 +12,7 @@ maintainer: iavor.diatchki@gmail.com -- copyright: category: Data-extra-source-files: CHANGELOG.md+extra-doc-files: CHANGELOG.md source-repository head type: git@@ -86,5 +86,6 @@ default-language: Haskell2010 build-depends: base, libBF,+ math-functions, tasty >= 1.3 && < 1.6, tasty-hunit >= 0.10 && < 0.11
src/LibBF.hs view
@@ -44,6 +44,16 @@ , bfFMA, bfMulWord, bfMulInt, bfMul2Exp , bfSqrt , bfPow+ , bfConstPi+ , bfExp+ , bfLog+ , bfSin+ , bfCos+ , bfTan+ , bfAsin+ , bfAcos+ , bfAtan+ , bfAtan2 -- * Rounding , bfRoundFloat, bfRoundInt@@ -303,6 +313,48 @@ -- | Exponentiate a word to a positive integer power. bfPow :: BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status) bfPow opts (BigFloat x) (BigFloat y) = newBigFloat' (fpow opts x y)++-- | Compute @pi@ using the given options.+bfConstPi :: BFOpts -> (BigFloat,Status)+bfConstPi opt = newBigFloat' (fconst_pi opt)++-- | Compute the exponential function (@exp()@) of a number using the given+-- options.+bfExp :: BFOpts -> BigFloat -> (BigFloat,Status)+bfExp opt (BigFloat x) = newBigFloat' (fexp opt x)++-- | Compute the logarithm (@log()@) of a number using the given options.+bfLog :: BFOpts -> BigFloat -> (BigFloat,Status)+bfLog opt (BigFloat x) = newBigFloat' (flog opt x)++-- | Compute the sine of a number using the given options.+bfSin :: BFOpts -> BigFloat -> (BigFloat,Status)+bfSin opt (BigFloat x) = newBigFloat' (fsin opt x)++-- | Compute the cosine of a number using the given options.+bfCos :: BFOpts -> BigFloat -> (BigFloat,Status)+bfCos opt (BigFloat x) = newBigFloat' (fcos opt x)++-- | Compute the tangent of a number using the given options.+bfTan :: BFOpts -> BigFloat -> (BigFloat,Status)+bfTan opt (BigFloat x) = newBigFloat' (ftan opt x)++-- | Compute the arcsine of a number using the given options.+bfAsin :: BFOpts -> BigFloat -> (BigFloat,Status)+bfAsin opt (BigFloat x) = newBigFloat' (fasin opt x)++-- | Compute the arccosine of a number using the given options.+bfAcos :: BFOpts -> BigFloat -> (BigFloat,Status)+bfAcos opt (BigFloat x) = newBigFloat' (facos opt x)++-- | Compute the arctangent of a number using the given options.+bfAtan :: BFOpts -> BigFloat -> (BigFloat,Status)+bfAtan opt (BigFloat x) = newBigFloat' (fatan opt x)++-- | Compute the two-argument arctangent function of two numbers using the given+-- options.+bfAtan2 :: BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status)+bfAtan2 opts (BigFloat x) (BigFloat y) = newBigFloat' (fatan2 opts x y) -- | Constant to a 'Double' bfToDouble :: RoundMode -> BigFloat -> (Double, Status)
src/LibBF/Mutable.hsc view
@@ -51,7 +51,16 @@ , fpow , fround , frint-+ , fconst_pi+ , fexp+ , flog+ , fsin+ , fcos+ , ftan+ , fasin+ , facos+ , fatan+ , fatan2 -- * Convert from a number , toDouble@@ -391,8 +400,36 @@ foreign import ccall "bf_sqrt" bf_sqrt :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status +foreign import ccall "bf_const_pi"+ bf_const_pi :: Ptr BF -> LimbT -> FlagsT -> IO Status +foreign import ccall "bf_exp"+ bf_exp :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status +foreign import ccall "bf_log"+ bf_log :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_sin"+ bf_sin :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_cos"+ bf_cos :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_tan"+ bf_tan :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_asin"+ bf_asin :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_acos"+ bf_acos :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_atan"+ bf_atan :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status++foreign import ccall "bf_atan2"+ bf_atan2 :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status+ bfArith :: (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status) -> BFOpts -> BF -> BF -> BF -> IO Status bfArith fun (BFOpts prec flags) (BF fa) (BF fb) (BF fr) =@@ -487,8 +524,51 @@ fpow :: BFOpts -> BF -> BF -> BF -> IO Status fpow (BFOpts prec flags) = bf3 (\out in1 in2 -> bf_pow out in1 in2 prec flags) +-- | Compute @pi@ to the specified precision and store the result in the+-- argument.+fconst_pi :: BFOpts -> BF -> IO Status+fconst_pi (BFOpts p f) (BF fout) = withForeignPtr fout \out -> bf_const_pi out p f +-- | Compute the exponential function (@exp()@) of the first number and store+-- the result in the second.+fexp :: BFOpts -> BF -> BF -> IO Status+fexp (BFOpts p f) = bf2 (\res inp -> bf_exp res inp p f) +-- | Compute the logarithm (@log()@) of the first number and store the result in+-- the second.+flog :: BFOpts -> BF -> BF -> IO Status+flog (BFOpts p f) = bf2 (\res inp -> bf_log res inp p f)++-- | Compute the sine of the first number and store the result in the second.+fsin :: BFOpts -> BF -> BF -> IO Status+fsin (BFOpts p f) = bf2 (\res inp -> bf_sin res inp p f)++-- | Compute the cosine of the first number and store the result in the second.+fcos :: BFOpts -> BF -> BF -> IO Status+fcos (BFOpts p f) = bf2 (\res inp -> bf_cos res inp p f)++-- | Compute the tangent of the first number and store the result in the second.+ftan :: BFOpts -> BF -> BF -> IO Status+ftan (BFOpts p f) = bf2 (\res inp -> bf_tan res inp p f)++-- | Compute the arcsine of the first number and store the result in the second.+fasin :: BFOpts -> BF -> BF -> IO Status+fasin (BFOpts p f) = bf2 (\res inp -> bf_asin res inp p f)++-- | Compute the arccosine of the first number and store the result in the+-- second.+facos :: BFOpts -> BF -> BF -> IO Status+facos (BFOpts p f) = bf2 (\res inp -> bf_acos res inp p f)++-- | Compute the arctangent of the first number and store the result in the+-- second.+fatan :: BFOpts -> BF -> BF -> IO Status+fatan (BFOpts p f) = bf2 (\res inp -> bf_atan res inp p f)++-- | Compute the two-argument arctangent function (@atan2()@) of the first two+-- numbers and store the result in the second.+fatan2 :: BFOpts -> BF -> BF -> BF -> IO Status+fatan2 (BFOpts prec flags) = bf3 (\out in1 in2 -> bf_atan2 out in1 in2 prec flags) --------------------------------------------------------------------------------
tests/RunUnitTests.hs view
@@ -1,8 +1,10 @@ {-# Language BlockArguments #-}+{-# Language LambdaCase #-} module Main(main) where +import Numeric.MathFunctions.Comparison (within) import Test.Tasty (TestTree, defaultMain, testGroup)-import Test.Tasty.HUnit ((@=?), assertFailure, testCase)+import Test.Tasty.HUnit ((@=?), assertBool, assertEqual, assertFailure, testCase) import LibBF @@ -46,6 +48,15 @@ , testCase "0 <= NaN" $ False @=? bfPosZero <= bfNaN ] ]+ , testGroup "Transcendental functions"+ [ -- LibBF's implementation of atan2 is ever-so-slightly difference from+ -- macOS libc's implementation, so check that their results are within+ -- 1 ULP rather than checking for IEEE equality.+ dblWithin1UlpTestCase "atan2 1 2" atan2 (bfAtan2 (float64 NearEven)) 1 2+ , dblWithin1UlpTestCase "atan2 2 1" atan2 (bfAtan2 (float64 NearEven)) 2 1+ , checkPredicateTestCase "sin" (bfSin (float256 NearEven)) (bfIsZero) (bfFromDouble 0)+ , checkPredicateTestCase "exp" (bfExp (float256 NearEven)) (== (bfFromDouble 1)) (bfFromDouble 0)+ ] ] statusUnderflow :: Status -> Bool@@ -63,11 +74,35 @@ (Double -> Double -> Double) -> (BigFloat -> BigFloat -> (BigFloat, Status)) -> Double -> Double -> TestTree-dblTestCase op opD opBF x y =+dblTestCase = dblCompareTestCase (@=?)++-- Check that a binary operation over BigFloats returns approximately the same+-- result as the corresponding operation over doubles. Here, "approximately"+-- means "within 1 unit in the last place (ULP)". This is a very crude way to+-- check if two values are approximately equal, so use this with caution.+dblWithin1UlpTestCase ::+ String ->+ (Double -> Double -> Double) ->+ (BigFloat -> BigFloat -> (BigFloat, Status)) ->+ Double -> Double -> TestTree+dblWithin1UlpTestCase = dblCompareTestCase $ \expected actual ->+ assertBool "Values not within 1 ULP" $ within 1 expected actual++-- Construct a test case that compares the result of a binary BigFloat+-- operation against the same result as the corresponding operation over+-- doubles.+dblCompareTestCase ::+ -- How to compare the expected result against the actual result.+ (Double -> Double -> IO ()) ->+ String ->+ (Double -> Double -> Double) ->+ (BigFloat -> BigFloat -> (BigFloat, Status)) ->+ Double -> Double -> TestTree+dblCompareTestCase resCmp op opD opBF x y = testCase (unwords [show x, op, show y]) $ case z1 of Left err -> assertFailure ("status: " ++ err)- Right actual -> expected @=? actual+ Right actual -> resCmp expected actual where expected = opD x y z1 = case opBF (bfFromDouble x) (bfFromDouble y) of@@ -82,3 +117,23 @@ bfSubnormalTestCase bf expected = testCase (show bf) $ expected @=? bfIsSubnormal (float32 NearEven) bf++checkPredicateTestCase ::+ Show a =>+ String ->+ (a -> (BigFloat, Status)) ->+ (BigFloat -> Bool) ->+ a ->+ TestTree+checkPredicateTestCase opName opBF predicate input =+ testCase opName $ do+ assertEqual+ ("Status '" ++ show bfStatus ++ "' not OK for " ++ describeOp)+ bfStatus+ Ok+ assertBool+ ("Test predicate failed on result " ++ show bfRes ++ " on " ++ describeOp)+ (predicate bfRes)+ where+ (bfRes, bfStatus) = opBF input+ describeOp = opName ++ "(" ++ show input ++ ")"