Save the files using the names given, then compile using:
fbc test.bas gmp_int.bas
I haven't included some of the more advanced stuff like kronecker, as to be honest I don't know what it is :), however it covers most of the regular stuff like +-*/\mod, and also shows the usage of the new feature for FOR loops using a TYPE.
You will need GMP for it to work, on linux you can either build yourself, or get a package the usual way, for windows I found this page http://cs.nyu.edu/exact/core/gmp/ that seems to offer the DLL compiled, its probably best to get the dynamic for mingw version (I don't use windows so i can't test that)
test.bas
Code: Select all
#include "gmp_int.bi"
' Powers of two
print "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 FOR
print "Big numbers in FOR loop"
for i as gmp_int = gmp_int("10000000000000000") to gmp_int("50000000000000000") step gmp_int("20000000000000000")
print i
next 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 )
gmp_int.bas
Code: Select all
#include "gmp_int.bi"
' 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 operator
'::::::::
operator gmp_int.cast ( ) as string
operator = getString( 10 )
end operator
'::::::::
operator gmp_int.for ( byref stp as gmp_int )
'' note: if STEP isn't explicitly given, it will be NULL
if @stp = 0 then
is_up = -1
else
is_up = (stp > 0)
end if
end operator
'::::::::
operator gmp_int.step ( byref stp as gmp_int )
this += stp
end operator
'::::::::
operator gmp_int.next ( byref end_cond as gmp_int ) as integer
if is_up then
operator = this <= end_cond
else
operator = this >= end_cond
end if
end 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 if
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end 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 = result
end operator
'::::::::
operator - ( byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_neg( result.num, rhs.num )
operator = result
end operator
'::::::::
operator not ( byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_com( result.num, rhs.num )
operator = result
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
'::::::::
operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) <> 0)
end operator
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 string
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 function getString ( byval _base as integer = 10 ) as string
num as mpz_ptr = 0
is_up as integer
end type
declare operator + ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator - ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator * ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator \ ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator / ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator ^ ( byref lhs as gmp_int, byval rhs as gmp_int ) as gmp_int
declare operator mod ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator and ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator or ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator xor ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator - ( byref rhs as gmp_int ) as gmp_int
declare operator not ( byref rhs as gmp_int ) as gmp_int
declare operator = ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator < ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator > ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator <= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator >= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
#endif '__GMP_INT_BI__