Always for me a Big question

New to FreeBASIC? Post your questions here.
student1347
Posts: 49
Joined: Dec 16, 2011 3:48

Always for me a Big question

With all the progresses in computer science and in year 2017 why programs can keep only 20-digit numbers(ulongint) and if I want to compute long and big numbers there is a limitation in it? In freebasic we can have a string about 2G it is good ,but with numbers......? I want to work with big numbers about for example 500 digits and can I have a digit unit other than binary or decade with ascci codes(base 256 ) and how ?
Last edited by student1347 on May 05, 2017 11:53, edited 1 time in total.
MrSwiss
Posts: 3665
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Always for me a Big question

There are libraries for that very purpose (I am not aware of any language, having such *native*).
See: Section Library's of the Forum ...
dodicat
Posts: 6766
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Always for me a Big question

get the gmp library.
gmp 6.1.2
from srvaldez (top post)
http://www.freebasic.net/forum/viewtopic.php?f=3&t=24110&p=230255#p230255

Put the static library (.a) into your lib folder.
That's all.
Try this factorial.

Code: Select all

`#Include Once "gmp.bi"Function factorial(n As Ulong,numberbase as long=10) As String     Dim As __mpz_struct Intanswer    mpz_init( @Intanswer)    mpz_fac_ui(@Intanswer,n)    Dim As ZString Ptr s = mpz_get_str(0, numberbase, @intanswer)    mpz_clear(@Intanswer)    function= Trim(*s)    deallocate(s)End Functionprint factorial(150,16)printprint factorial(150,10)sleep `
srvaldez
Posts: 2578
Joined: Sep 25, 2005 21:54

Re: Always for me a Big question

hello student1347
you may also be interested in the "Big Number Wrapper" (using GMP int) by Yetifoot viewtopic.php?t=7173
example code by Yetifoot

Code: Select all

`#include "gmp_int.bi"' Powers of twoprint "Some powers of two"for i as integer = 0 to 128   print "2 ^ " & i & " = " & gmp_int(2) ^ gmp_int(i)next i' Big numbers in FORprint "Big numbers in FOR loop"for i as gmp_int = gmp_int("10000000000000000") to gmp_int("50000000000000000") step gmp_int("20000000000000000")   print inext i' Printing a big number using a non 10 number base.dim n as gmp_int = gmp_int("123456789123456789123456789123456789")print "Printing a big number in base 16"print n, n.getString( 16 )`
Posts: 2184
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Always for me a Big question

I am not aware of any language, having such *native*

Python (2.7) seems to do this fine:

Code: Select all

`a = 123456789123456789123456789123456789123456789123456789b = 987654321987654321987654321987654321987654321987654321c = a + b + 1print c`

Result: 1111111111111111111111111111111111111111111111111111111

This however, may not be so great:

Code: Select all

`a = 123456789123456789123456789123456789123456789123456789.1b = 987654321987654321987654321987654321987654321987654321c = a + b + 1print c`

Result: 1.11111111111e+54
Makoto WATANABE
Posts: 196
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: Always for me a Big question

Dear srvaldez

I am interested in the "Big Number Wrapper" (using GMP int) by Yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173 .

Unfortunately the "example code" shows a following error:
BigNumberWrapper.bas(19) error 197: Missing overloaded operator: next (with step), before 'i' in 'Next i'

Please teach me if there is a countermeasure method.
srvaldez
Posts: 2578
Joined: Sep 25, 2005 21:54

Re: Always for me a Big question

hello Makoto WATANABE
I made some changes, hope it helps.

gmp_int.bi

Code: Select all

