new header file GMP
Re: new header file GMP
Hi Makoto WATANABE
The 2015 gmp binaries are here (by srvaldez top post gmp 6.1.0):
http://www.freebasic.net/forum/viewtopi ... 2A#p212995
I think maybe your gmp version is less ??
You might need 7 zip to uncompress:
http://www.7-zip.org/
The 2015 gmp binaries are here (by srvaldez top post gmp 6.1.0):
http://www.freebasic.net/forum/viewtopi ... 2A#p212995
I think maybe your gmp version is less ??
You might need 7 zip to uncompress:
http://www.7-zip.org/
Re: new header file GMP
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
FreeBASIC Compiler - Version 1.05.0 (01-31-2016)
This has the updated gmp.bi which has mpz_div
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: new header file GMP
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.
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.
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: new header file GMP
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.
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.
Re: new header file GMP
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:
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
Re: new header file GMP
Makoto WATANABEMakoto 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.
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.
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: new header file GMP
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 .
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 .
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: new header file GMP
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.
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.
Re: new header file GMP
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.
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
'
'
Re: new header file GMP
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.
I'll post the functions when done.
This should stop any memory leaks.
Re: new header file GMP
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.
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).
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
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
Re: new header file GMP
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.
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.
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: new header file GMP
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.
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
Re: new header file GMP
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
small example
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
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
Re: new header file GMP
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)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.
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.