문제

을 만들기 위해서는 임의의 정밀 부동 소수점/drop 에서 교체 위해 더블,해요 포장 MPFR 를 사용하 FFI 그러나에도 불구하고 내 모든 노력을 가장 간단한 비트의 코드 작동하지 않습니다.그것은 컴파일하고,그것을 실행하지만,그것은 충돌을 조롱한 후에 일하는 척한다.간단한 C 버전의 코드를 행복하게 인쇄 숫자"1"(640 소수 자릿수)의 총 10,000 번입니다.일 버전을 물었을 때,같은,조용히 부패한(?) 데이터 후 289 인쇄 밖의"1.0000...0000"후 385 인쇄 아웃,그것을 일으키는 주장 실패와 합니다.나는 손실에 대한 진행하는 방법에 디버깅 이 때문에 그것은"작업해야 합".

코드할 수 있습 숙독 http://hpaste.org/10923 에서 다운로드 http://www.updike.org/mpfr-broken.tar.gz

내가 사용하여 지 6.83on FreeBSD6GHC6.8.2Mac OS X.참고해야 합 MPFR(스 테스트 2.3.2)이 설치되어 있으로 올바른 경로(변경 Makefile)한 라이브러리 및 헤더 파일(사람들과 함께서 GMP)을 성공적으로 컴파일한다.

질문

  • 왜 C 버전하지만,일켈 버전 플레이크까?무엇이 다른 나는 누락에 접근할 때 FFI?나 StablePtrs 고 했다 정확한 결과입니다.

  • 할 수 있는 다른 사람을 확인하는 경우 이은 맥/BSD 만 문제가하여 컴파일하고 실행할 수 있는 내 코드는?(않 C 코드는"작품"일하는가?지 않는 메인 코드는"noworks"일하는가?) 할 수 있는 사람이 리눅스에서 윈도우 시도를 사용하여 컴파일을 실행하고 당신 동일한 결과를 얻을 수?

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);
    }  
}  

켈 코드:(습니다.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, 하지만,포함하여 모든니다.

Hmm, ./noworks +RTS -H1G 또한,고 ./noworks +RTS -k[n]k, 을 위해,다양한 값의 [n], 입증 장애에서 다른 방법이 있습니다.

난 솔리드 리드,하지만 두 가지는 가능성을 뛰어 내 마:

  • GMP 는 모 runtime 사용 MPFR 을 갖는 몇 가지 이상한 상호 작용
  • 스택을 위한 공간은 C 함수 호출에 들어 런타임이 제한,그리고 MPFR 지 않을 다루는 아

는 말하고...는 이유 있는 당신의 자신의 바인딩 보다는 오히려 사용 HMPFR?

다른 팁

유다 Jacobsen 응답이에켈-카페 메일링 리스트:

알려진 문제 GHC 때문에의 방법으로 데이타 모델을 사용하 GMP 내부적으로(을 유지해 정수).

분명히 C 데이터 힙에 혼자서에 의해 들어에 기본적으로 모든 경우 를 제외하고 를 사용하는 코드 FFI 액세스 GMP 또는 C 라이브러리에 의존하는 GMP(같은 MPFR 고 싶었다는 것을 포함)를 사용합니다.방법을 사용하여 해결할 수 있습니다(고)하지만"오른쪽"이 방법은 것 중 하나에 해킹 GHC(하드)또는 시몬을 제거한 데이타 모델의 의존에 GMP(힘).

Aleš Bizjak,유지 관리자의 HMPFR 게시켈-카페 및 보여준을 유지하는 방법 들에서 제어할당의 사지(따라서 그들을 떠나,혼자는 대신 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 에서 구현하는 것이 유일한 대안이 될 경우 내가 정말 원하는 사용하는 라이브러리에 따라 달라집 GMP.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top