`#ifndef __GMP_INT_BI__#define __GMP_INT_BI__#include "gmp.bi"type gmp_int   declare constructor ( )   declare constructor ( byval i as integer )   declare constructor ( byref s as string )   declare constructor ( byref g as gmp_int )   declare destructor ( )   declare operator let ( byref g as gmp_int )   declare operator let ( byval i as Integer )   declare operator let ( byref s as string )   declare operator cast ( ) as Integer   declare operator cast ( ) as string   ' For Next Implicit step = +1   Declare Operator For ( )   Declare Operator Step( )   declare operator for ( byref stp as gmp_int )   declare operator step ( byref stp as gmp_int )   declare operator next ( byref end_cond as gmp_int ) as integer   Declare Operator Next( Byref end_cond As gmp_int, Byref step_var As gmp_int ) As Integer   declare function getString ( byval _base as integer = 10 ) as string   num as mpz_ptr = 0end typedeclare operator + ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator - ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator * ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator \ ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator / ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator ^ ( byref lhs as gmp_int, byval rhs as gmp_int ) as gmp_intdeclare operator mod ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator and ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator or ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator xor ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_intdeclare operator - ( byref rhs as gmp_int ) as gmp_intdeclare operator not ( byref rhs as gmp_int ) as gmp_intdeclare operator = ( byref lhs as gmp_int, byref rhs as gmp_int ) as integerdeclare operator < ( byref lhs as gmp_int, byref rhs as gmp_int ) as integerdeclare operator > ( byref lhs as gmp_int, byref rhs as gmp_int ) as integerdeclare operator <= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integerdeclare operator >= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integerdeclare operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer#endif '__GMP_INT_BI__''''#include "gmp_int.bi" 'code above' Any time we allocate with sizeof( __mpz_struct ), we add the safety net onto the size, ' without this it crashes for me, perhaps the __mpz_struct is declared wrong in gmp.bi, ' whatever the reason it doesn't matter too much, as the struct is only manipulated by' the gmp functions.const SAFETY_NET = 20'::::::::constructor gmp_int ( )   num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   mpz_init_set_si( num, 0 )   end constructor'::::::::constructor gmp_int ( byval i as integer )   num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   mpz_init_set_si( num, i )   end constructor'::::::::constructor gmp_int ( byref s as string )   num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   mpz_init_set_str( num, strptr( s ), 10 )   end constructor'::::::::constructor gmp_int ( byref g as gmp_int )   num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   mpz_init_set( num, g.num )   end constructor'::::::::destructor gmp_int ( )   mpz_clear( num )   deallocate( num )end destructor'::::::::operator gmp_int.let ( byref g as gmp_int )   mpz_set( num, g.num )   end operator'::::::::operator gmp_int.let ( byval i as Integer )   mpz_set_si( num, i )   end operator'::::::::operator gmp_int.let ( byref s as string )   mpz_set_str( num, strptr(s), 10 )   end operatorOperator gmp_int.cast ( ) As Integer   Operator = mpz_get_si(num)End Operator'::::::::operator gmp_int.cast ( ) as string   operator = getString( 10 )end operator'=====================================================================' Implicit step   gmp_int.For   gmp_int.Next   gmp_int.Step  is +1Operator gmp_int.for ( )End Operator Operator gmp_int.step ( )   this += 1 'this = this+1 'End Operator  Operator gmp_int.next ( Byref end_cond As gmp_int ) As Integer   Return this <= end_condEnd Operator  '' explicit step versions'' Operator gmp_int.for ( Byref step_var As gmp_int )End Operator Operator gmp_int.step ( Byref step_var As gmp_int )   this += step_var 'this = this + step_var '    End Operator  Operator gmp_int.next ( Byref end_cond As gmp_int, Byref step_var As gmp_int ) As Integer   If step_var < 0 Then      Return this >= end_cond   Else      Return this <= end_cond   End IfEnd Operator'::::::::function gmp_int.getString ( byval _base as integer = 10 ) as string   dim as zstring ptr s = mpz_get_str( 0, _base, num )   if s then      function = *s      deallocate( s )   end ifend function'::::::::operator + ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_add( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator - ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_sub( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator * ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_mul( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator \ ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_tdiv_q( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator / ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   ' This really is quite nasty, but it's the best way I could come up with   ' to do an FP divide, while rounding results the way people may expect them.   ' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0   ' I'm not 100% that temp is needed, but I used it just to be safe, for some   ' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.   dim as mpf_ptr l, r, q, half, temp   dim as integer cmp_val   dim as gmp_int result   l = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   r = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   q = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   half = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   temp = callocate( sizeof( __mpz_struct ) + SAFETY_NET )   mpf_init( l )   mpf_init( r )   mpf_init( q )   mpf_init_set_str( half, "0.50", 10 )   mpf_init( temp )   mpf_set_z( l, lhs.num )   mpf_set_z( r, rhs.num )   mpf_div( q, l, r )   cmp_val = mpf_cmp_d( q, 0 )   if cmp_val > 0 then      mpf_add( temp, q, half )   elseif cmp_val < 0 then      mpf_sub( temp, q, half )   else      mpf_set( temp, q )   end if   mpf_trunc( q, temp )   mpz_set_f( result.num, q )   mpf_clear( l )   mpf_clear( r )   mpf_clear( q )   mpf_clear( half )   mpf_clear( temp )   deallocate( l )   deallocate( r )   deallocate( q )   deallocate( half )   deallocate( temp )   operator = result   end operator'::::::::operator ^ ( byref lhs as gmp_int, byval rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )   operator = resultend operator'::::::::operator mod ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_mod( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator and ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_and( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator or ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_ior( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator xor ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_xor( result.num, lhs.num, rhs.num )   operator = resultend operator'::::::::operator - ( byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_neg( result.num, rhs.num )   operator = resultend operator'::::::::operator not ( byref rhs as gmp_int ) as gmp_int   dim as gmp_int result   mpz_com( result.num, rhs.num )   operator = resultend operator'::::::::operator = ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) = 0)end operator'::::::::operator < ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) < 0)end operator'::::::::operator > ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) > 0)end operator'::::::::operator <= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) <= 0)end operator'::::::::operator >= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) >= 0)end operator'::::::::operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer   operator = (mpz_cmp( lhs.num, rhs.num ) <> 0)end operator`

