diff --git a/external/gmp_wrapper.c b/external/gmp_wrapper.c index 71428ba0c099c..59aaf307f2395 100644 --- a/external/gmp_wrapper.c +++ b/external/gmp_wrapper.c @@ -53,28 +53,112 @@ extern int _jl_mpz_cmp(mpz_t* op1, mpz_t* op2) { return mpz_cmp(*op1, *op2); } +extern void _jl_mpz_pow_ui(mpz_t* rop, mpz_t* base, unsigned long int exp) { + mpz_pow_ui(*rop, *base, exp); +} + +extern void _jl_mpz_pow_sqrt(mpz_t* rop, mpz_t* op) { + mpz_sqrt(*rop, *op); +} + extern char* _jl_mpz_printf(mpz_t* rop) { - char** pp; - gmp_asprintf(pp, "%Zd", *rop); - return *pp; + char* pp; + int s = gmp_asprintf(&pp, "%Zd", *rop); + return pp; +} + +//// MPF + +extern void* _jl_mpf_init() +{ + mpf_t* flt = malloc(sizeof(mpf_t)); + mpf_init(*flt); + return flt; +} + +extern void _jl_mpf_clear(mpf_t* rop) { + mpf_clear(*rop); +} + +extern void _jl_mpf_set_string(mpf_t* rop, char* s) { + mpf_set_str(*rop, s, 0); +} + +extern void _jl_mpf_set_ui(mpf_t* rop, unsigned long int op) { + mpf_set_ui(*rop, op); +} + +extern void _jl_mpf_set_si(mpf_t* rop, signed long int op) { + mpf_set_si(*rop, op); +} + +extern void _jl_mpf_set_d(mpf_t* rop, double op) { + mpf_set_d(*rop, op); +} + +extern void _jl_mpf_set_z(mpf_t* rop, mpz_t* op) { + mpf_set_z(*rop, *op); +} + +extern void _jl_mpf_add(mpf_t* rop, mpf_t* op1, mpf_t* op2) { + mpf_add(*rop, *op1, *op2); +} + +extern void _jl_mpf_sub(mpf_t* rop, mpf_t* op1, mpf_t* op2) { + mpf_sub(*rop, *op1, *op2); +} + +extern void _jl_mpf_mul(mpf_t* rop, mpf_t* op1, mpf_t* op2) { + mpf_mul(*rop, *op1, *op2); +} + +extern void _jl_mpf_div(mpf_t* rop, mpf_t* op1, mpf_t* op2) { + mpf_div(*rop, *op1, *op2); +} + +extern void _jl_mpf_neg(mpf_t* rop, mpf_t* op1) { + mpf_neg(*rop, *op1); +} + +extern void _jl_mpf_abs(mpf_t* rop, mpf_t* op1) { + mpf_abs(*rop, *op1); } +extern int _jl_mpf_cmp(mpf_t* op1, mpf_t* op2) { + return mpf_cmp(*op1, *op2); +} + +extern void _jl_mpf_pow_ui(mpf_t* rop, mpf_t* base, unsigned long int exp) { + mpf_pow_ui(*rop, *base, exp); +} + +extern void _jl_mpf_sqrt(mpf_t* rop, mpf_t* op) { + mpf_sqrt(*rop, *op); +} + +extern char* _jl_mpf_printf(mpf_t* rop) { + char* pp; + gmp_asprintf(&pp, "%.Ff", *rop); + return pp; +} + + //Quick and dirty test of the gmp wrapper code int main( int argc, const char* argv[] ) { - void* rop = _jl_mpz_init(); - - void* op1 = _jl_mpz_init(); - _jl_mpz_set_string(op1, "123456789123456789123456789123456789"); + void* rop = _jl_mpf_init(); + void* op1 = _jl_mpf_init(); + + _jl_mpf_set_string(op1, "123456789123456789123456789123456789"); - void* op2 = _jl_mpz_init(); - _jl_mpz_set_string(op2, "12345"); + void* op2 = _jl_mpf_init(); + _jl_mpf_set_string(op2, "12345"); - _jl_mpz_add(rop, op1, op2); + _jl_mpf_add(rop, op1, op2); - printf("The sum is %s\n", _jl_mpz_printf(rop)); + printf("The sum is %s\n", _jl_mpf_printf(rop)); - _jl_mpz_clear(rop); + _jl_mpf_clear(rop); } diff --git a/jl/bigfloat.jl b/jl/bigfloat.jl new file mode 100644 index 0000000000000..2f6cb57b9ecba --- /dev/null +++ b/jl/bigfloat.jl @@ -0,0 +1,142 @@ +_jl_libgmp_wrapper = dlopen("libgmp_wrapper") + +load("bigint.jl") + +type BigFloat <: Float + mpf::Ptr{Void} + + function BigFloat(x::String) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_string), Void, (Ptr{Void}, Ptr{Uint8}), z, cstring(x)) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end + + function BigFloat(x::Float) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_d), Void, (Ptr{Void}, Float), z, x) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end + + function BigFloat(x::Uint) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_ui), Void, (Ptr{Void}, Uint), z, x) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end + + function BigFloat(x::Int) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_si), Void, (Ptr{Void}, Int), z, x) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end + + function BigFloat(x::BigInt) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_z), Void, (Ptr{Void}, Ptr{Void}), z, x.mpz) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end + + function BigFloat(z::Ptr{Void}) + b = new(z) + finalizer(b, _jl_BigFloat_clear) + b + end +end + +convert(::Type{BigFloat}, x::Int8) = BigFloat(x) +convert(::Type{BigFloat}, x::Int16) = BigFloat(x) +convert(::Type{BigFloat}, x::Int32) = BigFloat(x) +convert(::Type{BigFloat}, x::Int64) = BigFloat(x) +convert(::Type{BigFloat}, x::Uint8) = BigFloat(x) +convert(::Type{BigFloat}, x::Uint16) = BigFloat(x) +convert(::Type{BigFloat}, x::Uint32) = BigFloat(x) +convert(::Type{BigFloat}, x::Uint64) = BigFloat(x) + +convert(::Type{BigFloat}, x::Float) = BigFloat(x) +convert(::Type{BigFloat}, x::Float32) = BigFloat(x) +convert(::Type{BigFloat}, x::Float64) = BigFloat(x) + +promote_rule(::Type{BigFloat}, ::Type{Float32}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Float64}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Int8}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Int16}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Int32}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Int64}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Uint8}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Uint16}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Uint32}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{Uint64}) = BigFloat + +function +(x::BigFloat, y::BigFloat) + z= _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_add), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) + BigFloat(z) +end + +function -(x::BigFloat) + z= _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_neg), Void, (Ptr{Void}, Ptr{Void}), z, x.mpf) + BigFloat(z) +end + +function -(x::BigFloat, y::BigFloat) + z= _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_sub), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) + BigFloat(z) +end + +function *(x::BigFloat, y::BigFloat) + z= _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_mul), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) + BigFloat(z) +end + +function div (x::BigFloat, y::BigFloat) + z= _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_div), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) + BigFloat(z) +end + +function cmp(x::BigFloat, y::BigFloat) + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_cmp), Int, (Ptr{Void}, Ptr{Void}), x.mpf, y.mpf) +end + +function pow(x::BigFloat, y::Uint) + z = _jl_BigFloat_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_pow_ui), Void, (Ptr{Void}, Ptr{Void}, Uint), z, x.mpf, y) + BigFloat(z) +end + +==(x::BigFloat, y::BigFloat) = cmp(x,y) == 0 +<=(x::BigFloat, y::BigFloat) = cmp(x,y) <= 0 +>=(x::BigFloat, y::BigFloat) = cmp(x,y) >= 0 +<(x::BigFloat, y::BigFloat) = cmp(x,y) < 0 +>(x::BigFloat, y::BigFloat) = cmp(x,y) > 0 + +function string(x::BigFloat) + s=ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_printf), Ptr{Uint8}, (Ptr{Void},), x.mpf) + ret = cstring(s) #This copies s. + _jl_free(convert(Ptr{Void},s)) + ret +end + +function show(x::BigFloat) + print (string(x)) +end + +function _jl_BigFloat_clear(x::BigFloat) + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_clear), Void, (Ptr{Void},), x.mpf) +end + +function _jl_BigFloat_init() + return ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_init), Ptr{Void}, ()) +end \ No newline at end of file diff --git a/jl/bigint.jl b/jl/bigint.jl index 609dec323d312..bf0f30848d224 100644 --- a/jl/bigint.jl +++ b/jl/bigint.jl @@ -92,6 +92,12 @@ function sqrt(x::BigInt) BigInt(z) end +function pow(x::BigInt, y::Uint) + z = _jl_bigint_init() + ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_pow_ui), Void, (Ptr{Void}, Ptr{Void}, Uint), z, x.mpz, y) + BigInt(z) +end + ==(x::BigInt, y::BigInt) = cmp(x,y) == 0 <=(x::BigInt, y::BigInt) = cmp(x,y) <= 0 >=(x::BigInt, y::BigInt) = cmp(x,y) >= 0 diff --git a/test/bigfloat.jl b/test/bigfloat.jl new file mode 100644 index 0000000000000..08d522312cf5c --- /dev/null +++ b/test/bigfloat.jl @@ -0,0 +1,34 @@ + +load ("../jl/bigfloat.jl") +a=BigFloat("12.34567890121") +b=BigFloat("12.34567890122") + +@assert typeof(a+0.00000000001) == BigFloat +@assert a+0.00000000001 == b +@assert b == a+0.00000000001 +@assert !(b == a) +@assert b > a +@assert b >= a +@assert !(b < a) +@assert !(b <= a) + +c = BigFloat("24.69135780242") +@assert typeof(a * 2) == BigFloat +@assert a*2 == c +@assert c-a == a +@assert c == a + a +@assert c+1 == a+b + +d = BigFloat("-24.69135780242") +@assert typeof(d) == BigFloat +@assert d == -c + +#Multiple calls for sanity check, since we're doing direct memory manipulation +@assert string(a) == "12.34567890121" +@assert string(b) == "12.34567890122" +@assert string(c) == "24.69135780242" +@assert string(d) == "-24.69135780242" + +@assert div(BigFloat(3), BigFloat(2)) == BigFloat(1) +@assert rem(BigFloat(3), BigFloat(2)) == BigFloat(1) + diff --git a/test/bigint.jl b/test/bigint.jl index a505aaa1ee5c1..a5f6284c2e492 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -3,7 +3,6 @@ load ("../jl/bigint.jl") a=BigInt("123456789012345678901234567890") b=BigInt("123456789012345678901234567891") - @assert typeof(a+1) == BigInt @assert a+1 == b @assert b == a+1