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

    \section{Fast booleans}
    -}

    {-# LANGUAGE CPP, MagicHash #-}

    module FastBool (
        --fastBool could be called bBox; isFastTrue, bUnbox; but they're not
        FastBool, fastBool, isFastTrue, fastOr, fastAnd
      ) where

    -- Import the beggars
    import GHC.Exts
    #ifdef DEBUG
    import Panic
    #endif

    type FastBool = Int#
    fastBool True  = 1#
    fastBool False = 0#

    #ifdef DEBUG
    --then waste time deciding whether to panic. FastBool should normally
    --be at least as fast as Bool, one would hope...

    isFastTrue 1# = True
    isFastTrue 0# = False
    isFastTrue _ = panic "FastTypes: isFastTrue"

    -- note that fastOr and fastAnd are strict in both arguments
    -- since they are unboxed
    fastOr 1# _ = 1#
    fastOr 0# x = x
    fastOr _  _ = panicFastInt "FastTypes: fastOr"

    fastAnd 0# _ = 0#
    fastAnd 1# x = x
    fastAnd _  _ = panicFastInt "FastTypes: fastAnd"

    --these "panicFastInt"s (formerly known as "panic#") rely on
    --FastInt = FastBool ( = Int# presumably),
    --haha, true enough when __GLASGOW_HASKELL__.  Why can't we have functions
    --that return _|_ be kind-polymorphic ( ?? to be precise ) ?

    #else /* ! DEBUG */
    --Isn't comparison to zero sometimes faster on CPUs than comparison to 1?
    -- (since using Int# as _synonym_ fails to guarantee that it will
    --   only take on values of 0 and 1)
    isFastTrue 0# = False
    isFastTrue _ = True

    -- note that fastOr and fastAnd are strict in both arguments
    -- since they are unboxed
    -- Also, to avoid incomplete-pattern warning
    -- (and avoid wasting time with redundant runtime checks),
    -- we don't pattern-match on both 0# and 1# .
    fastOr 0# x = x
    fastOr _  _ = 1#

    fastAnd 0# _ = 0#
    fastAnd _  x = x

    #endif /* ! DEBUG */

    fastBool :: Bool -> FastBool
    isFastTrue :: FastBool -> Bool
    fastOr :: FastBool -> FastBool -> FastBool
    fastAnd :: FastBool -> FastBool -> FastBool