@@ -875,6 +875,8 @@ module MPQ
875875import  . Base:  unsafe_rational, __throw_rational_argerror_zero
876876import  .. GMP:  BigInt, MPZ, Limb, isneg
877877
878+ gmpq (op:: Symbol ) =  (Symbol (:__gmpq_ , op), :libgmp )
879+ 
878880mutable struct  _MPQ
879881    num_alloc:: Cint 
880882    num_size:: Cint 
@@ -907,70 +909,119 @@ end
907909function  Rational {BigInt} (num:: BigInt , den:: BigInt )
908910    if  iszero (den)
909911        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 )
912913    end 
913914    xq =  _MPQ (MPZ. set (num), MPZ. set (den))
914915    ccall ((:__gmpq_canonicalize , :libgmp ), Cvoid, (mpq_t,), xq)
915916    return  sync_rational! (xq)
916917end 
917918
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} )
919953    if  iszero (x. den) ||  iszero (y. den)
920954        if  iszero (x. den) &&  iszero (y. den) &&  isneg (x. num) !=  isneg (y. num)
921955            throw (DivideError ())
922956        end 
923-         return  iszero (x. den) ?  x :  y
957+         return  set! (z,  iszero (x. den) ?  x :  y) 
924958    end 
925-     zq =  _MPQ ()
959+     zq =  _MPQ (z )
926960    ccall ((:__gmpq_add , :libgmp ), Cvoid,
927961          (mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
928962    return  sync_rational! (zq)
929963end 
930- function  Base.:- (x:: Rational{BigInt} , y:: Rational{BigInt} )
964+ 
965+ function  sub! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
931966    if  iszero (x. den) ||  iszero (y. den)
932967        if  iszero (x. den) &&  iszero (y. den) &&  isneg (x. num) ==  isneg (y. num)
933968            throw (DivideError ())
934969        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 )
936972    end 
937-     zq =  _MPQ ()
973+     zq =  _MPQ (z )
938974    ccall ((:__gmpq_sub , :libgmp ), Cvoid,
939975          (mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
940976    return  sync_rational! (zq)
941977end 
942- function  Base.:* (x:: Rational{BigInt} , y:: Rational{BigInt} )
978+ 
979+ function  mul! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
943980    if  iszero (x. den) ||  iszero (y. den)
944981        if  iszero (x. num) ||  iszero (y. num)
945982            throw (DivideError ())
946983        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 )
948985    end 
949-     zq =  _MPQ ()
986+     zq =  _MPQ (z )
950987    ccall ((:__gmpq_mul , :libgmp ), Cvoid,
951988          (mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
952989    return  sync_rational! (zq)
953990end 
954- function  Base.:// (x:: Rational{BigInt} , y:: Rational{BigInt} )
991+ 
992+ function  div! (z:: Rational{BigInt} , x:: Rational{BigInt} , y:: Rational{BigInt} )
955993    if  iszero (x. den)
956994        if  iszero (y. den)
957995            throw (DivideError ())
958996        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 )
960999    elseif  iszero (y. den)
961-         return  y . den  //  y . num 
1000+         return  set_si! (z,  0 ,  1 ) 
9621001    elseif  iszero (y. num)
9631002        if  iszero (x. num)
9641003            throw (DivideError ())
9651004        end 
966-         return  ( isneg ( x. num)  ?   - one (BigInt)  :   one (BigInt))  //  y . num 
1005+         return  set_si! (z,  flipsign ( 1 ,  x. num),  0 ) 
9671006    end 
968-     zq =  _MPQ ()
1007+     zq =  _MPQ (z )
9691008    ccall ((:__gmpq_div , :libgmp ), Cvoid,
9701009          (mpq_t,mpq_t,mpq_t), zq, _MPQ (x), _MPQ (y))
9711010    return  sync_rational! (zq)
9721011end 
9731012
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+ 
9741025end  #  MPQ module
9751026
9761027end  #  module
0 commit comments