test.bas

Code: Select all

`#include "gmp_int.bi"dim as gmp_int i, two = 2 'if the number is small' if the number is larger than FB integer then use: two = gmp_int("2")dim as integer k' Powers of twoprint "Some powers of two"for i = 0 to 128   print "2 ^ " & i & " = " & two ^ i next iprintprint "casting a gmp_int to a FreeBASIC Integer"print "this should only be done if you know the gmp_int will fit in a Integer"k = twoprint "k = two ->";k`
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: Always for me a Big question

Gmp_int.bi has two problems in the floating point division (/) routine. First the gmp floats need a 16 byte structure (__mpf_struct) but they get a 12 byte structure (__mpz_struct) which result in data stored outside the structure and most likely overwriting data in the next structure, hence crashes.
Solution: change __mpz_struct to __mpf_struct.

The size for gmp_floats is fixed where as the size for integers depends on the size of the number. The default size for floats is 32bit.
Solution: find the size in bits of lhs and rhs. Take the biggest of the two. Use mpf_init2 instead of mpf_init to give the floats a size that is at least equal to the size of the integers

Tweaked the Constructor ( ByRef s As String) to Constructor ( ByRef s As String, ByVal _base As Long = 10 ) to make it possible to enter numbers in base 2 to 62. Default = 10 (decimal)

i = gmp_int("1234") = gmp_int("1234", 10)
i = gmp_int("abcd", 16) ' hexadecimal
i = gmp_int("1001", 2) ' binary
i = gmp_int("7777", 8) ' octal

gmp_int.bi

Code: Select all

