### [project @ 1999-12-08 14:21:52 by simonmar]

Add Marc Van Dongen's Integer improvements.  Specifically:

- new primops: gcdInt#, gcdIntegerInt#, divExact#,
quotInteger#, remInteger#.

- new definitions of quot and rem for Integer in
PrelNum (using the new quotInteger# and remInteger#
primops instead of quotRemInteger#).  Should be
slightly faster than before.  div & mod aren't
likewise optimised (yet).

- specialisations of gcd for Int and Integer, and
lcm for Integer in PrelNum.
parent 60741e42
This diff is collapsed.
 /* ----------------------------------------------------------------------------- * $Id: PrimOps.h,v 1.40 1999/12/01 14:34:48 simonmar Exp$ * $Id: PrimOps.h,v 1.41 1999/12/08 14:21:54 simonmar Exp$ * * (c) The GHC Team, 1998-1999 * ... ... @@ -355,6 +355,20 @@ typedef union { (r) = RET_PRIM_STGCALL2(I_,mpz_cmp_si,&arg,i); \ } /* I think mp_limb_t must be the same size as StgInt for this to work * properly --SDM */ #define gcdIntzh(r,a,b) \ { StgInt aa = a; \ r = (aa) ? (b) ? \ RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(&aa), 1, (mp_limb_t)(b)) \ : abs(aa) \ : abs(b); \ } #define gcdIntegerIntzh_fast(r,a,sb,b) \ RET_STGCALL3(StgInt, mpn_gcd_1, (unsigned long int *) b, sb, (mp_limb_t)(a)) /* The rest are all out-of-line: -------- */ /* Integer arithmetic */ ... ... @@ -363,6 +377,9 @@ EF_(minusIntegerzh_fast); EF_(timesIntegerzh_fast); EF_(gcdIntegerzh_fast); EF_(quotRemIntegerzh_fast); EF_(quotIntegerzh_fast); EF_(remIntegerzh_fast); EF_(divExactIntegerzh_fast); EF_(divModIntegerzh_fast); /* Conversions */ ... ...
 ... ... @@ -83,6 +83,7 @@ __export PrelGHC zszh quotIntzh remIntzh gcdIntzh negateIntzh iShiftLzh iShiftRAzh ... ... @@ -191,6 +192,11 @@ __export PrelGHC minusIntegerzh timesIntegerzh gcdIntegerzh quotIntegerzh remIntegerzh gcdIntegerzh gcdIntegerIntzh divExactIntegerzh quotRemIntegerzh divModIntegerzh integer2Intzh ... ...
 ... ... @@ -276,29 +276,13 @@ instance Integral Integer where (# s3, d3, s4, d4 #) -> (J# s3 d3, J# s4 d4) {- USING THE UNDERLYING "GMP" CODE IS DUBIOUS FOR NOW: divMod (J# a1 s1 d1) (J# a2 s2 d2) = case (divModInteger# a1 s1 d1 a2 s2 d2) of Return2GMPs a3 s3 d3 a4 s4 d4 -> (J# a3 s3 d3, J# a4 s4 d4) -} toInteger n = n toInt (S# i) = I# i toInt (J# s d) = case (integer2Int# s d) of { n# -> I# n# } -- the rest are identical to the report default methods; -- you get slightly better code if you let the compiler -- see them right here: (S# n) quot (S# d) = S# (n quotInt# d) n quot d = if d /= 0 then q else error "Prelude.Integral.quot{Integer}: divide by 0" where (q,_) = quotRem n d (S# n) rem (S# d) = S# (n remInt# d) n rem d = if d /= 0 then r else error "Prelude.Integral.rem{Integer}: divide by 0" where (_,r) = quotRem n d -- we've got specialised quot/rem methods for Integer (see below) n quot d = n quotInteger d n rem d = n remInteger d n div d = q where (q,_) = divMod n d n mod d = r where (_,r) = divMod n d ... ... @@ -312,6 +296,48 @@ instance Integral Integer where (# s3, d3, s4, d4 #) -> (J# s3 d3, J# s4 d4) remInteger :: Integer -> Integer -> Integer remInteger ia 0 = error "Prelude.Integral.rem{Integer}: divide by 0" remInteger (S# a) (S# b) = S# (remInt# a b) remInteger ia@(S# a) (J# sb b) = if sb ==# 1# then S# (remInt# a (word2Int# (integer2Word# sb b))) else if sb ==# -1# then S# (remInt# a (0# -# (word2Int# (integer2Word# sb b)))) else if 0# <# sb then ia else S# (0# -# a) remInteger (J# sa a) (S# b) = case int2Integer# b of { (# sb, b #) -> case remInteger# sa a sb b of { (# sr, r #) -> S# (sr *# (word2Int# (integer2Word# sr r))) }} remInteger (J# sa a) (J# sb b) = case remInteger# sa a sb b of (# sr, r #) -> J# sr r quotInteger :: Integer -> Integer -> Integer quotInteger ia 0 = error "Prelude.Integral.quot{Integer}: divide by 0" quotInteger (S# a) (S# b) = S# (quotInt# a b) quotInteger (S# a) (J# sb b) = if sb ==# 1# then S# (quotInt# a (word2Int# (integer2Word# sb b))) else if sb ==# -1# then S# (quotInt# a (0# -# (word2Int# (integer2Word# sb b)))) else zeroInteger quotInteger (J# sa a) (S# b) = case int2Integer# b of { (# sb, b #) -> case quotInteger# sa a sb b of (# sq, q #) -> J# sq q } quotInteger (J# sa a) (J# sb b) = case quotInteger# sa a sb b of (# sg, g #) -> J# sg g zeroInteger :: Integer zeroInteger = S# 0# ------------------------------------------------------------------------ instance Enum Integer where succ x = x + 1 ... ... @@ -448,9 +474,6 @@ even, odd :: (Integral a) => a -> Bool even n = n rem 2 == 0 odd = not . even {-# SPECIALISE gcd :: Int -> Int -> Int, Integer -> Integer -> Integer #-} gcd :: (Integral a) => a -> a -> a gcd 0 0 = error "Prelude.gcd: gcd 0 0 is undefined" gcd x y = gcd' (abs x) (abs y) ... ... @@ -485,3 +508,55 @@ _ ^ _ = error "Prelude.^: negative exponent" x ^^ n = if n >= 0 then x^n else recip (x^(negate n)) \end{code} %********************************************************* %* * \subsection{Specialized versions of gcd/lcm for Int/Integer} %* * %********************************************************* \begin{code} {-# RULES "Int.gcd" forall a b . gcd a b = gcdInt a b "Integer.gcd" forall a b . gcd a b = gcdInteger a b "Integer.lcm" forall a b . lcm a b = lcmInteger a b #-} gcdInt :: Int -> Int -> Int gcdInt (I# a) (I# b) = I# (gcdInt# a b) gcdInteger :: Integer -> Integer -> Integer gcdInteger (S# a) (S# b) = case gcdInt# a b of g -> S# g gcdInteger ia@(S# a) ib@(J# sb b) | a ==# 0# = abs ib | sb ==# 0# = abs ia | otherwise = case gcdIntegerInt# sb b a of g -> S# g gcdInteger ia@(J# sa a) ib@(S# b) | sa ==# 0# = abs ib | b ==# 0# = abs ia | otherwise = case gcdIntegerInt# sa a b of g -> S# g gcdInteger (J# sa a) (J# sb b) = case gcdInteger# sa a sb b of (# sg, g #) -> J# sg g lcmInteger :: Integer -> Integer -> Integer lcmInteger a 0 = zeroInteger lcmInteger 0 b = zeroInteger lcmInteger a b = (divExact aa (gcdInteger aa ab)) * ab where aa = abs a ab = abs b divExact :: Integer -> Integer -> Integer divExact (S# a) (S# b) = S# (quotInt# a b) divExact (S# a) (J# sb b) = S# (quotInt# a (sb *# (word2Int# (integer2Word# sb b)))) divExact (J# sa a) (S# b) = case int2Integer# b of (# sb, b #) -> case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d divExact (J# sa a) (J# sb b) = case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d \end{code}
 /* ----------------------------------------------------------------------------- * $Id: PrimOps.hc,v 1.35 1999/12/01 14:34:38 simonmar Exp$ * $Id: PrimOps.hc,v 1.36 1999/12/08 14:21:52 simonmar Exp$ * * (c) The GHC Team, 1998-1999 * ... ... @@ -704,10 +704,13 @@ FN_(name) \ FE_ \ } GMP_TAKE2_RET1(plusIntegerzh_fast, mpz_add); GMP_TAKE2_RET1(minusIntegerzh_fast, mpz_sub); GMP_TAKE2_RET1(timesIntegerzh_fast, mpz_mul); GMP_TAKE2_RET1(gcdIntegerzh_fast, mpz_gcd); GMP_TAKE2_RET1(plusIntegerzh_fast, mpz_add); GMP_TAKE2_RET1(minusIntegerzh_fast, mpz_sub); GMP_TAKE2_RET1(timesIntegerzh_fast, mpz_mul); GMP_TAKE2_RET1(gcdIntegerzh_fast, mpz_gcd); GMP_TAKE2_RET1(quotIntegerzh_fast, mpz_tdiv_q); GMP_TAKE2_RET1(remIntegerzh_fast, mpz_tdiv_r); GMP_TAKE2_RET1(divExactIntegerzh_fast, mpz_divexact); GMP_TAKE2_RET2(quotRemIntegerzh_fast, mpz_tdiv_qr); GMP_TAKE2_RET2(divModIntegerzh_fast, mpz_fdiv_qr); ... ...
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!