From 9aadbeb0739f6d05f46b959006bd44892707404f Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Fri, 11 Mar 2022 19:38:32 +0300 Subject: [PATCH 01/15] add inplace Rational{BigInt} arithmetic --- base/gmp.jl | 31 ++++++++++++++++------ test/gmp.jl | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 8 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 435a0a0954ce9..bebe1a1ae5fd6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -915,43 +915,46 @@ function Rational{BigInt}(num::BigInt, den::BigInt) return sync_rational!(xq) end -function Base.:+(x::Rational{BigInt}, y::Rational{BigInt}) +function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && iszero(y.den) && isneg(x.num) != isneg(y.num) throw(DivideError()) end return iszero(x.den) ? x : y end - zq = _MPQ() + zq = _MPQ(z) ccall((:__gmpq_add, :libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end -function Base.:-(x::Rational{BigInt}, y::Rational{BigInt}) + +function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && iszero(y.den) && isneg(x.num) == isneg(y.num) throw(DivideError()) end return iszero(x.den) ? x : -y end - zq = _MPQ() + zq = _MPQ(z) ccall((:__gmpq_sub, :libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end -function Base.:*(x::Rational{BigInt}, y::Rational{BigInt}) + +function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return xor(isneg(x.num),isneg(y.num)) ? -one(BigInt)//zero(BigInt) : one(BigInt)//zero(BigInt) end - zq = _MPQ() + zq = _MPQ(z) ccall((:__gmpq_mul, :libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end -function Base.://(x::Rational{BigInt}, y::Rational{BigInt}) + +function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) @@ -965,12 +968,24 @@ function Base.://(x::Rational{BigInt}, y::Rational{BigInt}) end return (isneg(x.num) ? -one(BigInt) : one(BigInt)) // y.num end - zq = _MPQ() + zq = _MPQ(z) ccall((:__gmpq_div, :libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end +for (fJ, fC) in ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) + fC! = Symbol(fC, :!) + @eval begin + ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = $fC!(x, x, y) + ($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = $fC!(unsafe_rational(BigInt(), BigInt()), x, y) + end +end + +function cmp(x::Rational{BigInt}, y::Rational{BigInt}) + Int(ccall((:__gmpq_cmp, :libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) +end + end # MPQ module end # module diff --git a/test/gmp.jl b/test/gmp.jl index 2eb1e9faf47da..d944c9537b678 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -542,3 +542,78 @@ end @test T(big"2"^(n+1) - big"2"^(n-precision(T)) - 1) === floatmax(T) end end + +a = Rational{BigInt}(12345678901234567890123456789, 987654321987654320) +b = Rational{BigInt}(12345678902222222212111111109, 987654321987654320) +c = Rational{BigInt}(24691357802469135780246913578, 987654321987654320) +d = Rational{BigInt}(- 12345678901234567890123456789, 493827160993827160) +e = Rational{BigInt}(12345678901234567890123456789, 12345678902222222212111111109) +@testset "big rational basics" begin + @test a+BigInt(1) == b + @test typeof(a+1) == Rational{BigInt} + @test a+1 == b + @test isequal(a+1, b) + @test b == a+1 + @test !(b == a) + @test b > a + @test b >= a + @test !(b < a) + @test !(b <= a) + + @test typeof(a * 2) == Rational{BigInt} + @test a*2 == c + @test c-a == a + @test c == a + a + @test c+1 == a+b + + @test typeof(d) == Rational{BigInt} + @test d == -c + + + @test e == a // b + + @testset "gmp cmp" begin + @test cmp(b, a) == 1 + @test cmp(a, b) == -1 + @test cmp(c-a, a) == 0 + end + + @testset "division errors" begin + oz = Rational{BigInt}(0, 1) + zo = Rational{BigInt}(1, 0) + + @test oz + oz == 2 * oz + @test oz // zo == oz + @test zo // oz == zo + + @test_throws DivideError() zo - zo + @test_throws DivideError() zo + (-zo) + @test_throws DivideError() zo * oz + @test_throws DivideError() oz // oz + @test_throws DivideError() zo // zo + end +end + + +a = Rational{BigInt}(1, 2) +b = Rational{BigInt}(-1, 3) +c = Rational{BigInt}(3, 2) +t = Rational{BigInt}(0, 1) +@testset "big rational inplace" begin + @test Base.GMP.MPQ.add!(t, a, b) == Rational{BigInt}(1, 6) + @test t == Rational{BigInt}(1, 6) + @test Base.GMP.MPQ.add!(t, t) == Rational{BigInt}(1, 3) + + @test iszero(Base.GMP.MPQ.sub!(t, t)) + @test Base.GMP.MPQ.sub!(t, b, c) == Rational{BigInt}(-11, 6) + @test t == Rational{BigInt}(-11, 6) + + @test Base.GMP.MPQ.mul!(t, a, b) == Rational{BigInt}(-1, 6) + @test t == Rational{BigInt}(-1, 6) + @test Base.GMP.MPQ.mul!(t, t) == Rational{BigInt}(1, 36) + @test t == Rational{BigInt}(1, 36) + @test iszero(Base.GMP.MPQ.mul!(t, Rational{BigInt}(0))) + + @test Base.GMP.MPQ.div!(t, a, b) == Rational{BigInt}(-3, 2) + @test t == Rational{BigInt}(-3, 2) +end From 27b9332c5217e6cef4fc0cf38c4ac6c71b3ba9f8 Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Fri, 11 Mar 2022 19:43:08 +0300 Subject: [PATCH 02/15] use cmp from gmp by default --- base/gmp.jl | 2 +- test/gmp.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index bebe1a1ae5fd6..93b462314068c 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -982,7 +982,7 @@ for (fJ, fC) in ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) end end -function cmp(x::Rational{BigInt}, y::Rational{BigInt}) +function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, :libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end diff --git a/test/gmp.jl b/test/gmp.jl index d944c9537b678..f40e79c7d8572 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -573,9 +573,9 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 @test e == a // b @testset "gmp cmp" begin - @test cmp(b, a) == 1 - @test cmp(a, b) == -1 - @test cmp(c-a, a) == 0 + @test Base.GMP.MPQ.cmp(b, a) == 1 + @test Base.GMP.MPQ.cmp(a, b) == -1 + @test Base.GMP.MPQ.cmp(c-a, a) == 0 end @testset "division errors" begin From 5e4500df450730e9930845fcd2f541f807f7efdd Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Sat, 12 Mar 2022 19:08:12 +0300 Subject: [PATCH 03/15] fix infinity bug, added `set` methods --- base/gmp.jl | 50 +++++++++++++++++++++++++++----- test/gmp.jl | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 7 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 93b462314068c..283567ea83706 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -875,6 +875,8 @@ module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, isneg +gmpq(op::Symbol) = (Symbol(:__gmpq_, op), :libgmp) + mutable struct _MPQ num_alloc::Cint num_size::Cint @@ -915,12 +917,45 @@ function Rational{BigInt}(num::BigInt, den::BigInt) return sync_rational!(xq) end +# define set, set_ui, set_si, set_z, and their inplace versions +function set!(z::Rational{BigInt}, x::Rational{BigInt}) + zq = _MPQ(z) + ccall((:__gmpq_set, :libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) + return sync_rational!(zq) +end + +function set_z!(z::Rational{BigInt}, x::BigInt) + zq = _MPQ(z) + ccall((:__gmpq_set_z, :libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) + return sync_rational!(zq) +end + +for (op, T) in ((:set, Rational{BigInt}), (:set_z, BigInt)) + op! = Symbol(op, :!) + @eval $op(a::$T) = $op!(unsafe_rational(BigInt(), BigInt()), a) +end + +# note that rationals returned from set_ui and set_si are not checked, +# set_ui(0, 0) will return 0//0 without errors, just like unsafe_rational +for (op, T1, T2) in ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) + op! = Symbol(op, :!) + @eval begin + function $op!(z::Rational{BigInt}, a, b) + zq = _MPQ(z) + ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) + return sync_rational!(zq) + end + $op(a, b) = $op!(unsafe_rational(BigInt(), BigInt()), a, b) + end +end + +# define add, sub, mul, div, and their inplace versions function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && iszero(y.den) && isneg(x.num) != isneg(y.num) throw(DivideError()) end - return iszero(x.den) ? x : y + return set!(z, iszero(x.den) ? x : y) end zq = _MPQ(z) ccall((:__gmpq_add, :libgmp), Cvoid, @@ -933,7 +968,7 @@ function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) && iszero(y.den) && isneg(x.num) == isneg(y.num) throw(DivideError()) end - return iszero(x.den) ? x : -y + return set!(z, iszero(x.den) ? x : -y) end zq = _MPQ(z) ccall((:__gmpq_sub, :libgmp), Cvoid, @@ -946,7 +981,8 @@ function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.num) || iszero(y.num) throw(DivideError()) end - return xor(isneg(x.num),isneg(y.num)) ? -one(BigInt)//zero(BigInt) : one(BigInt)//zero(BigInt) + a, b = xor(isneg(x.num),isneg(y.num)) ? (-1, 0) : (1, 0) + return set_si!(z, a, b) end zq = _MPQ(z) ccall((:__gmpq_mul, :libgmp), Cvoid, @@ -959,14 +995,14 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(y.den) throw(DivideError()) end - return isneg(y.num) ? -x : x + return set!(z, isneg(y.num) ? -x : x) elseif iszero(y.den) - return y.den // y.num + return set!(z, y.den // y.num) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end - return (isneg(x.num) ? -one(BigInt) : one(BigInt)) // y.num + return set!(z, (isneg(x.num) ? -one(BigInt) : one(BigInt)) // y.num) end zq = _MPQ(z) ccall((:__gmpq_div, :libgmp), Cvoid, @@ -978,7 +1014,7 @@ for (fJ, fC) in ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = $fC!(x, x, y) - ($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = $fC!(unsafe_rational(BigInt(), BigInt()), x, y) + (Base.$fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = $fC!(unsafe_rational(BigInt(), BigInt()), x, y) end end diff --git a/test/gmp.jl b/test/gmp.jl index f40e79c7d8572..c0e642f074bf8 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -592,6 +592,23 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 @test_throws DivideError() oz // oz @test_throws DivideError() zo // zo end + + @testset "big infinities" begin + oz = Rational{BigInt}(1, 0) + zo = Rational{BigInt}(0, 1) + o = Rational{BigInt}(1, 1) + + @test oz + zo == oz + @test zo - oz == -oz + @test zo + (-oz) == -oz + @test -oz + zo == -oz + + @test (-oz) * (-oz) == oz + @test (-oz) * oz == -oz + + @test o // zo == oz + @test (-o) // zo == -oz + end end @@ -599,12 +616,17 @@ a = Rational{BigInt}(1, 2) b = Rational{BigInt}(-1, 3) c = Rational{BigInt}(3, 2) t = Rational{BigInt}(0, 1) +aa = copy(a) +bb = copy(b) +cc = copy(c) @testset "big rational inplace" begin @test Base.GMP.MPQ.add!(t, a, b) == Rational{BigInt}(1, 6) @test t == Rational{BigInt}(1, 6) @test Base.GMP.MPQ.add!(t, t) == Rational{BigInt}(1, 3) + @test t == Rational{BigInt}(1, 3) @test iszero(Base.GMP.MPQ.sub!(t, t)) + @test iszero(t) @test Base.GMP.MPQ.sub!(t, b, c) == Rational{BigInt}(-11, 6) @test t == Rational{BigInt}(-11, 6) @@ -616,4 +638,65 @@ t = Rational{BigInt}(0, 1) @test Base.GMP.MPQ.div!(t, a, b) == Rational{BigInt}(-3, 2) @test t == Rational{BigInt}(-3, 2) + @test Base.GMP.MPQ.div!(t, a) == Rational{BigInt}(-3, 1) + @test t == Rational{BigInt}(-3, 1) + + @test aa == a && bb == b && cc == c + + @testset "set" begin + @test Base.GMP.MPQ.set!(a, b) == b + @test a == b == bb + + Base.GMP.MPQ.add!(a, b, c) + @test b == bb + + @test Base.GMP.MPQ.set_z!(a, BigInt(0)) == BigInt(0) + @test iszero(a) + @test Base.GMP.MPQ.set_z!(a, BigInt(3)) == BigInt(3) + @test a == BigInt(3) + + @test Base.GMP.MPQ.set_ui(1, 2) == Rational{BigInt}(1, 2) + @test Base.GMP.MPQ.set_ui(0, 1) == Rational{BigInt}(0, 1) + @test Base.GMP.MPQ.set_ui!(a, 1, 2) == Rational{BigInt}(1, 2) + @test a == Rational{BigInt}(1, 2) + + @test Base.GMP.MPQ.set_si(1, 2) == Rational{BigInt}(1, 2) + @test Base.GMP.MPQ.set_si(-1, 2) == Rational{BigInt}(-1, 2) + @test Base.GMP.MPQ.set_si!(a, -1, 2) == Rational{BigInt}(-1, 2) + @test a == Rational{BigInt}(-1, 2) + end + + @testset "infinities" begin + oz = Rational{BigInt}(1, 0) + zo = Rational{BigInt}(0, 1) + oo = Rational{BigInt}(1, 1) + + @test Base.GMP.MPQ.add!(zo, oz) == oz + @test zo == oz + zo = Rational{BigInt}(0, 1) + + @test Base.GMP.MPQ.sub!(zo, oz) == -oz + @test zo == -oz + zo = Rational{BigInt}(0, 1) + + @test Base.GMP.MPQ.add!(zo, -oz) == -oz + @test zo == -oz + zo = Rational{BigInt}(0, 1) + + @test Base.GMP.MPQ.sub!(zo, oz) == -oz + @test zo == -oz + zo = Rational{BigInt}(0, 1) + + @test Base.GMP.MPQ.mul!(-oz, -oz) == oz + @test Base.GMP.MPQ.mul!(-oz, oz) == -oz + @test Base.GMP.MPQ.mul!(oz, -oz) == -Rational{BigInt}(1, 0) + @test oz == -Rational{BigInt}(1, 0) + oz = Rational{BigInt}(1, 0) + + @test Base.GMP.MPQ.div!(oo, zo) == oz + @test oo == oz + oo = Rational{BigInt}(1, 1) + + @test Base.GMP.MPQ.div!(-oo, zo) == -oz + end end From 3b3c9f019af205786369d34861407e2191f8618c Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Sat, 12 Mar 2022 20:28:00 +0300 Subject: [PATCH 04/15] Update base/gmp.jl Co-authored-by: Lionel Zoubritzky --- base/gmp.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 283567ea83706..0312cbd1e17c2 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -968,7 +968,8 @@ function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) && iszero(y.den) && isneg(x.num) == isneg(y.num) throw(DivideError()) end - return set!(z, iszero(x.den) ? x : -y) + iszero(x.den) && return set!(z, x) + return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, :libgmp), Cvoid, From 90d49a4d6f241ae61c91b6ae16ab7a6b8b27c954 Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Sat, 12 Mar 2022 20:32:51 +0300 Subject: [PATCH 05/15] Update base/gmp.jl Co-authored-by: Lionel Zoubritzky --- base/gmp.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 0312cbd1e17c2..914851a87d3f2 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -996,7 +996,8 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(y.den) throw(DivideError()) end - return set!(z, isneg(y.num) ? -x : x) + isneg(y.num) || return set!(z, x) + return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set!(z, y.den // y.num) elseif iszero(y.num) From e11a338ffceb691e5901ffa6c0932c3d15a61824 Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Sat, 12 Mar 2022 20:33:45 +0300 Subject: [PATCH 06/15] Update base/gmp.jl Co-authored-by: Lionel Zoubritzky --- base/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 914851a87d3f2..09ae9bcc85968 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -999,7 +999,7 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) - return set!(z, y.den // y.num) + return set!(z, unsafe_rational(BigInt(), one(BigInt))) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) From addfa0a1ccb97264a85de42d9f3de46baf754b03 Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Sat, 12 Mar 2022 21:20:08 +0300 Subject: [PATCH 07/15] minor improvement --- base/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 09ae9bcc85968..1ecff50316c47 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -1004,7 +1004,7 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.num) throw(DivideError()) end - return set!(z, (isneg(x.num) ? -one(BigInt) : one(BigInt)) // y.num) + return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, :libgmp), Cvoid, From d2f241af7249c169cb6220d82ca9d8cf57f306fb Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Wed, 16 Mar 2022 16:18:38 +0300 Subject: [PATCH 08/15] Update base/gmp.jl Co-authored-by: Lionel Zoubritzky --- base/gmp.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 1ecff50316c47..0fcd475628781 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -982,8 +982,7 @@ function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.num) || iszero(y.num) throw(DivideError()) end - a, b = xor(isneg(x.num),isneg(y.num)) ? (-1, 0) : (1, 0) - return set_si!(z, a, b) + return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, :libgmp), Cvoid, From 89d58a0c749dbaffa4a468e6ae2a88836f5ef236 Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Wed, 16 Mar 2022 16:18:49 +0300 Subject: [PATCH 09/15] Update base/gmp.jl Co-authored-by: Lionel Zoubritzky --- base/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 0fcd475628781..e85af2ec980ec 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -998,7 +998,7 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) - return set!(z, unsafe_rational(BigInt(), one(BigInt))) + return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) From 6348a5e8ba233bea151a8ddf21becb20093b372d Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Wed, 16 Mar 2022 16:19:06 +0300 Subject: [PATCH 10/15] Update test/gmp.jl Co-authored-by: Lionel Zoubritzky --- test/gmp.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/gmp.jl b/test/gmp.jl index c0e642f074bf8..18f2c4ba97790 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -573,9 +573,9 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 @test e == a // b @testset "gmp cmp" begin - @test Base.GMP.MPQ.cmp(b, a) == 1 - @test Base.GMP.MPQ.cmp(a, b) == -1 - @test Base.GMP.MPQ.cmp(c-a, a) == 0 + @test Base.GMP.MPQ.cmp(b, a) == 1 + @test Base.GMP.MPQ.cmp(a, b) == -1 + @test Base.GMP.MPQ.cmp(a, a) == 0 end @testset "division errors" begin From e009eb2ef8606c57656b9ac53f3ffd489641bb8d Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Wed, 16 Mar 2022 16:21:39 +0300 Subject: [PATCH 11/15] Update test/gmp.jl Co-authored-by: Lionel Zoubritzky --- test/gmp.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/gmp.jl b/test/gmp.jl index 18f2c4ba97790..b88a5b1e2e9a1 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -683,8 +683,8 @@ cc = copy(c) @test zo == -oz zo = Rational{BigInt}(0, 1) - @test Base.GMP.MPQ.sub!(zo, oz) == -oz - @test zo == -oz + @test Base.GMP.MPQ.sub!(zo, -oz) == oz + @test zo == oz zo = Rational{BigInt}(0, 1) @test Base.GMP.MPQ.mul!(-oz, -oz) == oz From c2fc64a8d7f4320444ba0056fc2651c253fa492b Mon Sep 17 00:00:00 2001 From: Alexander Demin <60229118+sumiya11@users.noreply.github.com> Date: Wed, 16 Mar 2022 16:22:05 +0300 Subject: [PATCH 12/15] Update test/gmp.jl Co-authored-by: Lionel Zoubritzky --- test/gmp.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/gmp.jl b/test/gmp.jl index b88a5b1e2e9a1..b092fadc518cb 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -612,13 +612,13 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 end -a = Rational{BigInt}(1, 2) -b = Rational{BigInt}(-1, 3) -c = Rational{BigInt}(3, 2) +aa = 1//2 +bb = -1//3 +cc = 3//2 +a = Rational{BigInt}(aa) +b = Rational{BigInt}(bb) +c = Rational{BigInt}(cc) t = Rational{BigInt}(0, 1) -aa = copy(a) -bb = copy(b) -cc = copy(c) @testset "big rational inplace" begin @test Base.GMP.MPQ.add!(t, a, b) == Rational{BigInt}(1, 6) @test t == Rational{BigInt}(1, 6) From bbf7cdde4c7f9c4c23b5cbe9c38cfa0408524b93 Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Wed, 16 Mar 2022 16:37:12 +0300 Subject: [PATCH 13/15] improvement in 1//0 constructor --- base/gmp.jl | 3 +-- test/gmp.jl | 55 ++++++++++++++++++++++++++++------------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index e85af2ec980ec..35def4170ef15 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -909,8 +909,7 @@ end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) - num = isneg(num) ? -one(BigInt) : one(BigInt) - return unsafe_rational(BigInt, num, den) + return set_si!(z, flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, :libgmp), Cvoid, (mpq_t,), xq) diff --git a/test/gmp.jl b/test/gmp.jl index b092fadc518cb..dfe973b46ac82 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -608,6 +608,9 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 @test o // zo == oz @test (-o) // zo == -oz + + @test Rational{BigInt}(-1, 0) == -1//0 + @test Rational{BigInt}(1, 0) == 1//0 end end @@ -620,26 +623,26 @@ b = Rational{BigInt}(bb) c = Rational{BigInt}(cc) t = Rational{BigInt}(0, 1) @testset "big rational inplace" begin - @test Base.GMP.MPQ.add!(t, a, b) == Rational{BigInt}(1, 6) - @test t == Rational{BigInt}(1, 6) - @test Base.GMP.MPQ.add!(t, t) == Rational{BigInt}(1, 3) - @test t == Rational{BigInt}(1, 3) + @test Base.GMP.MPQ.add!(t, a, b) == 1//6 + @test t == 1//6 + @test Base.GMP.MPQ.add!(t, t) == 1//3 + @test t == 1//3 @test iszero(Base.GMP.MPQ.sub!(t, t)) @test iszero(t) - @test Base.GMP.MPQ.sub!(t, b, c) == Rational{BigInt}(-11, 6) - @test t == Rational{BigInt}(-11, 6) + @test Base.GMP.MPQ.sub!(t, b, c) == -11//6 + @test t == -11//6 - @test Base.GMP.MPQ.mul!(t, a, b) == Rational{BigInt}(-1, 6) - @test t == Rational{BigInt}(-1, 6) - @test Base.GMP.MPQ.mul!(t, t) == Rational{BigInt}(1, 36) - @test t == Rational{BigInt}(1, 36) + @test Base.GMP.MPQ.mul!(t, a, b) == -1//6 + @test t == -1//6 + @test Base.GMP.MPQ.mul!(t, t) == 1//36 + @test t == 1//36 @test iszero(Base.GMP.MPQ.mul!(t, Rational{BigInt}(0))) - @test Base.GMP.MPQ.div!(t, a, b) == Rational{BigInt}(-3, 2) - @test t == Rational{BigInt}(-3, 2) - @test Base.GMP.MPQ.div!(t, a) == Rational{BigInt}(-3, 1) - @test t == Rational{BigInt}(-3, 1) + @test Base.GMP.MPQ.div!(t, a, b) == -3//2 + @test t == -3//2 + @test Base.GMP.MPQ.div!(t, a) == -3//1 + @test t == -3//1 @test aa == a && bb == b && cc == c @@ -650,20 +653,20 @@ t = Rational{BigInt}(0, 1) Base.GMP.MPQ.add!(a, b, c) @test b == bb - @test Base.GMP.MPQ.set_z!(a, BigInt(0)) == BigInt(0) + @test Base.GMP.MPQ.set_z!(a, BigInt(0)) == 0 @test iszero(a) - @test Base.GMP.MPQ.set_z!(a, BigInt(3)) == BigInt(3) + @test Base.GMP.MPQ.set_z!(a, BigInt(3)) == 3 @test a == BigInt(3) - @test Base.GMP.MPQ.set_ui(1, 2) == Rational{BigInt}(1, 2) - @test Base.GMP.MPQ.set_ui(0, 1) == Rational{BigInt}(0, 1) - @test Base.GMP.MPQ.set_ui!(a, 1, 2) == Rational{BigInt}(1, 2) - @test a == Rational{BigInt}(1, 2) + @test Base.GMP.MPQ.set_ui(1, 2) == 1//2 + @test Base.GMP.MPQ.set_ui(0, 1) == 0//1 + @test Base.GMP.MPQ.set_ui!(a, 1, 2) == 1//2 + @test a == 1//2 - @test Base.GMP.MPQ.set_si(1, 2) == Rational{BigInt}(1, 2) - @test Base.GMP.MPQ.set_si(-1, 2) == Rational{BigInt}(-1, 2) - @test Base.GMP.MPQ.set_si!(a, -1, 2) == Rational{BigInt}(-1, 2) - @test a == Rational{BigInt}(-1, 2) + @test Base.GMP.MPQ.set_si(1, 2) == 1//2 + @test Base.GMP.MPQ.set_si(-1, 2) == -1//2 + @test Base.GMP.MPQ.set_si!(a, -1, 2) == -1//2 + @test a == -1//2 end @testset "infinities" begin @@ -689,8 +692,8 @@ t = Rational{BigInt}(0, 1) @test Base.GMP.MPQ.mul!(-oz, -oz) == oz @test Base.GMP.MPQ.mul!(-oz, oz) == -oz - @test Base.GMP.MPQ.mul!(oz, -oz) == -Rational{BigInt}(1, 0) - @test oz == -Rational{BigInt}(1, 0) + @test Base.GMP.MPQ.mul!(oz, -oz) == -1//0 + @test oz == -1//0 oz = Rational{BigInt}(1, 0) @test Base.GMP.MPQ.div!(oo, zo) == oz From 698a7b4c80c4f58eab9b969f6153c09cb587f698 Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Wed, 16 Mar 2022 16:38:46 +0300 Subject: [PATCH 14/15] add a test --- test/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/gmp.jl b/test/gmp.jl index dfe973b46ac82..1125f57b195b3 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -582,7 +582,7 @@ e = Rational{BigInt}(12345678901234567890123456789, 1234567890222222221211111110 oz = Rational{BigInt}(0, 1) zo = Rational{BigInt}(1, 0) - @test oz + oz == 2 * oz + @test oz + oz == 3 * oz == oz @test oz // zo == oz @test zo // oz == zo From ac228001bfc329820984003065585aefc88791fd Mon Sep 17 00:00:00 2001 From: sumiya11 Date: Wed, 16 Mar 2022 16:55:32 +0300 Subject: [PATCH 15/15] fix bug --- base/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 35def4170ef15..564f0551f5d45 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -909,7 +909,7 @@ end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) - return set_si!(z, flipsign(1, num), 0) + return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, :libgmp), Cvoid, (mpq_t,), xq)