new header file GMP

General FreeBASIC programming questions.
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Nov 29, 2016 1:02

Hi Makoto WATANABE
The 2015 gmp binaries are here (by srvaldez top post gmp 6.1.0):
http://www.freebasic.net/forum/viewtopic.php?f=3&t=24110&p=212995&hilit=press%2A#p212995

I think maybe your gmp version is less ??

You might need 7 zip to uncompress:
http://www.7-zip.org/
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Nov 29, 2016 1:45

Are you using the latest freebasic version?

FreeBASIC Compiler - Version 1.05.0 (01-31-2016)

This has the updated gmp.bi which has mpz_div
Makoto WATANABE
Posts: 171
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: new header file GMP

Postby Makoto WATANABE » Nov 29, 2016 6:11

Dear dodicat

Thanks for your quick reply.

I am very sorry to trouble you.
I am very sorry to bother you.

I found two "gmp.bi" in my environment.
1. "2015/01/16"
2. "2016/01/31"'' FreeBASIC binding for gmp-6.0.0

When I changed it to the version of "2016/01/31", the results of your two "Integer divide function"s have become same value (OK) .

The version of "2016/01/31" gmp.bi has the following description.
declare sub mpz_div alias "__gmpz_fdiv_q"(byval as mpz_ptr, byval as mpz_srcptr, byval as mpz_srcptr)
For this reason 'mpz_ div (@ answer, @ mn 1, @ mn 2)' did not result in an error.

I appreciate your efforts and your aid.
Makoto WATANABE
Posts: 171
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: new header file GMP

Postby Makoto WATANABE » Nov 30, 2016 3:38

Hi dodicat

If it is possible, I think it is beautiful visually that function results display excluding useless 0 below the decimal point.

Currently,
Sqrroot ("1") prints 1.000000000000000000,
Divide ("10", "2") prints 5.00000000000000000000.

Just as power ("1", "0.5") displays only 1, I am glad if functions not display meaningless 0s.
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Nov 30, 2016 11:50

Hi Makoto WATANABE

Those two functions in the string overload section had not been properly trimmed.
Thanks for finding this.
But here they are now:

Code: Select all

Function Sqrroot(number As String,decimals As Uinteger=PRECISION) As String'precision parameter
    if instr(number,"-") then exit function
    Dim As __mpf_struct num,FloatAnswer
    Dim As Integer LN=Len(number)
    mpf_init2(@num,4*Ln):mpf_init2(@FloatAnswer,4*Ln)
    mpf_set_str(@num,number,10)
    mpf_sqrt( @FloatAnswer,@num)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function
'precision parameter
Function divide(number1 As String,number2 As String,decimals As Uinteger=PRECISION) As String
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),Ln
    If Ln1>=Ln2 Then  Ln=Ln1 Else Ln=Ln2
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2( @num1,4*(Ln+1) )
    mpf_init2( @num2,4*(Ln+1) )
    mpf_init2(@Floatanswer,4*(Ln+1)+4*decimals)
    mpf_set_str( @num1,number1,10)
    mpf_set_str( @num2,number2,10)
    mpf_div(@Floatanswer,@num1,@num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer)
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: new header file GMP

Postby frisian » Nov 30, 2016 22:00

Makoto WATANABE wrote:Dear frisian
Dear dodicat