`#Ifndef __GMP_INT_BI__#Define __GMP_INT_BI__#Include Once "gmp.bi"Type gmp_int    Declare Constructor ( )    Declare Constructor ( ByVal i As Integer )    Declare Constructor ( ByRef s As String, ByVal _base As Long = 10 )    Declare Constructor ( ByRef g As gmp_int )    Declare Destructor ( )    Declare Operator Let ( ByRef g As gmp_int )    Declare Operator Let ( ByVal i As Integer )    Declare Operator Let ( ByRef s As String )    Declare Operator Cast ( ) As Integer    Declare Operator Cast ( ) As String    ' For Next Implicit step = +1    Declare Operator For ( )    Declare Operator Step( )    Declare Operator For ( ByRef stp As gmp_int )    Declare Operator Step ( ByRef stp As gmp_int )    Declare Operator Next ( ByRef end_cond As gmp_int ) As Integer    Declare Operator Next( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer    Declare Function getString ( ByVal _base As Integer = 10 ) As String    num As mpz_ptr = 0End TypeDeclare Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_intDeclare Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator - ( ByRef rhs As gmp_int ) As gmp_intDeclare Operator Not ( ByRef rhs As gmp_int ) As gmp_intDeclare Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer#EndIf '__GMP_INT_BI__''''#include "gmp_int.bi" 'code above' Any time we allocate with sizeof( __mpz_struct ), we add the safety net onto the size,' without this it crashes for me, perhaps the __mpz_struct is declared wrong in gmp.bi,' whatever the reason it doesn't matter too much, as the struct is only manipulated by' the gmp functions.' Const SAFETY_NET = 20Const SAFETY_NET = 0 ' not needed'::::::::Constructor gmp_int ( )num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )' mpz_init_set_si( num, 0 )mpz_init( num )End Constructor'::::::::Constructor gmp_int ( ByVal i As Integer )num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )mpz_init_set_si( num, i )End Constructor'::::::::Constructor gmp_int ( ByRef s As String, ByVal _base As Long = 10 )num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )mpz_init_set_str( num, StrPtr( s ), _base )End Constructor'::::::::Constructor gmp_int ( ByRef g As gmp_int )num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )mpz_init_set( num, g.num )End Constructor'::::::::Destructor gmp_int ( )mpz_clear( num )DeAllocate( num )End Destructor'::::::::Operator gmp_int.let ( ByRef g As gmp_int )    mpz_set( num, g.num )End Operator'::::::::Operator gmp_int.let ( ByVal i As Integer )    mpz_set_si( num, i )End Operator'::::::::Operator gmp_int.let ( ByRef s As String )    mpz_set_str( num, StrPtr(s), 10 )End OperatorOperator gmp_int.cast ( ) As IntegerOperator = mpz_get_si(num)End Operator'::::::::Operator gmp_int.cast ( ) As StringOperator = getString( 10 )End Operator'=====================================================================' Implicit step   gmp_int.For   gmp_int.Next   gmp_int.Step  is +1Operator gmp_int.for ( )End OperatorOperator gmp_int.step ( )    This += 1 'this = this+1 'End OperatorOperator gmp_int.next ( ByRef end_cond As gmp_int ) As Integer    Return This <= end_condEnd Operator'' explicit step versions''Operator gmp_int.for ( ByRef step_var As gmp_int )End OperatorOperator gmp_int.step ( ByRef step_var As gmp_int )    This += step_var 'this = this + step_var 'End OperatorOperator gmp_int.next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer    If step_var < 0 Then        Return This >= end_cond    Else        Return This <= end_cond    End IfEnd Operator'::::::::Function gmp_int.getString ( ByVal _base As Integer = 10 ) As String    Dim As ZString Ptr s = mpz_get_str( 0, _base, num )    If s Then        Function = *s        DeAllocate( s )    End IfEnd Function'::::::::Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_add( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_sub( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_mul( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_tdiv_q( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    ' This really is quite nasty, but it's the best way I could come up with    ' to do an FP divide, while rounding results the way people may expect them.    ' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0    ' I'm not 100% that temp is needed, but I used it just to be safe, for some    ' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.    Dim As mpf_ptr l, r, q, half, temp    Dim As gmp_int result    ' size for gmp floats is fixed, this could lead to loss of precision    ' the size is set by mpf_set_default_prec or by using mpf_init2( 'var', size)    ' find the size of lhs and rhs, take the longest size and add 32 bit (9 digits)    Dim As ULong l1 = mpz_sizeinbase ( lhs.num , 2)    Dim As ULong r1 = mpz_sizeinbase ( rhs.num , 2)    If r1 > l1 Then l1 = r1    l1 = l1 +32    ' l = callocate( sizeof( __mpz_struct ) + SAFETY_NET )    ' r = callocate( sizeof( __mpz_struct ) + SAFETY_NET )    ' q = callocate( sizeof( __mpz_struct ) + SAFETY_NET )    ' half = callocate( sizeof( __mpz_struct ) + SAFETY_NET )    ' temp = callocate( sizeof( __mpz_struct ) + SAFETY_NET )    ' sizeof( __mpz_struct ) = 12, sizeof( __mpf_struct ) = 16    l = Callocate( SizeOf( __mpf_struct ) )    r = Callocate( SizeOf( __mpf_struct ) )    q = Callocate( SizeOf( __mpf_struct ) )    half = Callocate( SizeOf( __mpf_struct ) )    temp = Callocate( SizeOf( __mpf_struct ) )    mpf_init2( l, l1 )          ' set the size for l to l1    mpf_init2( r, l1 )          ' set the size for l to l1    mpf_init2( q, l1 )          ' set the size for l to l1    mpf_init_set_d( half, .5 )    mpf_init2( temp, l1 )       ' set the size for l to l1    mpf_set_z( l, lhs.num )    mpf_set_z( r, rhs.num )    mpf_div( q, l, r )    Dim As Long cmp_val = mpf_cmp_d( q, 0 )    If cmp_val > 0 Then        mpf_add( temp, q, half )    ElseIf cmp_val < 0 Then        mpf_sub( temp, q, half )    Else        mpf_set( temp, q )    End If    ' mpf_trunc( q, temp )    ' mpz_set_f( result.num, q )    ' mpz_set_d, mpz_set_q and mpz_set_f truncate 'op' to make it an integer.    mpz_set_f( result.num, temp)    mpf_clear( l )    mpf_clear( r )    mpf_clear( q )    mpf_clear( half )    mpf_clear( temp )    DeAllocate( l )    DeAllocate( r )    DeAllocate( q )    DeAllocate( half )    DeAllocate( temp )    Operator = resultEnd Operator'::::::::Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )    Operator = resultEnd Operator'::::::::Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_mod( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_and( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_ior( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_xor( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator - ( ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_neg( result.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Not ( ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_com( result.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) = 0)End Operator'::::::::Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) < 0)End Operator'::::::::Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) > 0)End Operator'::::::::Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) <= 0)End Operator'::::::::Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) >= 0)End Operator'::::::::Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) <> 0)End Operator`

