Skip to content

Commit

Permalink
Merge pull request #3065 from andrioni/master
Browse files Browse the repository at this point in the history
Add `sum` methods for BigInts and BigFloats
  • Loading branch information
JeffBezanson committed May 9, 2013
2 parents 002f747 + 363cf61 commit 4978a52
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 10 deletions.
39 changes: 38 additions & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export BigInt
import Base: *, +, -, /, <, <<, >>, <=, ==, >, >=, ^, (~), (&), (|), ($),
binomial, cmp, convert, div, factorial, fld, gcd, gcdx, lcm, mod,
ndigits, promote_rule, rem, show, isqrt, string, isprime, powermod,
widemul
widemul, sum

type BigInt <: Integer
alloc::Cint
Expand Down Expand Up @@ -100,6 +100,33 @@ for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul),
end
end

# More efficient commutative operations
for (fJ, fC) in ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:$, :xor))
@eval begin
function ($fJ)(a::BigInt, b::BigInt, c::BigInt)
z = BigInt()
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c)
return z
end
function ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt)
z = BigInt()
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &d)
return z
end
function ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt)
z = BigInt()
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &d)
ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &e)
return z
end
end
end

# Basic arithmetic without promotion
function +(x::BigInt, c::Culong)
z = BigInt()
Expand Down Expand Up @@ -227,6 +254,16 @@ function gcdx(a::BigInt, b::BigInt)
BigInt(g), BigInt(s), BigInt(t)
end

function sum(arr::AbstractArray{BigInt})
n = BigInt(0)
for i in arr
ccall((:__gmpz_add, :libgmp), Void,
(Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}),
&n, &n, &i)
end
return n
end

function factorial(bn::BigInt)
if bn<0
return BigInt(0)
Expand Down
45 changes: 36 additions & 9 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,33 @@ for (fJ, fC) in ((:+,:add), (:-,:sub), (:*,:mul), (:/,:div), (:^, :pow))
end
end

# More efficient commutative operations
for (fJ, fC, fI) in ((:+, :add, 0), (:*, :mul, 1))
@eval begin
function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat)
z = BigFloat()
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &a, &b, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &c, ROUNDING_MODE[end])
return z
end
function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat)
z = BigFloat()
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &a, &b, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &c, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &d, ROUNDING_MODE[end])
return z
end
function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat)
z = BigFloat()
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &a, &b, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &c, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &d, ROUNDING_MODE[end])
ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &z, &e, ROUNDING_MODE[end])
return z
end
end
end