I think that your programs (test_gmp.bas and dodicat's own stuff) show how to use GMP in FreeBasic plainly.
I would like to translate your programs into Japanese and introduce them to Japanese people on my website.
Please consent to this.

Makoto WATANABE
You have my consent for all my posting on this forum to use them and my posting on Rosetta Code (under the name frisian).
Please by aware of the fact that only a small portion of the posting is by me others have also made contributions.
Makoto WATANABE
Posts: 171
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: new header file GMP

Postby Makoto WATANABE » Dec 01, 2016 14:35

Dear frisian

Thank you for your consent.
I will learn and understand GMP and then I will translate your program into Japanese.
I thank all contributors.

Thank you for teaching me the site Rosetta Code. I was overwhelmed by programs of huge numbers .
Makoto WATANABE
Posts: 171
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: new header file GMP

Postby Makoto WATANABE » Dec 01, 2016 15:47

Dear dodicat

Thank you very much for your prompt and accurate answers every time.
I was able to guess that two lines were added to the program.
However, I did not notice changing "Return Trim(outtext)" to "Return Trim(outtxt)".
Please forgive my stupid question.


additional request.

I called these functions more than 5,000,000 times, this program ended abnormally.
I think that memory leak is the cause.
If these functions can clear memory every time , please teach me how to do it.
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Dec 01, 2016 22:11

I repaired a leak in _exp().

I have looped all the functions, you can check in your Resource Monitor.
Press <esc> to exit the loop.

Code: Select all


'1 December 2016
#Include once "gmp.bi"
Type mpf_t As  __mpf_struct
'approx list
'equals,greater,less,absolute
'sin,cos,tan,logtaylor,log,exp,power,atn,acos,asin,greater,equals,less
'absolute,Pi_ui
'_mod,_div
Dim Shared As Ulongint PRECISION
'========= Just in case you forget to set_precision ==========
precision=60
mpf_set_default_prec( PRECISION*4 )
'========================================================

Sub set_precision(n As Uinteger)
    PRECISION=n
    mpf_set_default_prec( PRECISION*4 )
End Sub

Function equals Overload(a As mpf_t,b As mpf_t) As Integer
    If Mpf_cmp(@a,@b) = 0 Then Return -1
End Function

Function greater Overload(a As mpf_t,b As mpf_t) As Integer 'a>b
    If equals(a,b) Then Return 0
    Dim As mpf_t Ab,diff
    mpf_init(@Ab)
    mpf_init(@diff)
    mpf_sub(@diff,@b,@a)
    mpf_abs(@Ab,@diff)
    If mpf_cmp(@Ab,@diff)=0 Then Return 0
    Return -1
End Function

Function less Overload(a As mpf_t,b As mpf_t) As Integer 'a>b
    If equals(a,b) Then Return 0
    If greater(a,b) Then Return 0
    Return -1
End Function

Function Absolute Overload(a As mpf_t) As  mpf_t
    Dim As mpf_t Ab
    mpf_init(@Ab)
    mpf_abs(@Ab,@a)
    Return Ab
End Function

Function Pi_ui Overload(places As Uinteger) As mpf_t
    Dim As __mpf_struct a,b,t,p,aa,bb,tt,pp,pi
    mpf_init2( @a, 4*places)
    mpf_init2( @b, 4*places)
    mpf_init2( @t, 4*places)
    mpf_init2( @p, 4*places)
    mpf_init2( @aa,4*places)
    mpf_init2( @bb,4*places)
    mpf_init2( @tt,4*places)
    mpf_init2( @pp,4*places)
    mpf_init2( @pi,4*places)
    mpf_set_str( @a,"1",10)
    mpf_set_str( @b,"2",10):mpf_sqrt( @b, @b )
    mpf_set_str( @t,".25",10)
    mpf_set_str( @p,"1",10)
    mpf_ui_div( @b,1,@b)
    Do
        mpf_add( @aa,  @a,  @b )
        mpf_div_ui( @aa, @aa , 2 )
        mpf_mul( @bb, @a, @b )
        mpf_sqrt( @bb, @bb )
        mpf_sub( @tt, @a, @aa )
        mpf_mul(@tt,@tt,@tt)
        mpf_mul( @tt, @tt, @p )
        mpf_sub( @tt, @t, @tt )
        mpf_mul_ui( @pp, @p, 2 )
        mpf_swap( @a, @aa )
        mpf_swap( @b, @bb )
        mpf_swap( @t, @tt )
        mpf_swap( @p, @pp )
    Loop Until  Mpf_cmp(@a,@aa) = 0
    mpf_add( @pi, @a, @b )
    mpf_mul(@pi,@pi,@pi)
    mpf_div_ui( @pi, @pi, 4 )
    mpf_div( @pi, @pi, @t )
    Return pi
End Function

Function _sin Overload(x As mpf_t) As mpf_t
    Dim As mpf_t inv,XX,Term,Accum,_x,p,temp2,fac
    mpf_init(@_x)
    mpf_set(@_x,@x)
    Dim As mpf_t pi2,circ,Ab
    mpf_init(@circ)
    mpf_init(@Ab)
    pi2=Pi_ui(Cuint(20))
    mpf_mul_ui(@circ,@pi2,2)
    mpf_abs(@Ab,@x)
    If greater(Ab,circ) Then
        '======== CENTRALIZE ==============
        'floor/ceil to centralize
        Dim As mpf_t tmp,tmp2
        mpf_init(@tmp2)
        mpf_init(@tmp)
        If precision>20 Then
            pi2=pi_ui(precision)
        End If
        mpf_mul_ui(@pi2,@pi2,2) 'got 2*pi
        mpf_div(@tmp,@_x,@pi2)
        mpf_set(@tmp2,@tmp)
        mpf_trunc(@tmp,@tmp)     'int part
        mpf_sub(@tmp,@tmp2,@tmp) 'frac part
        mpf_mul(@tmp,@tmp,@pi2)
        mpf_set(@_x,@tmp)
    End If
    '==================================
    Dim As Integer sign(3):sign(3)=1
    Dim As Integer c=1
    mpf_init(@XX)
    mpf_init(@Term)
    mpf_init(@Accum)
    mpf_init(@p)
    mpf_init(@fac)
    mpf_init(@temp2)
    mpf_init_set(@accum,@_x)
    mpf_init_set_str(@fac,"1",10)
    mpf_init_set(@p,@_x)
    mpf_mul(@XX,@_x,@_x)
    Do
        c=c+2
        Mpf_set(@temp2,@accum)
        mpf_mul_ui(@fac,@fac,c*(c-1))
        mpf_mul(@p,@p,@XX)
        mpf_div(@term,@p,@fac)
        If sign(c And 3) Then
            mpf_sub(@Accum,@temp2,@Term)
        Else
            mpf_add(@Accum,@temp2,@Term)
        End If
    Loop Until  Mpf_cmp(@accum,@temp2) = 0 
    Return accum
End Function
Function _cos Overload(x As mpf_t) As mpf_t
    Dim As mpf_t inv,XX,Term,Accum,_x,p,temp2,fac
    mpf_init(@_x)
    mpf_set(@_x,@x)
    Dim As mpf_t pi2,circ,AB
    mpf_init(@circ)
    mpf_init(@Ab)
    pi2=Pi_ui(Cuint(20))
    mpf_mul_ui(@circ,@pi2,2)
    mpf_abs(@Ab,@x)
    If greater(Ab,circ) Then
        '======== CENTRALIZE ==============
        'floor/ceil to centralize
        Dim As mpf_t tmp,tmp2
        mpf_init(@tmp2)
        mpf_init(@tmp)
        If precision>20 Then
            pi2=pi_ui(precision)
        End If
        mpf_mul_ui(@pi2,@pi2,2) 'got 2*pi
        mpf_div(@tmp,@_x,@pi2)
        mpf_set(@tmp2,@tmp)
        mpf_trunc(@tmp,@tmp)     'int part
        mpf_sub(@tmp,@tmp2,@tmp) 'frac part
        mpf_mul(@tmp,@tmp,@pi2)
        mpf_set(@_x,@tmp)
    End If
    '==================================
    Dim As Integer sign(3):sign(2)=1
    Dim As Integer c
    mpf_init(@XX)
    mpf_init(@Term)
    mpf_init(@Accum)
    mpf_init(@p)
    mpf_init(@fac)
    mpf_init(@temp2)
    mpf_init_set_str(@accum,"1",10)
    mpf_init_set_str(@fac,"1",10)
    mpf_init_set_str(@p,"1",10)
    mpf_mul(@XX,@_x,@_x)
    Do
        c=c+2
        Mpf_set(@temp2,@accum)
        mpf_mul_ui(@fac,@fac,c*(c-1))
        mpf_mul(@p,@p,@XX)
        mpf_div(@term,@p,@fac)
        If sign(c And 3) Then
            mpf_sub(@Accum,@temp2,@Term)
        Else
            mpf_add(@Accum,@temp2,@Term)
        End If
    Loop Until  Mpf_cmp(@accum,@temp2) = 0 
    Return accum
End Function
Function _tan Overload(x As mpf_t) As mpf_t
    Dim As mpf_t s,c,_x,ans
    mpf_init(@ans)
    mpf_init(@_x)
    mpf_set(@_x,@x)
    s=_sin(_x)
    c=_cos(_x)
    mpf_div(@ans,@s,@c)
    Return ans
End Function
Function _logTaylor(x As mpf_t) As mpf_t
    'taylor series
    '====================Log Guard==================
    Dim As mpf_t g,zero
    mpf_init(@g)
    mpf_set(@g,@x)
    mpf_init(@zero)
    mpf_init_set_str(@zero,"0",10)
    mpf_abs(@g,@g)
    If  Mpf_cmp(@g,@x) <> 0 Then  Exit Function
    If Mpf_cmp(@x,@zero) = 0 Then  Exit Function
    '=============================================
    Dim As Integer invflag
    Dim As  mpf_t Inv,XX,Term,Accum,strC,_x,tmp,tmp2
    Dim As mpf_t T,B,one,Q,two
    mpf_init(@two)
    mpf_init(@XX)
    mpf_init(@Q)
    mpf_init(@inv)
    mpf_init(@tmp)
    mpf_init(@tmp2)
    mpf_init(@accum)
    mpf_init(@term)
    mpf_init(@T)
    mpf_init(@B)
    mpf_init(@one)
    mpf_init(@_x)
    mpf_init_set_str(@one,"1",10)
    mpf_init_set_str(@two,"2",10)
    mpf_set(@_x,@x)
    If less(x,one) Then
        invflag=1
        mpf_div(@_x,@one,@_x)
    End If
    mpf_sub(@T,@_x,@one)
    mpf_add(@B,@_x,@one)
    mpf_div(@accum,@T,@B)
    mpf_div(@Q,@T,@B)
    Mpf_set(@tmp,@Q)
    Mpf_mul(@XX,@Q,@Q)
    Dim As Integer c=1
    Do
        c=c+2
        Mpf_set(@tmp2,@tmp)
        mpf_mul(@Q,@Q,@XX)
        mpf_div_ui(@term,@Q,c)
        mpf_add(@Accum,@tmp,@Term)
        Mpf_swap(@tmp,@Accum)
    Loop Until Mpf_cmp(@tmp,@tmp2) = 0
    mpf_mul(@accum,@accum,@two)
    If invflag Then
        Dim As mpf_t minus1
        mpf_init(@minus1)
        mpf_init_set_str(@minus1,"-1",10)
        mpf_mul(@accum,@minus1,@accum)
        Return accum
    End If
    Return accum
End Function
Function _log Overload(x As mpf_t) As mpf_t
    '====================Log Guard==================
    Dim As mpf_t g=x,zero
    mpf_init(@zero)
    mpf_init_set_str(@zero,"0",10)
    mpf_abs(@g,@g)
    If  Mpf_cmp(@g,@x) <> 0 Then  Exit Function
    If Mpf_cmp(@x,@zero) = 0 Then  Exit Function
    '=============================================
    Dim As mpf_t approx,ans,logx,factor
    mpf_init(@approx)
    Mpf_set(@approx,@x)
    mpf_init(@factor)
    mpf_init_set_str(@factor,"8",10)
    mpf_init(@ans)
    mpf_sqrt(@approx,@approx)
    mpf_sqrt(@approx,@approx)
    mpf_sqrt(@approx,@approx)
    logx=_logTaylor(approx)
    mpf_mul(@ans,@factor,@logx)
    Return ans
End Function
Function _exp Overload(x As mpf_t) As mpf_t
    'taylor series
    Dim As  mpf_t fac,_x,temp2,accum,strc,p,term
    mpf_init(@fac)
    mpf_init(@_x)
    mpf_init(@temp2)
    mpf_init(@accum)
    mpf_init(@strc)
    mpf_init(@p)
    mpf_init(@term)
    mpf_init_set_str(@fac,"1",10)
    mpf_set(@_x,@x)
    mpf_init_set_str(@p,"1",10)'_x
    mpf_init_set_str(@accum,"1",10)
    Dim As Integer c
    Do
        c=c+1
        Mpf_set(@temp2,@accum)
        mpf_set_str(@strC,Str(c),10) '''leak was here
        mpf_mul(@fac,@fac,@strc)
        mpf_mul(@p,@p,@_x)
        mpf_div(@term,@p,@fac)
        mpf_add(@Accum,@temp2,@Term)
    Loop Until Mpf_cmp(@accum,@temp2) = 0
    Return accum
End Function
Function power Overload(a As mpf_t,p As mpf_t) As mpf_t
    'a^p= exp(p*log(a))
    '====================Power Guard==================
    Dim As mpf_t g,zero
    mpf_init(@g)
    Mpf_set(@g,@a)
    mpf_init(@zero)
    mpf_init_set_str(@zero,"0",10)
    mpf_abs(@g,@g)
    If  Mpf_cmp(@g,@a) <> 0 Then  Exit Function
    If Mpf_cmp(@a,@zero) = 0 Then  Exit Function
    '=============================================
    Dim As mpf_t loga,product,ans
    mpf_init(@product)
    loga=_log(a)
    mpf_mul(@product,@p,@loga)
    ans=_exp(product)
    Return ans
End Function
Function _Atn Overload(x As mpf_t) As mpf_t
    #macro ArctanTaylor(decnum)
    mpf_init(@Inv)
    mpf_init(@XX)
    mpf_init(@Term)
    mpf_init(@Accum)
    mpf_init(@strC)
    mpf_init(@_x)
    mpf_init(@mt)
    mpf_init(@mt2)
    mpf_init(@p)
    Mpf_set(@mt,@decnum)
    Mpf_set(@_x,@decnum)
    Mpf_set(@p,@decnum)
    mpf_mul(@XX,@_x,@_x)
    Do
        c=c+2
        Mpf_set(@mt2,@mt)
        mpf_set_str(@strC,Str(c),10)
        mpf_mul(@p,@p,@XX)
        mpf_div(@Term,@p,@strc)
        If sign(c And 3) Then
            mpf_sub(@Accum,@mt,@Term)
        Else
            mpf_add(@Accum,@mt,@Term)
        End If
        Mpf_swap(@mt,@Accum)
    Loop Until  Mpf_cmp(@mt,@mt2) = 0
    #endmacro
    Dim As Integer sign(3):sign(3)=1
    Dim As Uinteger c=1
    Dim As mpf_t Inv,XX,Term,Accum,_one,strC,_x,mt,mt2,p
    Dim As mpf_t _temp,one,_temp2,factor
   
    mpf_init(@_temp)
    mpf_init(@one)
    mpf_init(@factor)
    mpf_init(@_temp2)
    mpf_set(@_temp2,@x)
    mpf_init_set_str(@one,"1",10)
    Dim As Integer limit=16
    Dim As String P2=Str(2^limit)
    mpf_init_set_str(@factor,p2,10)
    For z As Integer=1 To limit
        mpf_mul(@_temp,@_temp2,@_temp2)
        mpf_add(@_temp,@_temp,@one)
        mpf_sqrt(@_temp,@_temp)
        mpf_add(@_temp,@_temp,@one)
        mpf_div(@_temp,@_temp2,@_temp)
        Mpf_set(@_temp2,@_temp)
    Next z
    ArctanTaylor(_temp)
    mpf_mul(@mt,@factor,@mt)
    Return mt
End Function
Function _Acos Overload(x As mpf_t) As mpf_t
    Dim As mpf_t  one,minusone,two,atn1,tail,T,B,term1,atnterm1,ans',_x,temp
    'ARCCOS = ATN(-x / SQR(-x * x + 1)) + 2 * ATN(1)
    '============= ARCCOS GUARD =========
    Var num= mpf_get_d(@x)
    If num>1 Then Exit Function
    If num<-1 Then Exit Function
    '========================
    mpf_init(@one)
    mpf_init(@two)
    mpf_init(@minusone)
    mpf_init(@tail)
    mpf_init(@T)
    mpf_init(@B)
    mpf_init(@term1)
    mpf_init(@ans)
    mpf_init_set_str(@one,"1",10)
    mpf_init_set_str(@minusone,"-1",10)
    mpf_init_set_str(@two,"2",10)
    atn1=_ATN(one)
    mpf_mul(@tail,@two,@atn1)  '2*atn(1)
    mpf_mul(@T,@minusone,@x)   '-x
    mpf_mul(@B,@x,@x) 'x*x
    If Mpf_cmp(@B,@one) = 0 Then
        'for 1 and -1 
        If mpf_cmp(@x,@minusone)=0 Then
            Dim As mpf_t four
            mpf_init(@four)
            mpf_init_set_str(@four,"4",10)
            mpf_mul(@four,@four,@atn1)
            Return four
        Else
            Dim As mpf_t zero
            mpf_init(@zero)
            mpf_init_set_str(@zero,"0",10)
            Return zero
        End If
    End If
    mpf_sub(@B,@one,@B)        '1-x*x
    mpf_sqrt(@B,@B)            'sqr(1-x*x)
    mpf_div(@term1,@T,@B)
    atnterm1=_ATN(term1)
    mpf_add(@ans,@atnterm1,@tail)
    Return ans
End Function
Function _Asin Overload(x As mpf_t) As mpf_t
    ' ARCSIN = ATN(x / SQR(-x * x + 1))
    '============= ARCSIN GUARD =========
    Var num= mpf_get_d(@x)
    If num>1 Then Exit Function
    If num<-1 Then Exit Function
    '========================
    Dim As mpf_t  one,T,B,term1,atnterm1,minusone
    mpf_init(@minusone)
    mpf_init(@one)
    mpf_init(@T)
    mpf_init(@B)
    mpf_init(@term1)
    mpf_init_set_str(@one,"1",10)
    mpf_init_set_str(@minusone,"-1",10)
    mpf_set(@T,@x)
    'T=x
    mpf_mul(@B,@x,@x)          'x*x
    'for 1 and -1
    If Mpf_cmp(@B,@one) = 0 Then
        Dim As mpf_t two,atn1
        mpf_init(@two)
        mpf_init_set_str(@two,"2",10)
        atn1=_atn(one)
        If mpf_cmp(@x,@minusone)=0 Then
            mpf_mul(@two,@two,@atn1)
            mpf_mul(@two,@two,@minusone)
            Return two
        Else
            mpf_mul(@two,@two,@atn1)
            Return two
        End If
    End If
    mpf_sub(@B,@one,@B)        '1-x*x
    mpf_sqrt(@B,@B)            'sqr(1-x*x)
    mpf_div(@term1,@T,@B)
    atnterm1=_ATN(term1)
    Return atnterm1
End Function


'===========================================================================
'=======================   OVERLOADS  FOR STRINGS ===============================

Dim Shared As Zstring * 100000000 outtext

Function Pi_ui Overload(places As Integer) As String
    Dim As Mpf_t ans
    Var pl=Cuint(places)
    ans=pi_ui(pl)
    gmp_sprintf( @outtext,"%." & pl & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _sin Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_sin(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _cos Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_cos(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _tan Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_tan(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _log Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_log(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _exp Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_exp(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
   
    Return Trim(outtxt)
End Function

Function power Overload(a As String,p As String) As String
    Dim As Mpf_t _x,ans,pow
    mpf_init(@_x)
    mpf_init_set_str(@_x,a,10)
    mpf_init(@pow)
    mpf_init_set_str(@pow,p,10)
    ans=power(_x,pow)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Atn Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_Atn(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Acos Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_Acos(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Asin Overload(x As String) As String
    Dim As Mpf_t _x,ans
    mpf_init(@_x)
    mpf_init_set_str(@_x,x,10)
    ans=_Asin(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function


Function factorial(n As Uinteger) As String 'Automatic precision
    Dim As __mpz_struct Intanswer
    mpz_init2( @Intanswer,0)
    mpz_set_str( @Intanswer,"",10)
    mpz_fac_ui(@Intanswer,n)
    gmp_sprintf( @outtext,"%Zi", @Intanswer )
    Return Trim(outtext)
End Function

Function _mod(n1 As String,n2 As String) As String
    Dim As __mpz_struct answer,mn1,mn2
    mpz_init2( @answer,0)
    mpz_init2( @mn1,0)
    mpz_init2( @mn2,0)
    mpz_init_set_str( @answer,"",10)
    mpz_init_set_str( @mn1,n1,10)
    mpz_init_set_str( @mn2,n2,10)
    mpz_mod(@answer,@mn1,@mn2)
    gmp_sprintf( @outtext,"%Zi", @answer )
    Return Trim(outtext)
End Function

Function _div(n1 As String,n2 As String) As String
    Dim As __mpz_struct answer,mn1,mn2
    mpz_init2( @answer,0)
    mpz_init2( @mn1,0)
    mpz_init2( @mn2,0)
    mpz_init_set_str( @answer,"",10)
    mpz_init_set_str( @mn1,n1,10)
    mpz_init_set_str( @mn2,n2,10)
    mpz_div(@answer,@mn1,@mn2)
    gmp_sprintf( @outtext,"%Zi", @answer )
    Return Trim(outtext)
End Function

Function Sqrroot(number As String,decimals As Uinteger=PRECISION) As String'precision parameter
    If Instr(number,"-") Then Exit Function
    Dim As __mpf_struct num,FloatAnswer
    Dim As Integer LN=Len(number)
    mpf_init2(@num,4*Ln):mpf_init2(@FloatAnswer,4*Ln+4*decimals)
    mpf_set_str(@num,number,10)
    mpf_sqrt( @FloatAnswer,@num)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    Return Trim(outtext)
End Function

Function mult(number1 As String,number2 As String) As String'Automatic precision
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2)
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2( @num1,4*(Ln1+Ln2+1) )
    mpf_init2( @num2,4*(Ln1+Ln2+1) )
    mpf_init2(@Floatanswer,4*(Ln1+Ln2+1))
    Ln1=Instr(1,number1,"."):Ln2=Instr(1,number2,".")
    Var decimals=Len(Mid(number1,Ln1+1))+Len(Mid(number2,Ln2+1))+1
    mpf_set_str( @num1,number1,10)
    mpf_set_str( @num2,number2,10)
    mpf_mul(@Floatanswer,@num1,@num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

'precision parameter
Function divide(number1 As String,number2 As String,decimals As Uinteger=PRECISION) As String
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),Ln
    If Ln1>=Ln2 Then  Ln=Ln1 Else Ln=Ln2
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2( @num1,4*(Ln+1) )
    mpf_init2( @num2,4*(Ln+1) )
    mpf_init2(@Floatanswer,4*(Ln+1)+4*decimals)
    mpf_set_str( @num1,number1,10)
    mpf_set_str( @num2,number2,10)
    mpf_div(@Floatanswer,@num1,@num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer)
    Return Trim(outtext)
End Function

Function  Power Overload(number As String,n As Uinteger) As String'automatic precision
    #define dp 3321921
    Dim As __mpf_struct _number,FloatAnswer
    Dim As Ulongint ln=Len(number)*(n)*4
    If ln>dp Then ln=dp
    mpf_init2(@FloatAnswer,ln)
    mpf_init2(@_number,ln) 'or 4*len(number)
    mpf_set_str(@_number,number,10)
    mpf_pow_ui(@Floatanswer,@_number,n)
    gmp_sprintf( @outtext,"%." & Str(n) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function plus(number1 As String,number2 As String) As String'automatic precision
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),decimals,Ln
    If Ln1>=Ln2 Then Ln=Ln1 Else Ln=Ln2
    Ln=ln+1
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2( @num1,4*(Ln1+1) )
    mpf_init2( @num2,4*(Ln2+1) )
    mpf_init2(@Floatanswer,4*(Ln))
    mpf_set_str( @num1,number1,10)
    mpf_set_str( @num2,number2,10)
    Ln1=Instr(1,number1,"."):Ln2=Instr(1,number2,".")
    If Ln1 Or Ln2 Then
        decimals=Len(Mid(number1,Ln1+1))+Len(Mid(number2,Ln2+1))+1
    End If
    mpf_add(@Floatanswer,@num1,@num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function minus(number1 As String,number2 As String) As String'automatic precision
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),decimals,Ln
    If Ln1>=Ln2 Then  Ln=Ln1 Else Ln=Ln2
    Ln=ln+1
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2( @num1,4*(Ln1+1) )
    mpf_init2( @num2,4*(Ln2+1) )
    mpf_init2(@Floatanswer,4*(Ln))
    mpf_set_str( @num1,number1,10)
    mpf_set_str( @num2,number2,10)
    Ln1=Instr(1,number1,"."):Ln2=Instr(1,number2,".")
    If Ln1 Or Ln2 Then
        decimals=Len(Mid(number1,Ln1+1))+Len(Mid(number2,Ln2+1))+1
    End If
    mpf_sub(@Floatanswer,@num1,@num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function
Function Absolute Overload(a As String) As  String
    Dim As __mpf_struct Ab,Floatanswer
    mpf_init2( @FloatAnswer,4*precision )
    mpf_init2( @Ab,4*precision )
    mpf_set_str( @Ab,a,10)
    mpf_abs(@FloatAnswer,@Ab)
    gmp_sprintf( @outtext,"%." & Str(precision) & "Ff",@FloatAnswer )
    Var outtxt=Trim(outtext)
    If Instr(outtxt,".") Then outtxt= Rtrim(outtxt,"0"):outtxt=Rtrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function greater Overload(a As String,b As String) As Integer
    Dim As mpf_t ma,mb
    mpf_init2(@ma,4*precision)
    mpf_init2(@mb,4*precision)
    mpf_set_str( @ma,a,10)
    mpf_set_str( @mb,b,10)
    Return greater(ma,mb)
End Function
Function equals Overload(a As String,b As String) As Integer
    Dim As mpf_t ma,mb
    mpf_init2(@ma,4*precision)
    mpf_init2(@mb,4*precision)
    mpf_set_str( @ma,a,10)
    mpf_set_str( @mb,b,10)
    Return equals(ma,mb)
End Function

Function less Overload(a As String,b As String) As Integer
    If equals(a,b) Then Return 0
    If greater(a,b) Then Return 0
    Return -1
End Function

'======================== TESTS ===============================
''Extern gmp_version Alias "__gmp_version" As Zstring Ptr
Dim As Long counter
Do
    counter+=1
    Cls
    Print "COUNTER "; counter
    Print "GMP version ";*gmp_version
    set_precision(100)
    Print pi_ui(100)
    Print _sin("1")
    Print _cos("1")
    Print _tan("1")
    Print _log("12.88")
    Print _exp("1")
    Print power("5","-.5")
    Print
    Print _asin(".5")
    Print _acos(".5")
    Print _atn("1000")
    Print factorial(50)
    Print sqrroot("2")
    Print mult("123","10000.888")
    Print divide("1.0096","1023",100)
    Print power("2",100)
    Print plus("100","200")
    Print minus("100","200")
    Print absolute("-67")
    Print _mod("19990","444")
    Print _div("19990","444")
    Sleep 100
Loop Until Inkey=Chr(27)
Sleep

'
'


 
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Dec 02, 2016 0:46

I shall clear (using mpf_clear) all the initialized variables in all the functions.

I'll post the functions when done.
This should stop any memory leaks.
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: new header file GMP

Postby frisian » Dec 11, 2016 20:18

I don't know if dodicat is working on his program, but I post my version of his program with some alterations.
I still had the one I had done some time ago so it wasn't that hard. I have not commenting every things.

Code: Select all

'  1 December 2016 - orinal by dodicat
' 11 December 2016 - frisian, added mpf_clear/mpz_clear statements
' changed some code by using GMP code, cleaned up some init/init_set stuff
' reduced the number of big integer/float variables needed

#Include Once "gmp.bi"
Type mpf_t As __mpf_struct
'approx list
'equals,greater,less,absolute
'sin,cos,tan,logtaylor,log,exp,power,atn,acos,asin,greater,equals,less
'absolute,Pi_ui
'_mod,_div

Dim Shared As ULongInt PRECISION
'========= Just in case you forget to set_precision ==========
precision=60
mpf_set_default_prec(PRECISION * 4)
'========================================================

Sub set_precision(n As UInteger)
    PRECISION = n
    mpf_set_default_prec(PRECISION * 4)
End Sub

Function equals Overload(a As mpf_t, b As mpf_t) As Integer
    If Mpf_cmp(@a, @b) = 0 Then Return -1
    Return 0
End Function

Function greater Overload(a As mpf_t, b As mpf_t) As Integer 'a>b
    If mpf_cmp(@a, @b) > 0 Then Return -1
    Return 0
End Function

Function less Overload(a As mpf_t, b As mpf_t) As Integer 'a<b
    If mpf_cmp(@a, @b) < 0 Then Return -1
    Return 0
End Function

Function Absolute Overload(a As mpf_t) As mpf_t
    Dim As mpf_t Ab
    mpf_init(@Ab)
    mpf_abs(@Ab, @a)
    Return Ab
End Function

Function Pi_ui Overload(places As UInteger) As mpf_t
    ' Dim As __mpf_struct a,b,t,p,aa,bb,tt,pp,pi
    Dim As __mpf_struct a, b, t, aa, bb, tt, pi
    mpf_init2(@a, 4*places)
    mpf_init2(@b, 4*places)
    mpf_init2(@t, 4*places)
    ' mpf_init2( @p, 4*places)
    Dim As UInteger p
    mpf_init2(@aa,4*places)
    mpf_init2(@bb,4*places)
    mpf_init2(@tt,4*places)
    ' mpf_init2( @pp,4*places)
    mpf_init2(@pi,4*places)
    mpf_set_ui(@a, 1)
    mpf_set_ui(@b, 2) : mpf_sqrt(@b, @b)
    mpf_set_str(@t,".25",10)
    ' mpf_set_str(@p,"1",10)
    mpf_ui_div(@b,1,@b)
    Do
        mpf_add(@aa, @a, @b)
        ' mpf_div_ui(@aa, @aa, 2)
        mpf_div_2exp(@aa, @aa, 1)
        mpf_mul(@bb, @a, @b)
        mpf_sqrt(@bb, @bb)
        mpf_sub(@tt, @a, @aa)
        mpf_mul(@tt,@tt,@tt)
        ' mpf_mul(@tt, @tt,@p)
        mpf_mul_2exp(@tt, @tt, p)
        p += 1
        mpf_sub(@tt, @t, @tt)
        ' mpf_mul_ui(@pp, @p, 2)
        mpf_swap(@a, @aa)
        mpf_swap(@b, @bb)
        mpf_swap(@t, @tt)
        ' mpf_swap(@p, @pp)
    Loop Until  Mpf_cmp(@a, @aa) = 0
    mpf_add(@pi, @a, @b)
    mpf_mul(@pi, @pi, @pi)
    ' mpf_div_ui(@pi, @pi, 4)
    mpf_div_2exp(@pi, @pi, 2)
    mpf_div(@pi, @pi, @t)
    ' remove big int's from memory
    mpf_clear(@a) : mpf_clear(@aa)
    mpf_clear(@b) : mpf_clear(@bb)
    mpf_clear(@t) : mpf_clear(@tt)
    Return pi
End Function

Function _sin Overload(x As mpf_t) As mpf_t
    Dim As mpf_t XX, Term, Accum, _x, temp2, fac, pi2
    mpf_init_set(@_x, @x)
    mpf_init(@pi2)
    mpf_init(@temp2)
    If mpf_cmp_d(@x, 6.283185) >= 0 OrElse mpf_cmp_ui(@x, 0) < 0 Then
        '======== CENTRALIZE ==============
        'floor/ceil to centralize
        pi2 = Pi_ui(precision)
        mpf_mul_2exp(@pi2, @pi2, 1)   ' pi2 = pi * 2
        mpf_div(@temp2, @_x, @pi2)    ' temp2 = _x / pi2
        mpf_floor(@temp2, @temp2)     ' temp2 = floor(temp2) 'rounds temp2 down towards minus infinity
        mpf_mul(@temp2, @temp2, @pi2) ' temp2 = temp2 * p2
        mpf_sub(@_x, @_x, @temp2)     ' _x = _x - temp2 (_x = _x mod 2*pi)
    End If
    '==================================
    ' based on Richard methode for sin/cos in squares
    Dim As Integer c = 1
    mpf_init(@XX)
    mpf_init(@Term)
    mpf_init_set(@accum, @_x)
    mpf_init_set_ui(@fac, 1)
    mpf_mul(@XX, @_x, @_x)
    mpf_neg(@XX, @XX) ' make XX negative
    Do
        c = c + 2
        Mpf_swap(@temp2, @Accum)
        mpf_mul_ui(@fac, @fac, c)      ' avoid an overflow when c > 65536
        mpf_mul_ui(@fac, @fac, (c -1)) ' split in two separate multiply's
        mpf_mul(@_x , @_x, @XX)        ' _x alternates between negative an positive
        mpf_div(@Term, @_x, @fac)
        mpf_add(@Accum, @temp2, @term) ' temp2 and accum are swapped, temp2 holds the previous content of accum
    Loop Until  Mpf_cmp(@Accum, @temp2) = 0
    ' clean up
    mpf_clear(@XX) : mpf_clear(@Term)  : mpf_clear(@fac)
    mpf_clear(@_x) : mpf_clear(@temp2) : mpf_clear(@pi2)

    Return accum
End Function

Function _cos Overload(x As mpf_t) As mpf_t
    Dim As mpf_t XX, Term, Accum, _x, p, temp2, fac, pi2
    mpf_init_set(@_x,@x)
    mpf_init(@pi2)
    mpf_init(@temp2)
    If mpf_cmp_d(@x, 6.283185) >= 0 OrElse mpf_cmp_ui(@x, 0) < 0 Then
        '======== CENTRALIZE ==============
        'floor/ceil to centralize
        pi2 = Pi_ui(precision)
        mpf_mul_2exp(@pi2, @pi2, 1)   ' pi2 = pi * 2
        mpf_div(@temp2, @_x, @pi2)    ' temp2 = _x / pi2
        mpf_floor(@temp2, @temp2)     ' temp2 = floor(temp2) 'rounds temp2 down towards minus infinity
        mpf_mul(@temp2, @temp2, @pi2) ' temp2 = temp2 * p2
        mpf_sub(@_x, @_x, @temp2)     ' _x = _x - temp2 (_x = _x mod 2*pi)
    End If
    '==================================
    ' based on Richard methode for sin/cos in squares
    Dim As Integer c
    mpf_init(@XX)
    mpf_init(@Term)
    mpf_init_set_ui(@Accum, 1)
    mpf_init_set_ui(@fac, 1)
    mpf_init_set_ui(@p, 1)
    mpf_mul(@XX, @_x, @_x)
    mpf_neg(@XX, @XX)
    Do
        c += 2
        Mpf_swap(@temp2, @accum)
        mpf_mul_ui(@fac, @fac, c)
        mpf_mul_ui(@fac, @fac, (c-1))
        mpf_mul(@p, @p, @XX)
        mpf_div(@term, @p, @fac)
        mpf_add(@accum, @temp2, @term)
    Loop Until Mpf_cmp(@accum, @temp2) = 0
    ' clean up
    mpf_clear(@XX) : mpf_clear(@Term)  : mpf_clear(@fac)
    mpf_clear(@_x) : mpf_clear(@temp2) : mpf_clear(@pi2)
    mpf_clear(@p)

    Return accum
End Function

Function _tan Overload(x As mpf_t) As mpf_t
    Dim As mpf_t s, c, ans
    mpf_init(@ans)
    s = _sin(x)
    c = _cos(x)
    mpf_div(@ans, @s, @c)
    mpf_clear(@c) : mpf_clear(@s)

    Return ans
End Function

Function _logTaylor(x As mpf_t) As mpf_t
    'taylor series
    '====================Log Guard==================
    If mpf_cmp_ui(@x, 0) <= 0 Then Exit Function ' exit if x = 0 or x = negative
    '===============================================
    Dim As Integer invflag
    Dim As Mpf_t Q, tmp, _x, accum, term, XX
    mpf_init(@XX)
    mpf_init(@Q)
    mpf_init(@tmp)
    mpf_init(@accum)
    mpf_init(@term)
    mpf_init_set(@_x, @x)
    If mpf_cmp_ui(@_x, 1) < 0 Then
        invflag = 1
        mpf_ui_div(@_x, 1, @_x)
    End If
    mpf_sub_ui(@tmp, @_x, 1)
    mpf_add_ui(@Q, @_x, 1)     ' q = b
    mpf_div(@accum,@tmp, @Q)
    Mpf_set(@Q , @accum)
    Mpf_mul(@XX, @Q, @Q)
    Dim As Integer c=1
    Do
        c += 2
        Mpf_swap(@tmp,@accum)
        mpf_mul(@Q, @Q, @XX)
        mpf_div_ui(@term, @Q, c)
        mpf_add(@Accum, @tmp, @Term)
    Loop Until Mpf_cmp(@tmp, @accum) = 0
    mpf_mul_2exp(@accum, @accum, 1)
    If invflag Then
        mpf_neg(@accum, @accum)
    End If
    mpf_clear(@_x) : mpf_clear(@tmp) : mpf_clear(@Q)
    mpf_clear(@XX) : mpf_clear(@term)

    Return accum
End Function

Function _log Overload(x As mpf_t) As mpf_t
    /'
         '====================Log Guard==================
         If Mpf_cmp_ui(@x, 0) <= 0 Then Exit Function ' exit if x = 0 or x is negative
         '===============================================
         Dim As mpf_t approx, ans, logx   ',factor
         Mpf_init_set(@approx, @x)
         mpf_init(@ans)
         mpf_sqrt(@approx, @approx) ' 1
         mpf_sqrt(@approx, @approx) ' 2
         mpf_sqrt(@approx, @approx) ' 3
         logx = _logTaylor(approx)
         mpf_mul_2exp(@ans, @logx, 3)
         ' clean up
         mpf_clear(@approx) : mpf_clear(@logx)
         '/
    '====================Log Guard==================
    If Mpf_cmp_ui(@x, 0) <= 0 Then Exit Function ' exit if x = 0 or x is negative
    '===============================================
    Dim As mpf_t approx, ans, logx   ',factor
    Mpf_init_set(@approx, @x)
    mpf_init(@ans)
    Dim As Integer c
    While mpf_cmp_d(@approx, 1.25) > 0
        mpf_sqrt(@approx, @approx)
        c += 1
    Wend
    logx = _logTaylor(approx)
    mpf_mul_2exp(@ans, @logx, c)
    ' clean up
    mpf_clear(@approx) : mpf_clear(@logx)
    Return ans
End Function

Function _exp Overload(x As mpf_t) As mpf_t
    'taylor series
    Dim As mpf_t fac, temp2, accum, p, term
    mpf_init(@temp2)
    mpf_init(@term)
    mpf_init_set_ui(@fac, 1)
    mpf_init_set_ui(@p, 1)
    mpf_init_set_ui(@accum, 1)
    Dim As Integer c
    Do
        c += 1
        Mpf_swap(@temp2, @accum)
        mpf_mul_ui(@fac, @fac, c)
        mpf_mul(@p, @p, @x)
        mpf_div(@term, @p, @fac)
        mpf_add(@Accum, @temp2, @Term)
    Loop Until Mpf_cmp(@accum, @temp2) = 0
    ' clean up
    mpf_clear(@temp2) : mpf_clear(@fac)
    mpf_clear(@term)  : mpf_clear(@p)

    Return accum
End Function

Function power Overload(a As mpf_t,p As mpf_t) As mpf_t
    'a^p= exp(p*log(a))
    '====================Power Guard==================
    If Mpf_cmp_ui(@a, 0) <= 0 Then Exit Function ' exit if x = 0 or x is negative
    '=================================================
    Dim As mpf_t loga, product, ans
    mpf_init(@product)
    loga = _log(a)
    mpf_mul(@product, @p, @loga)
    ans = _exp(product)
    'clean up
    mpf_clear(@loga) : mpf_clear(@product)

    Return ans
End Function

Function _Atn Overload(x As mpf_t) As mpf_t
    #Macro ArctanTaylor(decnum)
        mpf_init(@XX)
        mpf_init(@Term)
        mpf_init(@Accum)
        mpf_init_set(@mt, @decnum)
        mpf_init_set(@p, @decnum)
        mpf_mul(@XX, @mt, @mt)
        mpf_neg(@XX, @XX)
        Do
            c += 2
            mpf_mul(@p, @p, @XX)
            mpf_div_ui(@Term, @p, c)
            mpf_add(@Accum, @mt, @Term)
            Mpf_swap(@mt, @Accum)
        Loop Until Mpf_cmp(@mt, @accum) = 0
    #EndMacro
    Dim As UInteger c = 1
    Dim As mpf_t XX, Term, Accum, mt, p, _temp, _temp2
    mpf_init(@_temp)
    mpf_init_set(@_temp2, @x)
    Dim As Integer limit = 16
    For z As Integer = 1 To limit
        mpf_mul(   @_temp, @_temp2, @_temp2)
        mpf_add_ui(@_temp ,@_temp, 1)
        mpf_sqrt(  @_temp, @_temp)
        mpf_add_ui(@_temp, @_temp, 1)
        mpf_div(   @_temp, @_temp2, @_temp)
        Mpf_swap(  @_temp, @_temp2)
    Next z
    ArctanTaylor(_temp)
    mpf_mul_2exp(@mt, @mt, (limit -1))
    mpf_clear(@_temp) : mpf_clear(@_temp2) : mpf_clear(@XX)
    mpf_clear(@accum) : mpf_clear(@term)   : mpf_clear(@p)

    Return mt
End Function

Function _Acos Overload(x As mpf_t) As mpf_t
    'ARCCOS = ATN(-x / SQR(-x * x + 1)) + 2 * ATN(1)
    '============= ARCCOS GUARD =========
    Dim As Mpf_t B : Mpf_init(@B)
    Mpf_mul(@B, @x, @x) 'x*x
    If Mpf_cmp_ui(@B, 1) > 0 Then
        mpf_clear(@B) ' need to clean up B
        Exit Function
    End If
    '====================================
    Dim As Mpf_t atn1, term1, ans
    Mpf_init_set_ui(@term1, 1)
    Mpf_init(@ans)
    atn1=_Atn(term1)
    If Mpf_cmp_ui(@B, 1) = 0 Then
        'for 1 and -1
        If Mpf_cmp_si(@x, -1) = 0 Then
            Mpf_mul_2exp(@ans, @atn1, 2)
        End If
        mpf_clear(@B) : mpf_clear(@atn1) : mpf_clear(@term1)
        ' ans = pi or 0
        Return ans
    End If
    Dim As Mpf_t tail, T, atnterm1
    mpf_init(@tail)
    mpf_init(@T)
    mpf_mul_2exp(@tail, @atn1, 1)  ' 2*atn(1)
    mpf_neg(@T, @x)                ' -x
    'mpf_mul(@B,@x,@x)             ' x*x ' done at the begin
    mpf_ui_sub(@B, 1, @B)          ' 1 - x*x
    mpf_sqrt(@B, @B)               ' sqr(1 - x*x)
    mpf_div(@term1, @T, @B)
    atnterm1 = _Atn(term1)
    mpf_add(@ans, @atnterm1, @tail)
    'clean up
    mpf_clear(@B) : mpf_clear(@atn1) : mpf_clear(@term1)
    mpf_clear(@T) : mpf_clear(@tail) : mpf_clear(@atnterm1)

    Return ans
End Function

Function _Asin Overload(x As mpf_t) As mpf_t
    ' ARCSIN = ATN(x / SQR(-x * x + 1))
    '============= ARCSIN GUARD =========
    Dim As Mpf_t B : Mpf_init(@B)
    Mpf_mul(@B, @x, @x) 'x*x
    If Mpf_cmp_ui(@B, 1) > 0 Then
        mpf_clear(@B)
        Exit Function
    End If
    '====================================
    Dim As mpf_t term1
    mpf_init_set_ui(@term1, 1)
    'for 1 and -1
    If Mpf_cmp_ui(@B, 1) = 0 Then
        Dim As mpf_t atn1
        atn1 = _Atn(term1)
        mpf_mul_2exp(@atn1, @atn1, 1)
        If mpf_cmp_si(@x, -1) = 0 Then
            mpf_neg(@atn1, @atn1)
        End If
        ' clean up
        mpf_clear(@B) : mpf_clear(@term1)
        Return atn1
    End If
    Dim As Mpf_t T, atnterm1
    Mpf_init_set(@T, @x)
    mpf_ui_sub(@B, 1, @B)       '1 - x*x
    mpf_sqrt(@B, @B)            'sqr(1 - x*x)
    mpf_div(@term1, @T, @B)
    atnterm1 = _Atn(term1)
    ' clean up
    mpf_clear(@B) : mpf_clear(@T) : mpf_clear(@term1)

    Return atnterm1

End Function


'===========================================================================
'======================= OVERLOADS FOR STRINGS =============================

Dim Shared As ZString * 100000000 outtext

Function Pi_ui Overload(places As Integer) As String
    Dim As Mpf_t ans
    Var pl=CUInt(places)
    ans=Pi_ui(pl)
    gmp_sprintf(@outtext, "%." & pl & "Ff", @ans )
    mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _sin Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x, x, 10)
    ans = _sin(_x)
    gmp_sprintf(@outtext, "%." & precision & "Ff", @ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _cos Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x,x,10)
    ans = _cos(_x)
    gmp_sprintf(@outtext, "%." & precision & "Ff", @ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _tan Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x,x,10)
    ans = _tan(_x)
    gmp_sprintf( @outtext, "%." & precision & "Ff", @ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _log Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x,x,10)
    ans = _log(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _exp Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x, x, 10)
    ans = _exp(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function power Overload(a As String,p As String) As String
    Dim As Mpf_t _x, ans, pow
    mpf_init_set_str(@_x, a, 10)
    mpf_init_set_str(@pow, p, 10)
    ans = power(_x, pow)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans) : mpf_clear(@pow)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Atn Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x, x, 10)
    ans = _Atn(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Acos Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x, x, 10)
    ans = _Acos(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function _Asin Overload(x As String) As String
    Dim As Mpf_t _x, ans
    mpf_init_set_str(@_x, x, 10)
    ans = _Asin(_x)
    gmp_sprintf( @outtext,"%." & precision & "Ff",@ans )
    mpf_clear(@_x) : mpf_clear(@ans)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function factorial(n As UInteger) As String 'Automatic precision
    Dim As __mpz_struct Intanswer
    mpz_init( @Intanswer)
    mpz_fac_ui(@Intanswer,n)
    gmp_sprintf( @outtext,"%Zi", @Intanswer )
    mpz_clear(@Intanswer)
    Return Trim(outtext)
End Function

Function _mod(n1 As String,n2 As String) As String
    Dim As __mpz_struct answer, mn1, mn2
    mpz_init(@answer)
    mpz_init_set_str(@mn1, n1, 10)
    mpz_init_set_str(@mn2, n2, 10)
    mpz_mod(@answer, @mn1, @mn2)
    gmp_sprintf( @outtext,"%Zi", @answer )
    mpz_clear(@answer) : mpz_clear(@mn1) : mpz_clear(@mn2)
    Return Trim(outtext)
End Function

Function _div(n1 As String,n2 As String) As String
    Dim As __mpz_struct answer, mn1, mn2

    mpz_init(@answer)
    mpz_init_set_str(@mn1, n1, 10)
    mpz_init_set_str(@mn2, n2, 10)
    mpz_div(@answer, @mn1, @mn2)
    gmp_sprintf( @outtext,"%Zi", @answer )
    mpz_clear(@answer) : mpz_clear(@mn1) : mpz_clear(@mn2)
    Return Trim(outtext)
End Function

Function Sqrroot(number As String,decimals As UInteger=PRECISION) As String'precision parameter
    If InStr(number,"-") Then Exit Function
    Dim As __mpf_struct num, FloatAnswer
    Dim As Integer LN = Len(number)
    mpf_init2(@num, 4*Ln) : mpf_init2(@FloatAnswer, 4*Ln+4*decimals)
    mpf_set_str(@num, number, 10)
    mpf_sqrt( @FloatAnswer, @num)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    mpf_clear(@num) : mpf_clear(@FloatAnswer)
    Return Trim(outtext)
End Function

Function mult(number1 As String,number2 As String) As String'Automatic precision
    Dim As Integer Ln1 = Len(number1), Ln2 = Len(number2)
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2(@num1, 4*(Ln1+Ln2+1) )
    mpf_init2(@num2, 4*(Ln1+Ln2+1) )
    mpf_init2(@Floatanswer, 4*(Ln1+Ln2+1))
    Ln1=InStr(1, number1, ".") : Ln2 = InStr(1, number2, ".")
    Var decimals = Len(Mid(number1, Ln1+1))+Len(Mid(number2, Ln2+1))+1
    mpf_set_str(@num1, number1, 10)
    mpf_set_str(@num2, number2, 10)
    mpf_mul(@Floatanswer, @num1, @num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    mpf_clear(@num1) : mpf_clear(@num2) : mpf_clear(@FloatAnswer)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

'precision parameter
Function divide(number1 As String,number2 As String,decimals As UInteger=PRECISION) As String
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),Ln
    If Ln1>=Ln2 Then  Ln=Ln1 Else Ln=Ln2
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2(@num1, 4*(Ln+1) )
    mpf_init2(@num2, 4*(Ln+1) )
    mpf_init2(@Floatanswer, 4*(Ln+1)+4*decimals)
    mpf_set_str(@num1, number1, 10)
    mpf_set_str(@num2, number2, 10)
    mpf_div(@Floatanswer, @num1, @num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer)
    mpf_clear(@num1) : mpf_clear(@num2) : mpf_clear(@FloatAnswer)
    Return Trim(outtext)
End Function

Function power Overload(number As String, n As UInteger) As String'automatic precision
    #Define dp 3321921
    Dim As __mpf_struct _number, FloatAnswer
    Dim As ULongInt ln=Len(number)*(n)*4
    If ln>dp Then ln=dp
    mpf_init2(@FloatAnswer, ln)
    mpf_init2(@_number, ln) 'or 4*len(number)
    mpf_set_str(@_number, number, 10)
    mpf_pow_ui(@Floatanswer, @_number, n)
    gmp_sprintf( @outtext,"%." & Str(n) & "Ff",@FloatAnswer )
    mpf_clear(@_number) : mpf_clear(@FloatAnswer)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function plus(number1 As String,number2 As String) As String'automatic precision
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),decimals,Ln
    If Ln1>=Ln2 Then Ln=Ln1 Else Ln=Ln2
    Ln=ln+1
    Dim As __mpf_struct num1,num2,FloatAnswer
    mpf_init2(@num1, 4*(Ln1+1) )
    mpf_init2(@num2, 4*(Ln2+1) )
    mpf_init2(@Floatanswer, 4*(Ln))
    mpf_set_str(@num1,number1,10)
    mpf_set_str(@num2,number2,10)
    Ln1=InStr(1,number1,"."):Ln2=InStr(1,number2,".")
    If Ln1 Or Ln2 Then
        decimals=Len(Mid(number1,Ln1+1))+Len(Mid(number2,Ln2+1))+1
    End If
    mpf_add(@Floatanswer, @num1, @num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    mpf_clear(@num1) : mpf_clear(@num2) : mpf_clear(@FloatAnswer)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function minus(number1 As String,number2 As String) As String'automatic precision
    Dim As Integer Ln1=Len(number1),Ln2=Len(number2),decimals,Ln
    If Ln1>=Ln2 Then  Ln=Ln1 Else Ln=Ln2
    Ln=ln+1
    Dim As __mpf_struct num1, num2, FloatAnswer
    mpf_init2(@num1, 4*(Ln1+1) )
    mpf_init2(@num2, 4*(Ln2+1) )
    mpf_init2(@Floatanswer, 4*(Ln))
    mpf_set_str(@num1, number1, 10)
    mpf_set_str(@num2, number2, 10)
    Ln1=InStr(1,number1,"."):Ln2=InStr(1,number2,".")
    If Ln1 Or Ln2 Then
        decimals=Len(Mid(number1,Ln1+1))+Len(Mid(number2,Ln2+1))+1
    End If
    mpf_sub(@Floatanswer, @num1, @num2)
    gmp_sprintf( @outtext,"%." & Str(decimals) & "Ff",@FloatAnswer )
    mpf_clear(@num1) : mpf_clear(@num2) : mpf_clear(@FloatAnswer)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function Absolute Overload(a As String) As  String
    Dim As __mpf_struct Ab, Floatanswer
    mpf_init2(@FloatAnswer, 4*precision )
    mpf_init2(@Ab, 4*precision )
    mpf_set_str(@Ab, a, 10)
    mpf_abs(@FloatAnswer, @Ab)
    gmp_sprintf( @outtext,"%." & Str(precision) & "Ff",@FloatAnswer )
    mpf_clear(@Ab) : mpf_clear(@FloatAnswer)
    Var outtxt=Trim(outtext)
    If InStr(outtxt,".") Then outtxt= RTrim(outtxt,"0"):outtxt=RTrim(outtxt,".")
    Return Trim(outtxt)
End Function

Function greater Overload(a As String,b As String) As Integer
    Dim As mpf_t ma, mb
    mpf_init2(@ma, 4*precision)
    mpf_init2(@mb, 4*precision)
    mpf_set_str(@ma, a, 10)
    mpf_set_str(@mb, b, 10)
    Return greater(ma,mb)
End Function

Function equals Overload(a As String,b As String) As Integer
    Dim As mpf_t ma, mb
    mpf_init2(@ma, 4*precision)
    mpf_init2(@mb, 4*precision)
    mpf_set_str(@ma, a, 10)
    mpf_set_str(@mb, b, 10)
    Return equals(ma, mb)
End Function

Function less Overload(a As String,b As String) As Integer
    If equals(a,b) Then Return 0
    If greater(a,b) Then Return 0
    Return -1
End Function

'======================== TESTS ===============================
''Extern gmp_version Alias "__gmp_version" As Zstring Ptr
Dim As Long counter

set_precision(60)
Do
    counter+=1
    Cls
    Print "COUNTER "; counter
    Print "GMP version "; *gmp_version
   ' set_precision(60) 'moved it outside the do loop
    Print Pi_ui(100)
    Print _sin("1")
    Print _cos("1")
    Print _tan("1")
    Print _log("12.88")
    Print _exp("1")
    Print power("5","-.5")
    Print
    Print _Asin(".5")
    Print _Acos(".5")
    Print _Atn("1000")
    Print factorial(50)
    Print Sqrroot("2")
    Print mult("123","10000.888")
    Print divide("1.0096","1023",100)
    Print power("2",100)
    Print plus("100","200")
    Print minus("100","200")
    Print Absolute("-67")
    Print _mod("19990","444")
    Print _div("19990","444")
    Sleep 100
Loop Until InKey=Chr(27)
Sleep
End


Makoto WATANABE
I wrote a litte program to show how thing work with GMP.
Mpz_inits, mpz_clears, mpf_inits, mpf_clears, mpf_inits and mpf_clears do not work.
Mpz_array_init is obsolete and also does not work in FreeBASIC.
It is impossble to mix the three types directly as basic, float = integer / integer.
To do this with GMP the integer's need to be converted to float's.
If possible use swap instead of set, set makes a copy, swap just swap the structure (12 to 24 bytes).

Code: Select all

#Include Once "gmp.bi"
' integer
Dim As __mpz_struct big_integer

mpz_init(@big_integer)
' mpz_init2(big_integer, 128)
mpz_set_ui(@big_integer, 1)
' or mpz_set_ui(big_integer, 3)
' or mpz_set_str(big_integer, "123", 10) ' decimal number
' or mpz_set_str(big_integer, "0F", 16)  ' hexadecimal number
' or init and set combined
' mpz_init_str(big_integer, "1234" , 10)

' 32bit
' set the size for big num floats in bits
' number gets divided by 32 and if mod 32 <> 0 then 1 is added to the result (ceil)
' the value is set to result * 32, 100 \ 32 = 3, 100 mod 32 = 4, result = 4
' value is set to 128
mpf_set_default_prec(100)
' get the size for big num floats and print it
Print "mpf_get_default_prec should return 128, value = "; mpf_get_default_prec

Dim As __mpf_struct big_float
mpf_init(@big_float)  ' uses the default size, size can be set with ' get the size for big num floats and print it
' mpf_init2(big_float, 1000) ' size get set to 1024
mpf_set_d(@big_float, 3.1415)
' of combine init and set
' mpz_init_set_str(@big_float, "1.234", 10)

Dim As __mpq_struct big_rational
mpq_init(@big_rational)
mpq_set_str(@big_rational, "355/113", 10)

'copy rational to float
mpf_set_q(@big_float, @big_rational)
Print
Gmp_printf(!"%.Ff\n", @big_float) 'print big_float as floating point value
Gmp_printf(!"%.Fe\n", @big_float) 'print big_float as scientific value


Print
Gmp_printf(!"%Qd\n", @big_rational) ' as decimal numbers
Gmp_printf(!"in hexadecimal %.Qx\n", @big_rational) ' as hexnumbers


' setting up an array, similar for float and rational numbers
Dim As __mpz_struct big_int(10)
For x As Integer = 0 To 10 ' lbound(big_int) to ubound(big_int)
    ' mpz_init(@big_int(x)
    mpz_init_set_ui(@big_int(x), x)
Next

mpz_clear(@big_integer)
mpf_clear(@big_float)
mpq_clear(@big_rational)

' clearing the array
For x As Integer = 0 To 10 ' lbound(big_int) to ubound(big_int)
    mpz_clear(@big_int(x))
Next

Randomize Timer
' setup the random generator
Dim As __gmp_randstate_struct rnd_seed
gmp_randinit_mt(@rnd_seed) ' in this case the mersenne twister
gmp_randseed_ui(@rnd_seed, Rnd * &HFFFFFFFF) ' seed the random number generator with uinteger

Dim As __mpz_struct big_num
mpz_init_set_str(@big_num, "1234567890111213", 10)
gmp_randseed(@rnd_seed, @big_integer)     ' seed the random number generator with a big_integer

For x As Integer = 0 To 3
    Print x:
    mpz_set_str(@big_num, "1"+String(20,"0"), 10)
    Gmp_printf(!"n = %Zd\n", @big_num) ' start value
    mpz_urandomm(@big_num, @rnd_seed, @big_num) ' return number between 0 and n -1
    Gmp_printf(!"random number = %Zd\n", @big_num) ' print number
    Print
Next

' haven't mastered the floating point part completly
Dim As __mpf_struct big_fl : mpf_init2(@big_fl, 1024)
For x As Integer = 1 To 3
    mpf_urandomb (@big_fl, @rnd_seed, 40)
    Gmp_printf(!"random number = %.Ff\n", @big_fl)
Next

gmp_randclear(@rnd_seed)   ' remove the rnd_seed
mpf_clear(@big_fl)
mpz_clear(@big_num)

Sleep
End
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: new header file GMP

Postby dodicat » Dec 11, 2016 21:23

O.K. Frisian.
I was working on clear in a similar fashion, but got sidetracked.
The leaks have gone, I tested without sleep 100, and let it run for a while.
So perhaps Makoto W. should use your alterations.

So Thanks again.
Makoto WATANABE
Posts: 171
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: new header file GMP

Postby Makoto WATANABE » Dec 15, 2016 10:01

Dear dodicat
Dear frisian

Thanks for your help.
I appreciate your efforts.

I tried frisian's alterations.
I ran a program of "factorization into prime factors" below.
Alterations have dramatically reduced memory consumption.
Also, processing time only took a little more than version using integer type.

However, when I tried to calculate "70,000,005,000,000,007", this program was terminated abnormally when 15 million times repeated the loop .
If any corresponding method is thought about, please teach me it.

Code: Select all

 #Include "gmpFunctionsFrisian+DivIntJP.bas"
 # include "vbcompat.bi"

 Declare Sub STRreplace(ByRef Expression As String, ByRef Find As String, ByRef Replacement As String, ByVal Start As Integer = 1)

 Rem Factorization into Prime factors

 Dim Suuchi As String
 Dim STARTT As Long
 Dim ENDTIME As Long
 Dim Minut As Integer
 Dim A As String
 Dim HANTEI As String
 Dim Hairetsu() As String
 Dim I As Integer
 Dim J As Integer
 Dim Kekka As String
 Dim Counter As Double
Dim  f As Integer 'File number

' Find the first free file number
f = FreeFile

Open "Counter.txt" For Output As #f
If Err>0 Then Print "Error opening the file":End

 'Function used
 'greater,_mod,plus,divide,Sqrroot
 
KURIKAESHI:
set_precision(30)
 
 Cls
 Print "Factorization into Prime factors"
 Print "Please input any integer."
 Print "For example, input 12,319 or 4,294,967,297 and Enter key.
 Print "For example, 99,400,891 or 6,041,375,340 or 123,456,789,013."
 Print "For example, 2,305,843,008,139,952,128 ."
 Print "For example, 70,000,104,900,007 or 70,000,005,000,000,007."
 Print
 Print "exceeds ULongInt: 18,446,744,073,709,551,617 = 274,177 * 67,280,421,310,721 ."
 Print

 I=0
 Kekka="1"
 Counter=0

 Line Input Suuchi
 STRreplace(Suuchi, ",", "")

 STARTT=Val(Left$(Time$,2))*3600+Val(Mid$(Time$,4,2))*60+Val(Right$(Time$,2))

 Cls
 Print Suuchi;"=";
 
Gusu:
   A = "2"
   
Tsugi:
   Counter= Counter+1
   
   If Counter Mod 1000000 =0 Then Print #f, Counter 'Write strings to a file using the number "f"

   If greater(A,Sqrroot(Suuchi))=-1 Then GoTo Owari
   If _mod (Suuchi,A)="0" Then GoTo Tsuzuku
   If greater(A,"2")=-1 Then A=plus(A,"2") :GoTo Tsugi
   A=plus(A,"1") :GoTo Tsugi
   
Tsuzuku:
 Print A; "*" ;
 I=I+1
 ReDim Preserve Hairetsu(I)
 Hairetsu(I)=A
 Suuchi= divide(Suuchi,A)
 If Instr(Suuchi,".") Then Suuchi= Rtrim(Suuchi,"0"):Suuchi=Rtrim(Suuchi,".")
 GoTo Gusu
 
Owari:
 Print Suuchi
 
 ENDTIME = Val(Left$(Time$,2))*3600+Val(Mid$(Time$,4,2))*60+Val(Right$(Time$,2))
 Minut=(ENDTIME-STARTT)\60
 Print Using "Processing time is #### minutes ## seconds"; Minut; (ENDTIME-STARTT)-Minut*60
 Print
 Print  "Number of loops:"; Format(Counter, "#,##0")
 Print
 'Sleep
 
 Print "prove the answer"
 For J=1 To I
    Print Hairetsu(J);"*";
    Kekka = mult(Kekka,Hairetsu(J))
 Next
 Print Suuchi;"="
 Print mult(Kekka,Suuchi)
 Print
 Print "Try again? If Y (or y) again."
 Input "End, other than y . ",HANTEI
 Print
 If HANTEI="Y" Or HANTEI="y" Then
    GoTo KURIKAESHI
 EndIf
 Close #f

 
Sub STRreplace(ByRef Expression As String, ByRef Find As String, ByRef Replacement As String, ByVal Start As Integer = 1)
   Var p = InStr(Start, Expression, Find), li = Len(Find), ls = Len(Replacement) : If li = ls Then li = 0
   While p
      If li Then Expression = Left(Expression, p - 1) & Replacement & Mid(Expression, p + li) Else Mid(Expression, p) = Replacement
      p = InStr(p + ls, Expression, Find)
   Wend
End Sub


Image
srvaldez
Posts: 2422
Joined: Sep 25, 2005 21:54

Re: new header file GMP

Postby srvaldez » Dec 16, 2016 4:06

hello Makoto WATANABE
I suggest that you use a structure that includes constructors and destructors for the types in GMP, together with operator overloading makes the use of libgmp easier and the program looks more natural.
here's a partial implementation.
save as gmpf-overload.bi

Code: Select all

#include once "gmp.bi"

Type gmpf
    Declare Constructor ( )
    Declare Constructor ( Byval rhs As Long )
    Declare Constructor ( Byval rhs As LongInt )
    Declare Constructor ( Byval rhs As Integer )
    Declare Constructor ( Byval rhs As Double )
    Declare Constructor ( Byval rhs As Single )
    Declare Constructor ( Byref rhs As String )
    Declare Constructor ( Byref rhs As gmpf )
    Declare Constructor ( Byref rhs As __mpq_struct )
    Declare Constructor ( Byref rhs As __mpz_struct )
    Declare Destructor ( )
    Declare Operator Let ( Byref rhs As gmpf )
    Declare Operator Let ( Byref rhs As __mpq_struct )
    Declare Operator Let ( Byref rhs As __mpz_struct )
    Declare Operator Let ( Byval rhs As Long )
    Declare Operator Let ( Byval rhs As LongInt )
    Declare Operator Let ( Byval rhs As Integer )
    Declare Operator Let ( Byval rhs As Double )
    Declare Operator Let ( Byval rhs As Single )
    Declare Operator Let ( Byref rhs As String )
    Declare Operator Cast ( ) As String
    Declare Operator Cast ( ) As Long
    Declare Operator Cast ( ) As Double
    Declare Operator Cast ( ) As Single
   
    '----------------------------------------------
    Declare Operator += (Byref rhs As gmpf)
    Declare Operator += (Byval rhs as long)
    Declare Operator += (byval rhs as double)
    Declare Operator += (byval rhs as single)
    Declare Operator += (byval rhs as longint)
    Declare Operator += (byval rhs as integer)
    Declare Operator += (byref rhs as String)
    Declare Operator -= (Byref rhs As gmpf)
    Declare Operator -= (byval rhs as double)
    Declare Operator -= (byval rhs as single)
    Declare Operator -= (byval rhs as longint)
    Declare Operator -= (byval rhs as integer)
    Declare Operator -= (byval rhs as long)
    Declare Operator -= (byref rhs as String)
    Declare Operator *= (Byref rhs As gmpf)
    Declare Operator *= (byval rhs as double)
    Declare Operator *= (byval rhs as single)
    Declare Operator *= (byval rhs as longint)
    Declare Operator *= (byval rhs as integer)
    Declare Operator *= (byval rhs as long)
    Declare Operator *= (byref rhs as String)
    Declare Operator /= (Byref rhs As gmpf)
    Declare Operator /= (byval rhs as double)
    Declare Operator /= (byval rhs as single)
    Declare Operator /= (byval rhs as longint)
    Declare Operator /= (byval rhs as integer)
    Declare Operator /= (byval rhs as long)
    Declare Operator /= (byref rhs as String)
    Declare Operator ^= (byval rhs as ulong)
    Declare Operator ^= (byref rhs as gmpf)
   
    ' For Next Implicit step = +1
    Declare Operator For ( )
    Declare Operator Step( )
    Declare Operator Next( Byref end_cond As gmpf ) As Integer
    ' For Next Exlicit step
    Declare Operator For ( Byref stp As gmpf )
    Declare Operator Step( Byref stp As gmpf )
    Declare Operator Next( Byref end_cond As gmpf, Byref step_var As gmpf ) As Integer
    '----------------------------------------------
    declare function toString( byval frmt as string ="") as string
    declare Function toLong ( ) As Long
    declare Function toDouble ( ) As Double
    declare Function toSingle ( ) As Single
    declare Sub Set_Prec (Byval n As Long = -1)
   
    num As __mpf_struct
End Type

Sub set_precision(Byval n As Ulong=mpf_get_default_prec()*.3)
    mpf_set_default_prec( n*3.33 )
End Sub

function gmpf.toString( byval frmt as string ="") as string
   dim as long length = mpf_get_prec(@num)*0.3
   dim as string sp =" "
   if frmt="" or frmt="g" then
      frmt="%"+str(length+4)+"."+str(length-1)+"g"
   elseif frmt="f" then
      frmt="%"+str(length+4)+"."+str(length-1)+"f"
   elseif frmt="e" then
      frmt="%"+str(length+4)+"."+str(length-1)+"e"
   end if
   frmt = left(frmt,len(frmt)-1)+"F"+right(frmt,1)
   if instr(frmt , "%")=0 then frmt = "%"+frmt
   length = gmp_snprintf(0, 0, frmt, @num)
   dim as zstring ptr rstring=allocate(length+20)
   gmp_sprintf(rstring, frmt, @num)
   if mpf_sgn(@num)<0 then sp = ""
   function = sp + ltrim(*rstring)
   deallocate(rstring)
end function

sub gmpf.Set_Prec(Byval n As Long = -1)
   if n=-1 then
      mpf_set_prec(@num, mpf_get_default_prec())
   else
      mpf_set_prec(@num, n*3.33)
   end if
end sub

Function gmpf.toLong ( ) As Long
   Function = mpf_get_si(@num)
End Function

Function gmpf.toDouble ( ) As Double
   Function = mpf_get_d(@num)
End Function

Function gmpf.toSingle ( ) As Single
   dim as double sx
   sx = mpf_get_d(@num)
   Function = sx
End Function

Constructor gmpf ( )
   mpf_init(@num)
   mpf_set_si(@num, 0)
End Constructor

Constructor gmpf ( Byval rhs As Long )
   mpf_init(@num)
   mpf_set_si(@num, rhs)
End Constructor

Constructor gmpf ( Byref rhs As __mpq_struct )
   mpf_init(@num)
   mpf_set_q(@num, @rhs)
End Constructor

Constructor gmpf ( Byref rhs As __mpz_struct )
   mpf_init(@num)
   mpf_set_z(@num, @rhs)
End Constructor

Constructor gmpf ( Byref rhs As String )
   mpf_init(@num)
   mpf_set_str(@num, rhs, 10)
End Constructor

Constructor gmpf ( Byref rhs As gmpf )
   mpf_init(@num)
   mpf_set(@num, @rhs.num)
End Constructor

Constructor gmpf ( Byval rhs As LongInt )
   Dim As String s=str(rhs)
   mpf_init(@num)
   mpf_set_str(@num, s, 10)
End Constructor

Constructor gmpf ( Byval rhs As Integer )
   Dim As String s=str(rhs)
   mpf_init(@num)
   mpf_set_str(@num, s, 10)
End Constructor

Constructor gmpf ( Byval rhs As Double )
   mpf_init(@num)
   mpf_set_d(@num, rhs)
End Constructor

Constructor gmpf ( Byval rhs As Single )
   dim as double sx = rhs
   mpf_init(@num)
   mpf_set_d(@num, sx)
End Constructor

Destructor gmpf ( )
   mpf_clear(@num)
End Destructor

Operator gmpf.let ( Byref rhs As gmpf )
   mpf_set(@num, @rhs.num)
End Operator

Operator gmpf.let ( Byref rhs As __mpq_struct )
   mpf_set_q(@num, @rhs)
End Operator

Operator gmpf.let ( Byref rhs As __mpz_struct )
   mpf_set_z(@num, @rhs)
End Operator

Operator gmpf.let ( Byval rhs As Long )
   mpf_set_si(@num, rhs)
End Operator

Operator gmpf.let ( Byref rhs As String )
   mpf_set_str(@num, rhs, 10)
End Operator

Operator gmpf.Let ( Byval rhs As LongInt )
   Dim As String s=str(rhs)
   mpf_set_str(@num, s, 10)
End Operator

Operator gmpf.Let ( Byval rhs As Integer )
   Dim As String s=str(rhs)
   mpf_set_str(@num, s, 10)
End Operator

Operator gmpf.Let ( Byval rhs As Double )
   mpf_set_d(@num, rhs)
End Operator

Operator gmpf.Let ( Byval rhs As Single )
   dim as double sx = rhs
   mpf_set_d(@num, sx)
End Operator

Operator gmpf.cast ( ) As String
   dim as long length = mpf_get_prec(@num)*0.3
   dim as string sp =" ", s = "%"+str(length+4)+"."+str(length-1)+"Fg"
   length = gmp_snprintf(0, 0, s, @num)
   dim as zstring ptr rstring=allocate(length+20)
   gmp_sprintf(rstring, s, @num)
   if mpf_sgn(@num)<0 then sp = ""
   Operator = sp + ltrim(*rstring)
   deallocate(rstring)
End Operator

Operator gmpf.cast ( ) As Long
   Operator = mpf_get_si(@num)
End Operator

Operator gmpf.cast ( ) As Double
   Operator = mpf_get_d(@num)
End Operator

Operator gmpf.cast ( ) As Single
   Operator = mpf_get_d(@num)
End Operator

'============================================================================
'' For Next for gmpf type
''
'' implicit step versions
''
'' In this example, we interpret implicit step
'' to mean 1
Operator gmpf.for ( )
End Operator
 
Operator gmpf.step ( )
        this += 1 'this = this+1 '
End Operator
 
Operator gmpf.next ( Byref end_cond As gmpf ) As Integer
        Return this <= end_cond
End Operator
 
 
'' explicit step versions
''
Operator gmpf.for ( Byref step_var As gmpf )
End Operator
 
Operator gmpf.step ( Byref step_var As gmpf )
        this += step_var 'this = this + step_var '   
End Operator
 
Operator gmpf.next ( Byref end_cond As gmpf, Byref step_var As gmpf ) As Integer
        If step_var < 0 Then
                Return this >= end_cond
        Else
                Return this <= end_cond
        End If
End Operator

'============================================================================

Operator + ( Byref lhs As gmpf, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_add(@result.num, @lhs.num, @rhs.num)
   Operator = result
End Operator

Operator + ( Byref lhs As gmpf, Byval rhs As culong ) As gmpf
   Dim As gmpf result
   mpf_add_ui(@result.num, @lhs.num, rhs)
   Operator = result
End Operator

Operator - ( Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_neg(@result.num, @rhs.num)
   Operator = result
End Operator

Operator - ( Byref lhs As gmpf, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_sub(@result.num, @lhs.num, @rhs.num)
   Operator = result
End Operator

Operator - ( Byref lhs As gmpf, Byval rhs As culong ) As gmpf
   Dim As gmpf result
   mpf_sub_ui(@result.num, @lhs.num, rhs)
   Operator = result
End Operator

Operator - ( Byval lhs As culong, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_ui_sub(@result.num, lhs, @rhs.num)
   Operator = result
End Operator

Operator * ( Byref lhs As gmpf, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_mul(@result.num, @lhs.num, @rhs.num)
   Operator = result
End Operator

Operator * ( Byref lhs As gmpf, Byval rhs As culong ) As gmpf
   Dim As gmpf result
   mpf_mul_ui(@result.num, @lhs.num, rhs)
   Operator = result
End Operator

Operator / ( Byref lhs As gmpf, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_div(@result.num, @lhs.num, @rhs.num)
   Operator = result
End Operator

Operator / ( Byref lhs As gmpf, Byval rhs As culong ) As gmpf
   Dim As gmpf result
   mpf_div_ui(@result.num, @lhs.num, rhs)
   Operator = result
End Operator

Operator / ( Byval lhs As culong, Byref rhs As gmpf ) As gmpf
   Dim As gmpf result
   mpf_ui_div(@result.num, lhs, @rhs.num)
   Operator = result
End Operator

Operator ^ ( Byref lhs As gmpf, Byval rhs As ulong ) As gmpf
   Dim As gmpf result
   mpf_pow_ui(@result.num, @lhs.num, rhs)
   Operator = result
End Operator

Operator gmpf.+= (byref rhs As gmpf)
   mpf_add(@this.num, @this.num, @rhs.num)
End Operator

Operator gmpf.+= (Byval rhs as long)
   dim as gmpf x
   mpf_set_si(@x.num, rhs)
   mpf_add(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.+= (byval rhs as double)
   dim as gmpf x
   mpf_set_d(@x.num, rhs)
   mpf_add(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.+= (byval rhs as single)
   dim as gmpf x
   dim as double dx = rhs
   mpf_set_d(@x.num, dx)
   mpf_add(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.+= (byval rhs as longint)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_add(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.+= (byval rhs as integer)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_add(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.+= (byref rhs as String)
   Dim As gmpf tmp
   tmp=rhs
   mpf_add(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.-= (byref rhs As gmpf)
   mpf_sub(@this.num, @this.num, @rhs.num)
End Operator

Operator gmpf.-= (Byval rhs as long)
   dim as gmpf x
   mpf_set_si(@x.num, rhs)
   mpf_sub(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.-= (byval rhs as double)
   dim as gmpf x
   mpf_set_d(@x.num, rhs)
   mpf_sub(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.-= (byval rhs as single)
   dim as gmpf x
   dim as double dx = rhs
   mpf_set_d(@x.num, dx)
   mpf_sub(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.-= (byval rhs as longint)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_sub(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.-= (byval rhs as integer)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_sub(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.-= (byref rhs as String)
   Dim As gmpf tmp
   tmp=rhs
   mpf_sub(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.*= (byref rhs As gmpf)
   mpf_mul(@this.num, @this.num, @rhs.num)
End Operator

Operator gmpf.*= (Byval rhs as long)
   dim as gmpf x
   mpf_set_si(@x.num, rhs)
   mpf_mul(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.*= (byval rhs as double)
   dim as gmpf x
   mpf_set_d(@x.num, rhs)
   mpf_mul(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.*= (byval rhs as single)
   dim as gmpf x
   dim as double dx = rhs
   mpf_set_d(@x.num, dx)
   mpf_mul(@this.num, @this.num, @x.num)
End Operator

Operator gmpf.*= (byval rhs as longint)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_mul(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.*= (byval rhs as integer)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_mul(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.*= (byref rhs as String)
   Dim As gmpf tmp
   tmp=rhs
   mpf_mul(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf./= (byref rhs As gmpf)
   mpf_div(@this.num, @this.num, @rhs.num)
End Operator

Operator gmpf./= (Byval rhs as long)
   dim as gmpf x
   mpf_set_si(@x.num, rhs)
   mpf_div(@this.num, @this.num, @x.num)
End Operator

Operator gmpf./= (byval rhs as double)
   dim as gmpf x
   mpf_set_d(@x.num, rhs)
   mpf_div(@this.num, @this.num, @x.num)
End Operator

Operator gmpf./= (byval rhs as single)
   dim as gmpf x
   dim as double dx = rhs
   mpf_set_d(@x.num, dx)
   mpf_div(@this.num, @this.num, @x.num)
End Operator

Operator gmpf./= (byval rhs as longint)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_div(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf./= (byval rhs as integer)
   Dim As gmpf tmp
   tmp=str(rhs)
   mpf_div(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf./= (byref rhs as String)
   Dim As gmpf tmp
   tmp=rhs
   mpf_div(@this.num, @this.num, @tmp.num)
End Operator

Operator gmpf.^= (Byval rhs as ulong)
   mpf_pow_ui(@this.num, @this.num, rhs)
End Operator

Operator = ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) = 0)
End Operator

Operator < ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) < 0)
End Operator

Operator > ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) > 0)
End Operator

Operator <= ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) <= 0)
End Operator

Operator >= ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) >= 0)
End Operator

Operator <> ( Byref lhs As gmpf, Byref rhs As gmpf ) As Integer
   Operator = (mpf_cmp(@lhs.num, @rhs.num) <> 0)
End Operator

Function gmpf_Abs(byref rhs As gmpf) As gmpf
   Dim As gmpf result
   mpf_abs(@result.num, @rhs.num)
   function = result
end function

function gmpf_ceil(byref x As gmpf) As gmpf
   Dim As gmpf result
   mpf_ceil(@result.num, @x.num)
   function = result
end function

function gmpf_floor(byref x As gmpf) As gmpf
   Dim As gmpf result
   mpf_floor(@result.num, @x.num)
   return result
end function

function gmpf_int(byref x As gmpf) As gmpf
   Dim As gmpf result
   mpf_trunc(@result.num, @x.num)
   function = result
end function

function gmpf_sgn(byref x As gmpf) As integer
   function = mpf_sgn(@x.num)
end function

Declare Function gmpf_Sqr Overload ( ByRef number As gmpf ) As gmpf

function gmpf_Sqr(byref x As gmpf) As gmpf
   Dim As gmpf result
   mpf_sqrt(@result.num, @x.num)
   return result
end function

function gmpf_Sqr(byval x As ulong) As gmpf
   Dim As gmpf result
   mpf_sqrt_ui(@result.num, x)
   return result
end function

small example

Code: Select all

#include "gmpf-overload.bi"

function pi( byval prec as long) as gmpf
   set_precision(prec)

   dim as gmpf a,b,t,p,aa,bb,tt,pp

   a=1
   b=0.5
   t=0.25
   p=1
   b=gmpf_sqr( b )

   for i as integer = 1 to int(log(prec)*1.44269504088896)
      aa = (a+b)/2
      bb = gmpf_sqr(a*b)
      tt = t-p*(a-aa)^2
      pp = 2*p
      swap a, aa
      swap b, bb
      swap t, tt
      swap p, pp
   next

   return (a+b)^2/4/t
end function

set_precision(20) 'set precision to at least 20 digits

dim as integer i
dim as gmpf y,x="0.333333333333333333333333333" 'use string for float assignment

if 3*x<1 then
   print "3*x is less than 1"
end if
'mpf in for loop
for x=1 to 10
   y=gmpf_sqr(x)
   print y
next
print y.toString("%15.10f") 'another way to print the mpf number
print pi(1000)
print "press RETURN to end ";
sleep
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: new header file GMP

Postby frisian » Dec 16, 2016 10:16

Makoto WATANABE wrote:However, when I tried to calculate "70,000,005,000,000,007", this program was terminated abnormally when 15 million times repeated the loop .
If any corresponding method is thought about, please teach me it.

Toke me some time to realize that there are two division routines one for integer's and one for float's you pick the wrong one.(Murphy's law)
change Suuchi=divide(Suuchi,A) into Suuchi= _div(Suuchi,A).

edit
This post only solves one memory leak, after testing I found a other memory leak.
The next post has a new file that solved this.
Last edited by frisian on Dec 16, 2016 16:01, edited 1 time in total.

Return to “General”

Who is online

Users browsing this forum: No registered users and 4 guests