+
+#if !defined(__GLASGOW_HASKELL__)
+-- Crude implementation of bitwise operations on Integers: convert them
+-- to finite lists of Ints (least significant first), zip and convert
+-- back again.
+
+-- posAnd requires at least one argument non-negative
+-- posOr and posXOr require both arguments non-negative
+
+posAnd, posOr, posXOr :: Integer -> Integer -> Integer
+posAnd x y = fromInts $ zipWith (.&.) (toInts x) (toInts y)
+posOr x y = fromInts $ longZipWith (.|.) (toInts x) (toInts y)
+posXOr x y = fromInts $ longZipWith xor (toInts x) (toInts y)
+
+longZipWith :: (a -> a -> a) -> [a] -> [a] -> [a]
+longZipWith f xs [] = xs
+longZipWith f [] ys = ys
+longZipWith f (x:xs) (y:ys) = f x y:longZipWith f xs ys
+
+toInts :: Integer -> [Int]
+toInts n
+ | n == 0 = []
+ | otherwise = mkInt (n `mod` numInts):toInts (n `div` numInts)
+ where mkInt n | n > toInteger(maxBound::Int) = fromInteger (n-numInts)
+ | otherwise = fromInteger n
+
+fromInts :: [Int] -> Integer
+fromInts = foldr catInt 0
+ where catInt d n = (if d<0 then n+1 else n)*numInts + toInteger d
+
+numInts = toInteger (maxBound::Int) - toInteger (minBound::Int) + 1
+#endif /* !__GLASGOW_HASKELL__ */
+
+{- Note [Constant folding for rotate]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The INLINE on the Int instance of rotate enables it to be constant
+folded. For example:
+ sumU . mapU (`rotate` 3) . replicateU 10000000 $ (7 :: Int)
+goes to:
+ Main.$wfold =
+ \ (ww_sO7 :: Int#) (ww1_sOb :: Int#) ->
+ case ww1_sOb of wild_XM {
+ __DEFAULT -> Main.$wfold (+# ww_sO7 56) (+# wild_XM 1);
+ 10000000 -> ww_sO7
+whereas before it was left as a call to $wrotate.
+
+All other Bits instances seem to inline well enough on their
+own to enable constant folding; for example 'shift':
+ sumU . mapU (`shift` 3) . replicateU 10000000 $ (7 :: Int)
+ goes to:
+ Main.$wfold =
+ \ (ww_sOb :: Int#) (ww1_sOf :: Int#) ->
+ case ww1_sOf of wild_XM {
+ __DEFAULT -> Main.$wfold (+# ww_sOb 56) (+# wild_XM 1);
+ 10000000 -> ww_sOb
+ }
+-}
+
+