% % (c) The University of Glasgow, 2000-2006 % \section{Fast integers, etc... booleans moved to FastBool for using panic} \begin{code}

    --Even if the optimizer could handle boxed arithmetic equally well,
    --this helps automatically check the sources to make sure that
    --it's only used in an appropriate pattern of efficiency.
    --(it also makes `let`s and `case`s stricter...)

    -- | Fast integers, characters and pointer types for use in many parts of GHC
    module FastTypes (
        -- * FastInt
        FastInt,

        -- ** Getting in and out of FastInt
        _ILIT, iBox, iUnbox,

        -- ** Arithmetic on FastInt
        (+#), (-#), (*#), quotFastInt, negateFastInt,
        --quotRemFastInt is difficult because unboxed values can't
        --be tupled, but unboxed tuples aren't portable.  Just use
        -- nuisance boxed quotRem and rely on optimization.
        (==#), (/=#), (<#), (<=#), (>=#), (>#),
        minFastInt, maxFastInt,
        --prefer to distinguish operations, not types, between
        --signed and unsigned.
        --left-shift is the same for 'signed' and 'unsigned' numbers
        shiftLFastInt,
        --right-shift isn't the same for negative numbers (ones with
        --the highest-order bit '1').  If you don't care because the
        --number you're shifting is always nonnegative, use the '_' version
        --which should just be the fastest one.
        shiftR_FastInt,
        --"L' = logical or unsigned shift; 'A' = arithmetic or signed shift
        shiftRLFastInt, shiftRAFastInt,
        bitAndFastInt, bitOrFastInt,
        --add more operations to this file as you need them

        -- * FastChar
        FastChar,

        -- ** Getting in and out of FastChar
        _CLIT, cBox, cUnbox,

        -- ** Operations on FastChar
        fastOrd, fastChr, eqFastChar,
        --note, fastChr is "unsafe"Chr: it doesn't check for
        --character values above the range of Unicode

        -- * FastPtr
        FastPtr,

        -- ** Getting in and out of FastPtr
        pBox, pUnbox,

        -- ** Casting FastPtrs
        castFastPtr
      ) where

    #include "HsVersions.h"

    #if defined(__GLASGOW_HASKELL__)

    -- Import the beggars
    import GHC.Exts

    type FastInt = Int#

    --in case it's a macro, don't lexically feed an argument!
    --e.g. #define _ILIT(x) (x#) , #define _ILIT(x) (x :: FastInt)
    _ILIT = \(I# x) -> x
    --perhaps for accomodating caseless-leading-underscore treatment,
    --something like _iLIT or iLIT would be better?

    iBox x = I# x
    iUnbox (I# x) = x
    quotFastInt   = quotInt#
    negateFastInt = negateInt#

    --I think uncheckedIShiftL# and uncheckedIShiftRL# are the same
    --as uncheckedShiftL# and uncheckedShiftRL# ...
    --should they be used? How new are they?
    --They existed as far back as GHC 6.0 at least...
    shiftLFastInt x y = uncheckedIShiftL# x y
    shiftR_FastInt x y = uncheckedIShiftRL# x y
    shiftRLFastInt x y = uncheckedIShiftRL# x y
    shiftRAFastInt x y = uncheckedIShiftRA# x y
    --{-# INLINE shiftLNonnegativeFastInt #-}
    --{-# INLINE shiftRNonnegativeFastInt #-}
    --shiftLNonnegativeFastInt n p = word2Int#((int2Word# n) `uncheckedShiftL#` p)
    --shiftRNonnegativeFastInt n p = word2Int#((int2Word# n) `uncheckedShiftRL#` p)
    bitAndFastInt x y = word2Int# (and# (int2Word# x) (int2Word# y))
    bitOrFastInt x y = word2Int# (or# (int2Word# x) (int2Word# y))

    type FastChar = Char#
    _CLIT = \(C# c) -> c
    cBox c = C# c
    cUnbox (C# c) = c
    fastOrd c = ord# c
    fastChr x = chr# x
    eqFastChar a b = eqChar# a b

    --note that the type-parameter doesn't provide any safety
    --when it's a synonym, but as long as we keep it compiling
    --with and without __GLASGOW_HASKELL__ defined, it's fine.
    type FastPtr a = Addr#
    pBox p = Ptr p
    pUnbox (Ptr p) = p
    castFastPtr p = p

    #else /* ! __GLASGOW_HASKELL__ */

    import Data.Char (ord, chr)

    import Data.Bits
    import Data.Word (Word) --is it a good idea to assume this exists too?
    --does anyone need shiftRLFastInt? (apparently yes.)

    import Foreign.Ptr

    type FastInt = Int
    _ILIT x = x
    iBox x = x
    iUnbox x = x
    (+#) = (+)
    (-#) = (-)
    (*#) = (*)
    quotFastInt   = quot
    --quotRemFastInt = quotRem
    negateFastInt = negate
    (==#) = (==)
    (/=#) = (/=)
    (<#)  = (<)
    (<=#) = (<=)
    (>=#) = (>=)
    (>#)  = (>)
    shiftLFastInt = shiftL
    shiftR_FastInt = shiftR
    shiftRAFastInt = shiftR
    shiftRLFastInt n p = fromIntegral (shiftR (fromIntegral n :: Word) p)
    --shiftLFastInt n p = n * (2 ^ p)
    --assuming quot-Int is faster and the
    --same for nonnegative arguments than div-Int
    --shiftR_FastInt n p = n `quot` (2 ^ p)
    --shiftRAFastInt n p = n `div` (2 ^ p)
    --I couldn't figure out how to implement without Word nor Bits
    --shiftRLFastInt n p = fromIntegral ((fromIntegral n :: Word) `quot` (2 ^ (fromIntegral p :: Word)))

    bitAndFastInt = (.&.)
    bitOrFastInt = (.|.)

    type FastBool = Bool
    fastBool x = x
    isFastTrue x = x
    -- make sure these are as strict as the unboxed version,
    -- so that the performance characteristics match
    fastOr False False = False
    fastOr _ _ = True
    fastAnd True True = True
    fastAnd _ _ = False

    type FastChar = Char
    _CLIT c = c
    cBox c = c
    cUnbox c = c
    fastOrd = ord
    fastChr = chr  --or unsafeChr if there was a standard location for it
    eqFastChar = (==)

    type FastPtr a = Ptr a
    pBox p = p
    pUnbox p = p
    castFastPtr = castPtr

    --These are among the type-signatures necessary for !ghc to compile
    -- but break ghc (can't give a signature for an import...)
    --Note that the comparisons actually do return Bools not FastBools.
    (+#), (-#), (*#) :: FastInt -> FastInt -> FastInt
    (==#), (/=#), (<#), (<=#), (>=#), (>#) :: FastInt -> FastInt -> Bool

    #endif /* ! __GLASGOW_HASKELL__ */

    minFastInt, maxFastInt :: FastInt -> FastInt -> FastInt
    minFastInt x y = if x <# y then x else y
    maxFastInt x y = if x <# y then y else x

    -- type-signatures will improve the non-ghc-specific versions
    -- and keep things accurate (and ABLE to compile!)
    _ILIT :: Int -> FastInt
    iBox :: FastInt -> Int
    iUnbox :: Int -> FastInt

    quotFastInt :: FastInt -> FastInt -> FastInt
    negateFastInt :: FastInt -> FastInt
    shiftLFastInt, shiftR_FastInt, shiftRAFastInt, shiftRLFastInt
       :: FastInt -> FastInt -> FastInt
    bitAndFastInt, bitOrFastInt :: FastInt -> FastInt -> FastInt

    _CLIT :: Char -> FastChar
    cBox :: FastChar -> Char
    cUnbox :: Char -> FastChar
    fastOrd :: FastChar -> FastInt
    fastChr :: FastInt -> FastChar
    eqFastChar :: FastChar -> FastChar -> Bool

    pBox :: FastPtr a -> Ptr a
    pUnbox :: Ptr a -> FastPtr a
    castFastPtr :: FastPtr a -> FastPtr b

\end{code}