function -(x::BigFloat)
z = BigFloat()
ccall((:mpfr_neg, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, ROUNDING_MODE[end])
Expand Down Expand Up @@ -496,15 +523,15 @@ function rem(x::BigFloat, y::BigFloat)
return z
end

# function sum{T<:BigFloat}(arr::AbstractArray{T})
# z = BigFloat()
# n = length(arr)
# ptrarr = [pointer(&x) for x in arr]
# ccall((:mpfr_sum, :libmpfr), Int32,
# (Ptr{BigFloat}, Ptr{Void}, Culong, Int32),
# &z, ptrarr, n, ROUNDING_MODE[1])
# return z
# end
function sum(arr::AbstractArray{BigFloat})
z = BigFloat(0)
for i in arr
ccall((:mpfr_add, :libmpfr), Int32,
(Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Cint),
&z, &z, &i, 0)
end
return z
end

# Functions for which NaN results are converted to DomainError, following Base
for f in (:sin,:cos,:tan,:sec,:csc,
Expand Down
42 changes: 42 additions & 0 deletions test/bigint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,48 @@ end
@test binomial(BigInt(-53), 42) == BigInt("959509335087854414441273718")
@test binomial(BigInt(113), BigInt(42)) == BigInt("18672199984318438125634054194360")

a = rand(1:100, 10000)
b = map(BigInt, a)
@test sum(a) == sum(b)

# Iterated arithmetic
a = BigInt("315135")
b = BigInt("12412")
c = BigInt("3426495623485904783478347")
d = BigInt("-1398984130")
f = BigInt("2413804710837418037418307081437315263635345357386985747464")
g = BigInt("-1")

@test +(a, b) == BigInt("327547")
@test +(a, b, c) == BigInt("3426495623485904783805894")
@test +(a, b, c, d) == BigInt("3426495623485903384821764")
@test +(a, b, c, d, f) == BigInt("2413804710837418037418307081437318690130968843290370569228")
@test +(a, b, c, d, f, g) == BigInt("2413804710837418037418307081437318690130968843290370569227")

@test *(a, b) == BigInt("3911455620")
@test *(a, b, c) == BigInt("13402585563389346256121263521460140")
@test *(a, b, c, d) == BigInt("-18750004504148804423388563022070650287578200")
@test *(a, b, c, d, f) == BigInt("-45258849200337190631492857400003938881995610529251881450243326128168934937055005474972396281351684800")
@test *(a, b, c, d, f, g) == BigInt("45258849200337190631492857400003938881995610529251881450243326128168934937055005474972396281351684800")

@test ($)(a, b) == BigInt("327299")
@test ($)(a, b, c) == BigInt("3426495623485904783798472")
@test ($)(a, b, c, d) == BigInt("-3426495623485906178489610")
@test ($)(a, b, c, d, f) == BigInt("-2413804710837418037418307081437316711364709261074607933698")
@test ($)(a, b, c, d, f, g) == BigInt("2413804710837418037418307081437316711364709261074607933697")

@test (&)(a, b) == BigInt("124")
@test (&)(a, b, c) == BigInt("72")
@test (&)(a, b, c, d) == BigInt("8")
@test (&)(a, b, c, d, f) == BigInt("8")
@test (&)(a, b, c, d, f, g) == BigInt("8")

@test (|)(a, b) == BigInt("327423")
@test (|)(a, b, c) == BigInt("3426495623485904783802111")
@test (|)(a, b, c, d) == BigInt("-1396834561")
@test (|)(a, b, c, d, f) == BigInt("-1358954753")
@test (|)(a, b, c, d, f, g) == BigInt("-1")

@test isprime(BigInt(1000000007))
@test isprime(BigInt(1000000007), 1)
@test isprime(BigInt(10000000019))
Expand Down
20 changes: 20 additions & 0 deletions test/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ x = BigFloat(9)
y = BigFloat(6)
@test x / y == BigFloat(9/6)

# iterated arithmetic
a = BigFloat(12.25)
b = BigFloat(23.125)
c = BigFloat(-7)
d = BigFloat(-12.75)
f = BigFloat(2.0625)
g = BigFloat(0.03125)
@test +(a, b) == BigFloat(35.375)
@test +(a, b, c) == BigFloat(28.375)
@test +(a, b, c, d) == BigFloat(15.625)
@test +(a, b, c, d, f) == BigFloat(17.6875)
@test +(a, b, c, d, f, g) == BigFloat(17.71875)

@test *(a, b) == BigFloat("2.8328125e+02")
@test *(a, b, c) == BigFloat("-1.98296875e+03")
@test *(a, b, c, d) == BigFloat("2.52828515625e+04")
@test *(a, b, c, d, f) == BigFloat("5.214588134765625e+04")
@test *(a, b, c, d, f, g) == BigFloat("1.6295587921142578125e+03")

# < / > / <= / >=
x = BigFloat(12)
y = BigFloat(42)
Expand Down Expand Up @@ -241,6 +260,7 @@ w = BigFloat(4)
@test sum([x,y,z,w]) == BigFloat(10)
big_array = ones(BigFloat, 100)
@test sum(big_array) == BigFloat(100)
@test sum(BigFloat[]) == BigFloat(0)

# promotion
# the array converts everyone to the DEFAULT_PRECISION!
Expand Down

0 comments on commit 4978a52

Please sign in to comment.