To create arbitrary floating point / replace precision for Double, I try to wrap MPFR using FFI, but despite all my efforts, the simplest part of the code does not work. It compiles, it works, but it scoffs at us, pretending to need some work. A simple version of C code happily prints the number β1β (640 decimal places) for a total of 10,000 times. The Haskell version, when asked to do the same, silently decomposes (?) The data after 289 printouts of "1.0000 ... 0000" and after 385 printouts, this causes an assertion and bomb error. I do not understand how to do this, since it "should work."
The code can be viewed at http://hpaste.org/10923 and downloaded at http://www.updike.org/mpfr-broken.tar.gz
I use GHC 6.83 on FreeBSD 6 and GHC 6.8.2 on Mac OS X. Note that you will need MPFR (verified from 2.3.2) installed with the correct paths (changing the Makefile) for libs and headers (along with that of GMP) to successfully compile this.
Questions
Why does version C work, but version of Haskell has leaked? What else am I missing when approaching FFI? I tried StablePtrs and had the same results.
Can anyone else check if this is a Mac / BSD only issue by compiling and running my code? (Does the βCβ code work? Does the Haskell code βrunβ?) Can someone from Linux and Windows try to compile / run and see if you get the same results?
C code: (works.c)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <gmp.h> #include <mpfr.h> #include "mpfr_ffi.c" int main() { int i; mpfr_ptr one; mpf_set_default_prec_decimal(640); one = mpf_set_signed_int(1); for (i = 0; i < 10000; i++) { printf("%d\n", i); mpf_show(one); } }
Haskell Code: (Main.hs --- not working)
module Main where import Foreign.Ptr ( Ptr, FunPtr ) import Foreign.C.Types ( CInt, CLong, CULong, CDouble ) import Foreign.StablePtr ( StablePtr ) data MPFR = MPFR foreign import ccall "mpf_set_default_prec_decimal" c_set_default_prec_decimal :: CInt -> IO () setPrecisionDecimal :: Integer -> IO () setPrecisionDecimal decimal_digits = do c_set_default_prec_decimal (fromInteger decimal_digits) foreign import ccall "mpf_show" c_show :: Ptr MPFR -> IO () foreign import ccall "mpf_set_signed_int" c_set_signed_int :: CLong -> IO (Ptr MPFR) showNums kn = do print n c_show k main = do setPrecisionDecimal 640 one <- c_set_signed_int (fromInteger 1) mapM_ (showNums one) [1..10000]
source share