@@ -875,6 +875,8 @@ module MPQ
875
875
import . Base: unsafe_rational, __throw_rational_argerror_zero
876
876
import .. GMP: BigInt, MPZ, Limb, isneg
877
877
878
+ gmpq (op:: Symbol ) = (Symbol (:__gmpq_ , op), :libgmp )
879
+
878
880
mutable struct _MPQ
879
881
num_alloc:: Cint
880
882
num_size:: Cint
@@ -907,70 +909,119 @@ end
907
909
function Rational {BigInt} (num:: BigInt , den:: BigInt )
908
910
if iszero (den)
909
911
iszero (num) && __throw_rational_argerror_zero (BigInt)
910
- num = isneg (num) ? - one (BigInt) : one (BigInt)
911
- return unsafe_rational (BigInt, num, den)
912
+ return set_si (flipsign (1 , num), 0 )
912
913
end
913
914
xq = _MPQ (MPZ. set (num), MPZ. set (den))
914
915
ccall ((:__gmpq_canonicalize , :libgmp ), Cvoid, (mpq_t,), xq)
915
916
return sync_rational! (xq)
916
917
end
917
918
918
- function Base.:+ (x:: Rational{BigInt} , y:: Rational{BigInt} )
919
+ # define set, set_ui, set_si, set_z, and their inplace versions
920
+ function set! (z:: Rational{BigInt} , x:: Rational{BigInt} )
921
+ zq = _MPQ (z)
922
+ ccall ((:__gmpq_set , :libgmp ), Cvoid, (mpq_t, mpq_t), zq, _MPQ (x))
923
+ return sync_rational! (zq)
924
+ end
925
+
926
+ function set_z! (z:: Rational{BigInt} , x:: BigInt )
927
+ zq = _MPQ (z)
928
+ ccall ((:__gmpq_set_z , :libgmp ), Cvoid, (mpq_t, MPZ. mpz_t), zq, x)
929
+ return sync_rational! (zq)
930
+ end
931
+
932
+ for (op, T) in ((:set , Rational{BigInt}), (:set_z , BigInt))
933
+ op! = Symbol (op, :! )
934
+ @eval $ op (a:: $T ) = $ op! (unsafe_rational (BigInt (), BigInt ()), a)
935
+ end
936
+
937
+ # note that rationals returned from set_ui and set_si are not checked,
938
+ # set_ui(0, 0) will return 0//0 without errors, just like unsafe_rational
939
+ for (op, T1, T2) in ((:set_ui , Culong, Culong), (:set_si , Clong, Culong))
940
+ op! = Symbol (op, :! )
941
+ @eval begin
942
+ function $op! (z:: Rational{BigInt} , a, b)
943
+ zq = _MPQ (z)
944
+ ccall ($ (gmpq (op)), Cvoid, (mpq_t, $ T1, $ T2), zq, a, b)
945
+ return sync_rational! (zq)
946
+ end
947
+ $ op (a, b) = $ op! (unsafe_rational (BigInt (), BigInt ()), a, b)
948
+ end
949
+ end
950
+
951
+ # define add, sub, mul, div, and their inplace versions
952
+ function add! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
919
953
if iszero (x. den) || iszero (y. den)
920
954
if iszero (x. den) && iszero (y. den) && isneg (x. num) != isneg (y. num)
921
955
throw (DivideError ())
922
956
end
923
- return iszero (x. den) ? x : y
957
+ return set! (z, iszero (x. den) ? x : y)
924
958
end
925
- zq = _MPQ ()
959
+ zq = _MPQ (z )
926
960
ccall ((:__gmpq_add , :libgmp ), Cvoid,
927
961
(mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
928
962
return sync_rational! (zq)
929
963
end
930
- function Base.:- (x:: Rational{BigInt} , y:: Rational{BigInt} )
964
+
965
+ function sub! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
931
966
if iszero (x. den) || iszero (y. den)
932
967
if iszero (x. den) && iszero (y. den) && isneg (x. num) == isneg (y. num)
933
968
throw (DivideError ())
934
969
end
935
- return iszero (x. den) ? x : - y
970
+ iszero (x. den) && return set! (z, x)
971
+ return set_si! (z, flipsign (- 1 , y. num), 0 )
936
972
end
937
- zq = _MPQ ()
973
+ zq = _MPQ (z )
938
974
ccall ((:__gmpq_sub , :libgmp ), Cvoid,
939
975
(mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
940
976
return sync_rational! (zq)
941
977
end
942
- function Base.:* (x:: Rational{BigInt} , y:: Rational{BigInt} )
978
+
979
+ function mul! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
943
980
if iszero (x. den) || iszero (y. den)
944
981
if iszero (x. num) || iszero (y. num)
945
982
throw (DivideError ())
946
983
end
947
- return xor (isneg (x. num),isneg (y. num)) ? - one (BigInt) // zero (BigInt) : one (BigInt) // zero (BigInt )
984
+ return set_si! (z, ifelse ( xor (isneg (x. num), isneg (y. num)), - 1 , 1 ), 0 )
948
985
end
949
- zq = _MPQ ()
986
+ zq = _MPQ (z )
950
987
ccall ((:__gmpq_mul , :libgmp ), Cvoid,
951
988
(mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
952
989
return sync_rational! (zq)
953
990
end
954
- function Base.:// (x:: Rational{BigInt} , y:: Rational{BigInt} )
991
+
992
+ function div! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
955
993
if iszero (x. den)
956
994
if iszero (y. den)
957
995
throw (DivideError ())
958
996
end
959
- return isneg (y. num) ? - x : x
997
+ isneg (y. num) || return set! (z, x)
998
+ return set_si! (z, flipsign (- 1 , x. num), 0 )
960
999
elseif iszero (y. den)
961
- return y . den // y . num
1000
+ return set_si! (z, 0 , 1 )
962
1001
elseif iszero (y. num)
963
1002
if iszero (x. num)
964
1003
throw (DivideError ())
965
1004
end
966
- return ( isneg ( x. num) ? - one (BigInt) : one (BigInt)) // y . num
1005
+ return set_si! (z, flipsign ( 1 , x. num), 0 )
967
1006
end
968
- zq = _MPQ ()
1007
+ zq = _MPQ (z )
969
1008
ccall ((:__gmpq_div , :libgmp ), Cvoid,
970
1009
(mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
971
1010
return sync_rational! (zq)
972
1011
end
973
1012
1013
+ for (fJ, fC) in ((:+ , :add ), (:- , :sub ), (:* , :mul ), (:// , :div ))
1014
+ fC! = Symbol (fC, :! )
1015
+ @eval begin
1016
+ ($ fC!)(x:: Rational{BigInt} , y:: Rational{BigInt} ) = $ fC! (x, x, y)
1017
+ (Base.$ fJ)(x:: Rational{BigInt} , y:: Rational{BigInt} ) = $ fC! (unsafe_rational (BigInt (), BigInt ()), x, y)
1018
+ end
1019
+ end
1020
+
1021
+ function Base. cmp (x:: Rational{BigInt} , y:: Rational{BigInt} )
1022
+ Int (ccall ((:__gmpq_cmp , :libgmp ), Cint, (mpq_t, mpq_t), _MPQ (x), _MPQ (y)))
1023
+ end
1024
+
974
1025
end # MPQ module
975
1026
976
1027
end # module
0 commit comments