Commit 9c370d69 authored by simonmar's avatar simonmar
Browse files

[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!
Please register or to comment