为了创建一种任意的精确度浮点/放在替双重的,我想到包裹 这三个库 使用FFI但是,尽管我所有的努力最简单位的代码不起作用。它汇编、运行,但它嘲弄崩溃之后假装的工作一段时间。一个简单的C的代码版本高兴地指纹数字"1"(640小数位)共计10,000倍。Haskell版本,当被要求做的一样,悄悄地破坏(?) 后的数据只289打印输出的"1.0000时...0000"后385打印输出,导致一个断言的失败和炸弹。我在失去对如何进行调试这一点,因为它"应当工作"。

代码可在仔细阅读 http://hpaste.org/10923 并下载 http://www.updike.org/mpfr-broken.tar.gz

我使用的GHC6.83FreeBSD上6和GHC6.8.2在Mac OS X.注意你会需要这三个库(测试2.3.2)安装着正确的路径(改变的生成文件),用于库和标题的文件(以及那些从GMP)以成功地汇编这一点。

的问题

  • 为什么不C版本的工作,但Haskell版本的鳞片?还有什么我失当接近FFI?我试图StablePtrs,并已完全相同的结果。

  • 可别人验证,如果这是Mac/BSD唯一的问题通过编写和运行我的代码?(不C码"工作"的工作?不Haskell的代码"noworks"工作?) 任何人都可以在Linux和Windows试图编纂/运行,并看看如果你得到同样的结果?

C码:(工作。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的代码:(。hs---不工作)

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 k n = do  
   print n  
   c_show k  

main = do  
   setPrecisionDecimal 640  
   one <- c_set_signed_int (fromInteger 1)  
   mapM_ (showNums one) [1..10000]  
有帮助吗?

解决方案

我看到的问题也在

$ uname -a
Linux burnup 2.6.26-gentoo-r1 #1 SMP PREEMPT Tue Sep 9 00:05:54 EDT 2008 i686 Intel(R) Pentium(R) 4 CPU 2.80GHz GenuineIntel GNU/Linux
$ gcc --version
gcc (GCC) 4.2.4 (Gentoo 4.2.4 p1.0)
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.8.3

我还看出改变,从1.0000时...000至1.0000时...[垃圾].

让我们来看看,以下工作:

main = do
    setPrecisionDecimal 640
    mapM_ (const $ c_set_signed_int (fromInteger 1) >>= c_show) [1..10000]

其范围缩小问题的部分 one 正在以某种方式破坏在运行时间。看的出 ghc -Cghc -S, 虽然,不是给我任何线索。

嗯, ./noworks +RTS -H1G 还工作, ./noworks +RTS -k[n]k, 为不同的价值观 [n], 证明故障在不同的方式。

我没有固体导致的,但有两种可能性,跳到我的心灵:

  • GMP,其GHC运行时使用,这三个库具有一些奇怪的相互作用
  • 堆空间C功能称为内的全康运行是有限的,这三个库不处理好的

这就是说...还有一个原因是你是你自己绑定,而不是使用 HMPFR?

其他提示

犹大*雅各布森回答这个Haskell-咖啡馆的邮寄名单:

这个是 一个已知的问题GHC 因为GHC使用GMP内部(维持整数)。

显然,C数据堆中独自由GHC在基本上所有的情况下 除了 代码使用的FFI访问GMP或任何C库依赖GMP(喜欢这三个库,我想到使用)。有一些解决办法(痛苦),但是"正确的"的方式将是为无论是黑客GHC(硬)或获得西蒙斯来消除全康的依赖GMP(困难).

阿莱斯Bizjak,维护者 HMPFR 张贴到haskell-咖啡馆和展示了如何保持GHC从控制分配的肢体(并因此让他们独自,而不是GCing他们,他们会重装):

mpfr_ptr mpf_new_mpfr()  
{  
  mpfr_ptr result = malloc(sizeof(__mpfr_struct));  
  if (result == NULL) return NULL;  
  /// these three lines:  
  mp_limb_t * limb = malloc(mpfr_custom_get_size(mpfr_get_default_prec()));  
  mpfr_custom_init(limb, mpfr_get_default_prec());  
  mpfr_custom_init_set(result, MPFR_NAN_KIND, 0, mpfr_get_default_prec(), limb);  
  return result;  
}

对我来说,这是很容易于加入的努力写一个替代GMP在GHC,这将是唯一的选择,如果我真的想要使用任何库,取决于GMP。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top