    {-
    (c) The University of Glasgow, 2000-2006

    \section{Fast integers, etc... booleans moved to FastBool for using panic}
    -}

    {-# LANGUAGE CPP, MagicHash #-}

    --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"

    -- Import the beggars
    import ExtsCompat46

    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

    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