littletest.bas

Code: Select all

`#Include Once "gmp_int.bi"Dim As gmp_int iPrintPrint gmp_int ("1"+String(40, "0")) / gmp_int(3)Printi = gmp_int(String(32,"F"), 16)Print ii = gmp_int(String(32,"f"), 16)Print ii = gmp_int(string(128,"1"), 2)Print iSleep`
Last edited by frisian on May 06, 2017 8:56, edited 1 time in total.
srvaldez
Posts: 2578
Joined: Sep 25, 2005 21:54

Re: Always for me a Big question

thanks frisian
this was Yetifoot's code and I did not check for correctness other than fixing the for loop code, thanks for the fix. :-)
 in the test code, next to last line you missed a right parenthesis
i = gmp_int(string(128,"1", 2) should be i = gmp_int(string(128,"1"), 2) also you missed a print i
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: Always for me a Big question

srvaldez wrote: in the test code, next to last line you missed a right parenthesis
i = gmp_int(string(128,"1", 2) should be i = gmp_int(string(128,"1"), 2) also you missed a print i

fixed the code in my previous post, thanks.

I have cleaned the listing of gmp_int.bi and added shl and shr also added a function to convert a big int into base 2 to 62 string.

gmp_int.bi

Code: Select all

`' Original by yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173' May 2017: srvaldez' fixed the loop code ' May 2017: frisian' corrected and improved the floating point division (/), this makes SAFETY_NET obsolete' added operators Shr and Shl' corrected some errors in comments i made, cleaned the listing ' added function gmp_int_2_base that returns a string of a gmp_int number in base 2 to 62 (default 10, decimal)#Ifndef __GMP_INT_BI__#Define __GMP_INT_BI__#Include Once "gmp.bi"Type gmp_int    Declare Constructor ( )    Declare Constructor ( ByVal i As Integer )    Declare Constructor ( ByRef s As String, ByVal _base As Integer = 10 )    Declare Constructor ( ByRef g As gmp_int )    Declare Destructor ( )    Declare Operator Let ( ByRef g As gmp_int )    Declare Operator Let ( ByVal i As Integer )    Declare Operator Let ( ByRef s As String )    Declare Operator Cast ( ) As Integer    Declare Operator Cast ( ) As String    ' For Next Implicit step = +1    Declare Operator For ( )    Declare Operator Step( )    Declare Operator For ( ByRef stp As gmp_int )    Declare Operator Step ( ByRef stp As gmp_int )    Declare Operator Next ( ByRef end_cond As gmp_int ) As Integer    Declare Operator Next( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer    Declare Function getString ( ByVal _base As Integer = 10 ) As String    num As mpz_ptr = 0End TypeDeclare Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_intDeclare Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_intDeclare Operator Shl ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_intDeclare Operator Shr ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_intDeclare Operator - ( ByRef rhs As gmp_int ) As gmp_intDeclare Operator Not ( ByRef rhs As gmp_int ) As gmp_intDeclare Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerDeclare Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer#EndIf '__GMP_INT_BI__''''#include "gmp_int.bi" 'code above'::::::::Constructor gmp_int ( )num = Callocate( SizeOf( __mpz_struct ) )mpz_init( num )End Constructor'::::::::Constructor gmp_int ( ByVal i As Integer )num = Callocate( SizeOf( __mpz_struct ) )mpz_init_set_si( num, i )End Constructor'::::::::Constructor gmp_int ( ByRef s As String, ByVal _base As Integer = 10 )num = Callocate( SizeOf( __mpz_struct ) )mpz_init_set_str( num, StrPtr( s ), _base )End Constructor'::::::::Constructor gmp_int ( ByRef g As gmp_int )num = Callocate( SizeOf( __mpz_struct ) )mpz_init_set( num, g.num )End Constructor'::::::::Destructor gmp_int ( )mpz_clear( num )DeAllocate( num )End Destructor'::::::::Operator gmp_int.let ( ByRef g As gmp_int )    mpz_set( num, g.num )End Operator'::::::::Operator gmp_int.let ( ByVal i As Integer )    mpz_set_si( num, i )End Operator'::::::::Operator gmp_int.let ( ByRef s As String )    mpz_set_str( num, StrPtr(s), 10 )End OperatorOperator gmp_int.cast ( ) As IntegerOperator = mpz_get_si(num)End Operator'::::::::Operator gmp_int.cast ( ) As StringOperator = getString( 10 )End Operator'=====================================================================' Implicit step   gmp_int.For   gmp_int.Next   gmp_int.Step  is +1Operator gmp_int.for ( )End OperatorOperator gmp_int.step ( )    This += 1 'this = this+1 'End OperatorOperator gmp_int.next ( ByRef end_cond As gmp_int ) As Integer    Return This <= end_condEnd Operator'' explicit step versions''Operator gmp_int.for ( ByRef step_var As gmp_int )End OperatorOperator gmp_int.step ( ByRef step_var As gmp_int )    This += step_var 'this = this + step_var 'End OperatorOperator gmp_int.next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer    If step_var < 0 Then        Return This >= end_cond    Else        Return This <= end_cond    End IfEnd Operator'::::::::Function gmp_int.getString ( ByVal _base As Integer = 10 ) As String    Dim As ZString Ptr s = mpz_get_str( 0, _base, num )    If s Then        Function = *s        DeAllocate( s )    End IfEnd Function'::::::::Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_add( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_sub( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_mul( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_tdiv_q( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    ' This really is quite nasty, but it's the best way I could come up with    ' to do an FP divide, while rounding results the way people may expect them.    ' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0    ' I'm not 100% that temp is needed, but I used it just to be safe, for some    ' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.    Dim As mpf_ptr l, r, q, half, temp    Dim As gmp_int result    ' size for gmp floats is fixed, this could lead to loss of precision    ' the size is set by mpf_set_default_prec or by using mpf_init2( 'var', size)    ' find the size of lhs and rhs, take the longest size and add 32 bit (9 digits)    Dim As UInteger l1 = mpz_sizeinbase ( lhs.num, 2 )    Dim As UInteger r1 = mpz_sizeinbase ( rhs.num, 2 )    If r1 > l1 Then l1 = r1    l1 = l1 +32    l = Callocate( SizeOf( __mpf_struct ) )    r = Callocate( SizeOf( __mpf_struct ) )    q = Callocate( SizeOf( __mpf_struct ) )    half = Callocate( SizeOf( __mpf_struct ) )    temp = Callocate( SizeOf( __mpf_struct ) )    mpf_init2( l, l1 )          ' set the size for l to l1    mpf_init2( r, l1 )          ' set the size for r to l1    mpf_init2( q, l1 )          ' set the size for q to l1    mpf_init_set_d( half, .5 )    mpf_init2( temp, l1 )       ' set the size for temp to l1    mpf_set_z( l, lhs.num )    mpf_set_z( r, rhs.num )    mpf_div( q, l, r )    Dim As Integer cmp_val = mpf_cmp_d( q, 0 )    If cmp_val > 0 Then        mpf_add( temp, q, half )    ElseIf cmp_val < 0 Then        mpf_sub( temp, q, half )    Else        mpf_set( temp, q )    End If    mpz_set_f( result.num, temp)    mpf_clear( l )    mpf_clear( r )    mpf_clear( q )    mpf_clear( half )    mpf_clear( temp )    DeAllocate( l )    DeAllocate( r )    DeAllocate( q )    DeAllocate( half )    DeAllocate( temp )    Operator = resultEnd Operator'::::::::Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )    Operator = resultEnd Operator'::::::::Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_mod( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_and( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_ior( result.num, lhs.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_xor( result.num, lhs.num, rhs.num )    Operator = resultEnd OperatorOperator Shl ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int    Dim As gmp_int result    mpz_mul_2exp( result.num, lhs.num, rhs )    Operator = resultEnd OperatorOperator Shr ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int    Dim As gmp_int result    mpz_tdiv_q_2exp( result.num, lhs.num, rhs )    Operator = resultEnd Operator'::::::::Operator - ( ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_neg( result.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator Not ( ByRef rhs As gmp_int ) As gmp_int    Dim As gmp_int result    mpz_com( result.num, rhs.num )    Operator = resultEnd Operator'::::::::Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) = 0)End Operator'::::::::Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) < 0)End Operator'::::::::Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) > 0)End Operator'::::::::Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) <= 0)End Operator'::::::::Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) >= 0)End Operator'::::::::Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As IntegerOperator = (mpz_cmp( lhs.num, rhs.num ) <> 0)End Operator' return a string of a gmp_int number in base 2 to 62 (default 10, decimal)Function gmp_int_2_base (ByRef bigint As gmp_int, ByVal _base As Integer = 10 ) As String    Dim As ZString Ptr s = mpz_get_str( 0, _base, bigint.num )    If s Then        Function = *s        DeAllocate( s )    End IfEnd Function`

test.bas added a few examples of shl and shr

Code: Select all

`#Include Once "gmp_int.bi"Dim as gmp_int i, two = 2 'if the number is small' if the number is larger than FB integer then use: two = gmp_int("2")dim as integer k' Powers of twoprint "Some powers of two"for i = 0 to 128   print "2 ^ " & i & " = " & two ^ inext iprintprint "casting a gmp_int to a FreeBASIC Integer"print "this should only be done if you know the gmp_int will fit in a Integer"k = twoprint "k = two ->";kprinti = "1" + string(35, "0") i = i + 1Print i; " / 3 = "; i / 3Printi = gmp_int(string(40,"1"), 2)Print "&B" + String(40,"1") + " = ";iPrint Print i; " shr 39 = "; i Shr 39Printi = 1 Print i; " shl 128 = "; i Shl 128Printi = "1234567890"Print i; " in base 62 = "; gmp_int_2_base(i, 62)Print i; " in base 16 = "; gmp_int_2_base(i, 16)Print i; " in base 8  = "; gmp_int_2_base(i, 8)Print i; " in base 2  = "; gmp_int_2_base(i, 2)Printi = gmp_int("09azAZ", 62)Print "09azAZ(62) = "; iSleep`
Makoto WATANABE
Posts: 196
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: Always for me a Big question

Dear srvaldez
Dear frisian

You two have always touched my interest and gave me perfect teachings.
I am very grateful.

Code: Select all

`#Include Once "gmp_int.bi"Dim As gmp_int a = gmp_int("123456789123456789123456789123456789123456789123456789")Dim As gmp_int b = gmp_int("987654321987654321987654321987654321987654321987654321") ,cc = a + b + 1Print cSleep`

Result: 1111111111111111111111111111111111111111111111111111111
srvaldez
Posts: 2578
Joined: Sep 25, 2005 21:54

Re: Always for me a Big question

thank you frisian for the update, perhaps you should post it in the tips & tricks section?
student1347
Posts: 49
Joined: Dec 16, 2011 3:48

Re: Always for me a Big question

Thanks as many as BIG NUMBERS for all the answers.But why gmp_int.bi does not work with fb version 0.24.0 but it is ok with version 1.05.0.thank you all again.
dodicat
Posts: 6766
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Always for me a Big question

If you have put libgmp.a into lib/win32 in version 0.24.0 then you should remove or rename libgmp.dll.a from the same folder.
student1347
Posts: 49
Joined: Dec 16, 2011 3:48

Re: Always for me a Big question

Dear dodicat I did it but It again does not work.here is the errors
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(136) error 9: Expected expression, found 'function' in 'declare sub __gmp_get_memory_functions(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(137) error 9: Expected expression, found 'function' in 'declare sub mp_get_memory_functions alias "__gmp_get_memory_functions"(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'