content: {- PARTS OF THIS FILE ARE SEMI-AUTOGENERATED.
    You can re-generate them by invoking the genprimops utility with --foundation-tests
    and then integrating the output in this file.
  
    This test compares the results of various primops between the
    pre-compiled version (primop wrapper) and the implementation of
    whatever the test is run with.
  
    This is particularly helpful when testing the interpreter as it allows us to
    compare the result of the primop wrappers with the results of interpretation.
  -}
  
  {-# LANGUAGE FlexibleContexts    #-}
  {-# LANGUAGE OverloadedStrings   #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeAbstractions #-}
  {-# LANGUAGE TypeFamilies        #-}
  {-# LANGUAGE DerivingStrategies #-}
  {-# LANGUAGE MagicHash #-}
  {-# LANGUAGE RecordWildCards #-}
  {-# LANGUAGE CPP #-}
  {-# LANGUAGE ViewPatterns #-}
  {-# LANGUAGE UnboxedTuples #-}
  module Main
      ( main
      ) where
  
  import Data.Bits (Bits((.&.), bit), FiniteBits, finiteBitSize)
  import Data.Word
  import Data.Int
  import GHC.Natural
  import Data.Typeable
  import Data.Proxy
  import GHC.Int
  import GHC.Word
  import GHC.Word
  import Data.Function
  import GHC.Prim
  import Control.Monad.Reader
  import System.IO
  import Foreign.Marshal.Alloc
  import Foreign.Storable
  import Foreign.Ptr
  import Data.List (intercalate)
  import Data.IORef
  import Unsafe.Coerce
  import GHC.Types
  import Data.Char
  import Data.Semigroup
  import System.Exit
  
  import qualified GHC.Internal.PrimopWrappers as Wrapper
  import qualified GHC.Internal.Prim as Primop
  
  newtype Gen a = Gen { runGen :: (ReaderT LCGGen IO a) }
    deriving newtype (Functor, Applicative, Monad)
  
  class Arbitrary a where
    arbitrary :: Gen a
  
  class IsProperty p where
      property :: p -> Property
  
  data PropertyCheck = PropertyBinaryOp Bool String String String
                     | PropertyAnd PropertyCheck PropertyCheck
  
  instance IsProperty PropertyCheck where
      property check = Prop $ pure (PropertyEOA check)
  
  data PropertyTestArg = PropertyEOA PropertyCheck
                       | PropertyArg String PropertyTestArg
  
  getCheck :: PropertyTestArg -> ([String], PropertyCheck)
  getCheck (PropertyEOA pc) = ([], pc)
  getCheck (PropertyArg s pta ) = let (ss, pc) = getCheck pta in (s:ss, pc)
  
  data Property = Prop { unProp :: Gen PropertyTestArg }
  
  instance (Show a, Arbitrary a, IsProperty prop) => IsProperty (a -> prop) where
      property p = forAll arbitrary p
  
  -- | Running a generator for a specific type under a property
  forAll :: (Show a, IsProperty prop) => Gen a -> (a -> prop) -> Property
  forAll generator tst = Prop $ do
      a <- generator
      augment a <$> unProp (property (tst a))
    where
      augment a arg = PropertyArg (show a) arg
  
  -- | A property that check for equality of its 2 members.
  propertyCompare :: (Show a) => String -> (a -> a -> Bool) -> a -> a -> PropertyCheck
  propertyCompare s f a b =
      let sa = show a
          sb = show b
       in PropertyBinaryOp (a `f` b) s sa sb
  
  (===) :: (Show a, Eq a) => a -> a -> PropertyCheck
  (===) = propertyCompare "==" (==)
  infix 4 ===
  
  propertyAnd = PropertyAnd
  
  
  data Test where
    Group :: String -> [Test] -> Test
    Property :: IsProperty prop => String -> prop -> Test
  
  
  arbitraryInt64 :: Gen Int64
  arbitraryInt64 = Gen $ do
      h <- ask
      W64# w <- liftIO (randomWord64 h)
      return (I64# (unsafeCoerce# w))
  
  integralDownsize :: (Integral a) => Int64 -> a
  integralDownsize = fromIntegral
  
  wordDownsize :: (Integral a) => Word64 -> a
  wordDownsize = fromIntegral
  
  arbitraryWord64 :: Gen Word64
  arbitraryWord64 = Gen $ do
      h <- ask
      liftIO (randomWord64 h)
  
  nonZero :: (Arbitrary a, Num a, Eq a) => Gen (NonZero a)
  nonZero = do
    x <- arbitrary
    if x == 0 then nonZero else pure $ NonZero x
  
  newtype NonZero a = NonZero { getNonZero :: a }
    deriving (Eq,Ord,Bounded,Show)
  
  instance (Arbitrary a, Num a, Eq a) => Arbitrary (NonZero a) where
    arbitrary = nonZero
  
  -- | A newtype for shift amounts that are bounded by @wordSize - 1@
  newtype BoundedShiftAmount a = BoundedShiftAmount {getBoundedShiftAmount :: Int}
    deriving (Eq, Ord, Show)
  
  instance (FiniteBits a) => Arbitrary (BoundedShiftAmount a) where
    arbitrary = do
      x <- arbitrary
      let widthBits = finiteBitSize (undefined :: a)
      pure $ BoundedShiftAmount (abs x `mod` widthBits)
  
  instance Arbitrary Natural where
      arbitrary = integralDownsize . (`mod` 10000) . abs <$> arbitraryInt64
  
  -- Bounded by Int64
  instance Arbitrary Integer where
      arbitrary = fromIntegral <$> arbitraryInt64
  
  instance Arbitrary Int where
      arbitrary = int64ToInt <$> arbitraryInt64
  instance Arbitrary Word where
      arbitrary = word64ToWord <$> arbitraryWord64
  instance Arbitrary Word64 where
      arbitrary = arbitraryWord64
  instance Arbitrary Word32 where
      arbitrary = wordDownsize <$> arbitraryWord64
  instance Arbitrary Word16 where
      arbitrary = wordDownsize <$> arbitraryWord64
  instance Arbitrary Word8 where
      arbitrary = wordDownsize <$> arbitraryWord64
  instance Arbitrary Int64 where
      arbitrary = arbitraryInt64
  instance Arbitrary Int32 where
      arbitrary = integralDownsize <$> arbitraryInt64
  instance Arbitrary Int16 where
      arbitrary = integralDownsize <$> arbitraryInt64
  instance Arbitrary Int8 where
      arbitrary = integralDownsize <$> arbitraryInt64
  
  instance Arbitrary Char where
      arbitrary = do
        let high = fromIntegral $ fromEnum (maxBound :: Char) :: Word
        (x::Word) <- arbitrary
        let x' = mod x high
        return (chr $ fromIntegral x')
  
  int64ToInt :: Int64 -> Int
  int64ToInt (I64# i) = I# (int64ToInt# i)
  
  
  word64ToWord :: Word64 -> Word
  word64ToWord (W64# i) = W# (word64ToWord# i)
  
  
  data RunS = RunS { depth :: Int, rg :: LCGGen, context :: [String] }
  
  newtype LCGGen = LCGGen { randomWord64 :: IO Word64 }
  
  data LCGParams = LCGParams { seed :: Word64, a :: Word64, c :: Word64, m :: Word64 }
  
  newLCGGen :: LCGParams -> IO LCGGen
  newLCGGen LCGParams{..}  = do
    var <- newIORef (fromIntegral seed)
    return $ LCGGen $ do
      atomicModifyIORef' var (\old_v -> let new_val = (old_v * a + c) `mod` m in (new_val, new_val))
  
  
  runPropertyCheck (PropertyBinaryOp res desc s1 s2) =
    if res then return Success
           else do
            ctx <- context <$> ask
            let msg = "Failure: " ++ s1 ++ desc ++ s2
            putMsg msg
            return (Failure [msg : ctx])
  runPropertyCheck (PropertyAnd a1 a2) = (<>) <$> runPropertyCheck a1 <*> runPropertyCheck a2
  
  runProperty :: Property -> ReaderT RunS IO Result
  runProperty (Prop p) = do
    let iterations = 100
    loop iterations iterations
    where
      loop iterations 0 = do
        putMsg ("Passed " ++ show iterations ++ " iterations")
        return Success
      loop iterations n = do
        h <- rg <$> ask
        p <- liftIO (runReaderT (runGen p) h)
        let (ss, pc) = getCheck p
        res <- runPropertyCheck pc
        case res of
          Success -> loop iterations (n-1)
          Failure msgs -> do
            let msg = ("With arguments " ++ intercalate ", " ss)
            putMsg msg
            return (Failure (map (msg :) msgs))
  
  data Result = Success | Failure [[String]]
  
  instance Semigroup Result where
    Success <> x = x
    x <> Success = x
    (Failure xs) <> (Failure ys) = Failure (xs ++ ys)
  
  instance Monoid Result where
    mempty = Success
  
  putMsg s = do
    n <- depth <$> ask
    liftIO . putStrLn $ replicate (n * 2) ' ' ++ s
  
  
  nest c = local (\s -> s { depth = depth s + 1, context = c : context s })
  
  runTestInternal :: Test -> ReaderT RunS IO Result
  runTestInternal (Group name tests) = do
    let label = ("Group " ++ name)
    putMsg label
    nest label (mconcat <$> mapM runTestInternal tests)
  runTestInternal (Property name p) = do
    let label = ("Running " ++ name)
    putMsg label
    nest label $ runProperty (property p)
  
  
  runTests :: Test -> IO ()
  runTests t = do
    -- These params are the same ones as glibc uses.
    h <- newLCGGen (LCGParams { seed = 1238123213, m = 2^31, a = 1103515245, c = 12345 })
    res <- runReaderT  (runTestInternal t) (RunS 0 h [])
    case res of
      Success -> return ()
      Failure tests -> do
        putStrLn $ "These tests failed:  \n" ++ intercalate "  \n" (map (showStack 0 . reverse) tests)
        exitFailure
  
  showStack _ [] = ""
  showStack n (s:ss) = replicate n ' ' ++ s ++ "\n" ++ showStack (n + 2) ss
  
  -------------------------------------------------------------------------------
  
  testIntegral :: forall a . (Arbitrary a, Show a, Integral a, Typeable a)
               => Proxy a -> Test
  testIntegral _ = Group "Integral"
      [ Property "FromIntegral(Integer(a)) == a" $ \(a :: a) -> fromInteger (toInteger a) === a
      ]
  
  testEqOrd :: forall a . (Arbitrary a, Show a, Eq a, Ord a, Integral a, Typeable a)
            => Proxy a -> Test
  testEqOrd _ = Group "Property"
      [ Property "Eq" $ \(a :: a) -> a === a
      -- , Property "Ne" $ \(a :: a) (b :: a) -> if a === w
      , Property "Show" $ \(a :: a) -> show a === show (toInteger a)
      , Property "Ord" $ \(a :: a) (b :: a) -> compare a b === (compare `on` toInteger) a b
      , Property "<" $ \(a :: a) (b :: a) -> case compare a b of
                                                  LT -> propertyCompare "<" (<) a b
                                                  GT -> propertyCompare "<" (<) b a
                                                  EQ -> propertyCompare "not <" ((not .) . (<)) a b `propertyAnd`
                                                        propertyCompare "not <" ((not .) . (<)) b a
      ]
  
  testAdditive :: forall a . (Show a, Eq a, Num a, Arbitrary a, Typeable a)
               => Proxy a -> Test
  testAdditive _ = Group "Additive"
      [ Property "a + azero == a" $ \(a :: a) -> a + 0 === a
      , Property "azero + a == a" $ \(a :: a) -> 0 + a === a
      , Property "a + b == b + a" $ \(a :: a) (b :: a) -> a + b === b + a
      ]
  
  testMultiplicative :: forall a . (Show a, Eq a, Integral a, Arbitrary a, Typeable a)
                     => Proxy a -> Test
  testMultiplicative _ = Group "Multiplicative"
      [ Property "a * 1 == a" $ \(a :: a) -> a * 1 === a
      , Property "1 * a == a" $ \(a :: a) -> 1 * a === a
      , Property "multiplication commutative" $ \(a :: a) (b :: a) -> a * b === b * a
      , Property "a * b == Integer(a) * Integer(b)" $ \(a :: a) (b :: a) -> a * b === fromInteger (toInteger a * toInteger b)
      ]
  
  testDividible :: forall a . (Show a, Eq a, Integral a, Num a, Arbitrary a, Typeable a)
                => Proxy a -> Test
  testDividible _ = Group "Divisible"
      [ Property "(x `div` y) * y + (x `mod` y) == x" $ \(a :: a) (NonZero b) ->
              a === (a `div` b) * b + (a `mod` b)
      ]
  
  testOperatorPrecedence :: forall a . (Show a, Eq a, Prelude.Num a, Integral a, Num a,  Arbitrary a, Typeable a)
                         => Proxy a -> Test
  testOperatorPrecedence _ = Group "Precedence"
      [ Property "+ and - (1)" $ \(a :: a) (b :: a) (c :: a) -> (a + b - c) === ((a + b) - c)
      , Property "+ and - (2)" $ \(a :: a) (b :: a) (c :: a) -> (a - b + c) === ((a - b) + c)
      , Property "+ and * (1)" $ \(a :: a) (b :: a) (c :: a) -> (a + b * c) === (a + (b * c))
      , Property "+ and * (2)" $ \(a :: a) (b :: a) (c :: a) -> (a * b + c) === ((a * b) + c)
      , Property "- and * (1)" $ \(a :: a) (b :: a) (c :: a) -> (a - b * c) === (a - (b * c))
      , Property "- and * (2)" $ \(a :: a) (b :: a) (c :: a) -> (a * b - c) === ((a * b) - c)
      , Property "* and ^ (1)" $ \(a :: a) (b :: Natural) (c :: a) -> (a ^ b * c) === ((a ^ b) * c)
      , Property "* and ^ (2)" $ \(a :: a) (c :: Natural) (b :: a) -> (a * b ^ c) === (a * (b ^ c))
      ]
  
  
  testNumber :: (Show a, Eq a, Prelude.Num a, Integral a, Num a, Arbitrary a, Typeable a)
             => String -> Proxy a -> Test
  testNumber name proxy = Group name
      [ testIntegral proxy
      , testEqOrd proxy
      , testAdditive proxy
      , testMultiplicative proxy
      , testDividible proxy
      , testOperatorPrecedence proxy
      ]
  
  testNumberRefs :: Test
  testNumberRefs = Group "ALL"
      [ testNumber "Int" (Proxy :: Proxy Int)
      , testNumber "Int8" (Proxy :: Proxy Int8)
      , testNumber "Int16" (Proxy :: Proxy Int16)
      , testNumber "Int32" (Proxy :: Proxy Int32)
      , testNumber "Int64" (Proxy :: Proxy Int64)
      , testNumber "Integer" (Proxy :: Proxy Integer)
      , testNumber "Word" (Proxy :: Proxy Word)
      , testNumber "Word8" (Proxy :: Proxy Word8)
      , testNumber "Word16" (Proxy :: Proxy Word16)
      , testNumber "Word32" (Proxy :: Proxy Word32)
      , testNumber "Word64" (Proxy :: Proxy Word64)
      ]
  {-
  test_binop :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) a r'
                (b :: TYPE r1) (r :: TYPE r2)  . String   -> (a -> b) -> (r -> r')
                         -> (b -> b -> r)
                         -> (b -> b -> r)
                         -> Test
  test_binop name unwrap wrap primop wrapper =
  -}
  -- #define TEST_BINOP(name, unwrap, wrap, primop, wrapper)  Property name $ \l r -> wrap (primop (unwrap l) (unwrap r)) === wrap (wrapper (unwrap l) (unwrap r))
  
  wInt# :: Int# -> Int
  wInt# = I#
  
  uInt# :: Int -> Int#
  uInt# (I# x) = x
  
  wWord#:: Word# -> Word
  wWord#= W#
  
  uWord# (W# w) = w
  uWord8# (W8# w) = w
  uWord16# (W16# w) = w
  uWord32# (W32# w) = w
  uWord64# (W64# w) = w
  uChar# (C# c) = c
  uInt8# (I8# w) = w
  uInt16# (I16# w) = w
  uInt32# (I32# w) = w
  uInt64# (I64# w) = w
  
  wWord8# = W8#
  wWord16# = W16#
  wWord32# = W32#
  wWord64# = W64#
  wChar# = C#
  wInt8# = I8#
  wInt16# = I16#
  wInt32# = I32#
  wInt64# = I64#
  
  #define WTUP2(f, g, x) (case x of (# a, b #) -> (f a, g b))
  #define WTUP3(f, g, h, x) (case x of (# a, b, c #) -> (f a, g b, h c))
  
  
  class TestPrimop f where
    testPrimop :: String -> f -> f -> Test
  
    testPrimopDivLike :: String -> f -> f -> Test
    testPrimopDivLike _ _ _ = error "Div testing not supported for this type."
  
    -- | Special test method for shift operations that bounds the shift amount
    testPrimopShift :: String -> f -> f -> Test
    testPrimopShift _ _ _ = error "Shift testing not supported for this type."
  
  {-
  instance TestPrimop (Int# -> Int# -> Int#) where
    testPrimop s l r = Property s $ \(uInt -> a1) (uInt -> a2) -> (wInt (l a1 a2)) === wInt (r a1 a2)
  
  instance TestPrimop (Word# -> Word# -> Int#) where
    testPrimop s l r = Property s $ \(uWord -> a1) (uWord -> a2) -> (wInt (l a1 a2)) === wInt (r a1 a2)
  
  instance TestPrimop (Word# -> Int#) where
    testPrimop s l r = Property s $ \(uWord -> a1) -> (wInt (l a1)) === wInt (r a1)
  
  instance TestPrimop (Word# -> Int# -> Word#) where
    testPrimop s l r = Property s $ \(uWord -> a1) (uInt -> a2) -> (wWord (l a1 a2)) === wWord (r a1 a2)
    -}
  
  -- | A special data-type for representing functions where,
  -- since only some number of the lower bits are defined,
  -- testing for strict equality in the undefined upper bits is not appropriate!
  -- Without using this data-type, false-positive failures will be reported
  -- when the undefined bit regions do not match, even though the equality of bits
  -- in this undefined region has no bearing on correctness.
  data LowerBitsAreDefined =
      LowerBitsAreDefined
      { definedLowerWidth :: Word
      -- ^ The (strictly-non-negative) number of least-significant bits
      -- for which the attached function is defined.
      , undefinedBehavior :: (Word# -> Word#)
      -- ^ Function with undefined behavior for some of its most significant bits.
      }
  
  instance TestPrimop LowerBitsAreDefined where
    testPrimop s l r = Property s $ \ (uWord#-> x0) ->
      let -- Create a mask to unset all bits in the undefined area,
          -- leaving set bits only in the area of defined behavior.
          -- Since the upper bits are undefined,
          -- if the function defines behavior for the lower N bits,
          -- then /only/ the lower N bits are preserved,
          -- and the upper WORDSIZE - N bits are discarded.
          mask = bit (fromEnum (definedLowerWidth r)) - 1
          valL = wWord# (undefinedBehavior l x0) .&. mask
          valR = wWord# (undefinedBehavior r x0) .&. mask
      in  valL === valR
  
  twoNonZero :: (a -> a -> b) -> a -> NonZero a -> b
  twoNonZero f x (NonZero y) = f x y
  
  main = runTests (Group "ALL" [testNumberRefs, testPrimops])
  
  -- Test an interpreted primop vs a compiled primop
  testPrimops = Group "primop"
    [ testPrimop "gtChar#" Primop.gtChar# Wrapper.gtChar#
    , testPrimop "geChar#" Primop.geChar# Wrapper.geChar#
    , testPrimop "eqChar#" Primop.eqChar# Wrapper.eqChar#
    , testPrimop "neChar#" Primop.neChar# Wrapper.neChar#
    , testPrimop "ltChar#" Primop.ltChar# Wrapper.ltChar#
    , testPrimop "leChar#" Primop.leChar# Wrapper.leChar#
    , testPrimop "ord#" Primop.ord# Wrapper.ord#
    , testPrimop "int8ToInt#" Primop.int8ToInt# Wrapper.int8ToInt#
    , testPrimop "intToInt8#" Primop.intToInt8# Wrapper.intToInt8#
    , testPrimop "negateInt8#" Primop.negateInt8# Wrapper.negateInt8#
    , testPrimop "plusInt8#" Primop.plusInt8# Wrapper.plusInt8#
    , testPrimop "subInt8#" Primop.subInt8# Wrapper.subInt8#
    , testPrimop "timesInt8#" Primop.timesInt8# Wrapper.timesInt8#
    , testPrimopDivLike "quotInt8#" Primop.quotInt8# Wrapper.quotInt8#
    , testPrimopDivLike "remInt8#" Primop.remInt8# Wrapper.remInt8#
    , testPrimopDivLike "quotRemInt8#" Primop.quotRemInt8# Wrapper.quotRemInt8#
    , testPrimopShift "uncheckedShiftLInt8#" Primop.uncheckedShiftLInt8# Wrapper.uncheckedShiftLInt8#
    , testPrimopShift "uncheckedShiftRAInt8#" Primop.uncheckedShiftRAInt8# Wrapper.uncheckedShiftRAInt8#
    , testPrimopShift "uncheckedShiftRLInt8#" Primop.uncheckedShiftRLInt8# Wrapper.uncheckedShiftRLInt8#
    , testPrimop "int8ToWord8#" Primop.int8ToWord8# Wrapper.int8ToWord8#
    , testPrimop "eqInt8#" Primop.eqInt8# Wrapper.eqInt8#
    , testPrimop "geInt8#" Primop.geInt8# Wrapper.geInt8#
    , testPrimop "gtInt8#" Primop.gtInt8# Wrapper.gtInt8#
    , testPrimop "leInt8#" Primop.leInt8# Wrapper.leInt8#
    , testPrimop "ltInt8#" Primop.ltInt8# Wrapper.ltInt8#
    , testPrimop "neInt8#" Primop.neInt8# Wrapper.neInt8#
    , testPrimop "word8ToWord#" Primop.word8ToWord# Wrapper.word8ToWord#
    , testPrimop "wordToWord8#" Primop.wordToWord8# Wrapper.wordToWord8#
    , testPrimop "plusWord8#" Primop.plusWord8# Wrapper.plusWord8#
    , testPrimop "subWord8#" Primop.subWord8# Wrapper.subWord8#
    , testPrimop "timesWord8#" Primop.timesWord8# Wrapper.timesWord8#
    , testPrimopDivLike "quotWord8#" Primop.quotWord8# Wrapper.quotWord8#
    , testPrimopDivLike "remWord8#" Primop.remWord8# Wrapper.remWord8#
    , testPrimopDivLike "quotRemWord8#" Primop.quotRemWord8# Wrapper.quotRemWord8#
    , testPrimop "andWord8#" Primop.andWord8# Wrapper.andWord8#
    , testPrimop "orWord8#" Primop.orWord8# Wrapper.orWord8#
    , testPrimop "xorWord8#" Primop.xorWord8# Wrapper.xorWord8#
    , testPrimop "notWord8#" Primop.notWord8# Wrapper.notWord8#
    , testPrimopShift "uncheckedShiftLWord8#" Primop.uncheckedShiftLWord8# Wrapper.uncheckedShiftLWord8#
    , testPrimopShift "uncheckedShiftRLWord8#" Primop.uncheckedShiftRLWord8# Wrapper.uncheckedShiftRLWord8#
    , testPrimop "word8ToInt8#" Primop.word8ToInt8# Wrapper.word8ToInt8#
    , testPrimop "eqWord8#" Primop.eqWord8# Wrapper.eqWord8#
    , testPrimop "geWord8#" Primop.geWord8# Wrapper.geWord8#
    , testPrimop "gtWord8#" Primop.gtWord8# Wrapper.gtWord8#
    , testPrimop "leWord8#" Primop.leWord8# Wrapper.leWord8#
    , testPrimop "ltWord8#" Primop.ltWord8# Wrapper.ltWord8#
    , testPrimop "neWord8#" Primop.neWord8# Wrapper.neWord8#
    , testPrimop "int16ToInt#" Primop.int16ToInt# Wrapper.int16ToInt#
    , testPrimop "intToInt16#" Primop.intToInt16# Wrapper.intToInt16#
    , testPrimop "negateInt16#" Primop.negateInt16# Wrapper.negateInt16#
    , testPrimop "plusInt16#" Primop.plusInt16# Wrapper.plusInt16#
    , testPrimop "subInt16#" Primop.subInt16# Wrapper.subInt16#
    , testPrimop "timesInt16#" Primop.timesInt16# Wrapper.timesInt16#
    , testPrimopDivLike "quotInt16#" Primop.quotInt16# Wrapper.quotInt16#
    , testPrimopDivLike "remInt16#" Primop.remInt16# Wrapper.remInt16#
    , testPrimopDivLike "quotRemInt16#" Primop.quotRemInt16# Wrapper.quotRemInt16#
    , testPrimopShift "uncheckedShiftLInt16#" Primop.uncheckedShiftLInt16# Wrapper.uncheckedShiftLInt16#
    , testPrimopShift "uncheckedShiftRAInt16#" Primop.uncheckedShiftRAInt16# Wrapper.uncheckedShiftRAInt16#
    , testPrimopShift "uncheckedShiftRLInt16#" Primop.uncheckedShiftRLInt16# Wrapper.uncheckedShiftRLInt16#
    , testPrimop "int16ToWord16#" Primop.int16ToWord16# Wrapper.int16ToWord16#
    , testPrimop "eqInt16#" Primop.eqInt16# Wrapper.eqInt16#
    , testPrimop "geInt16#" Primop.geInt16# Wrapper.geInt16#
    , testPrimop "gtInt16#" Primop.gtInt16# Wrapper.gtInt16#
    , testPrimop "leInt16#" Primop.leInt16# Wrapper.leInt16#
    , testPrimop "ltInt16#" Primop.ltInt16# Wrapper.ltInt16#
    , testPrimop "neInt16#" Primop.neInt16# Wrapper.neInt16#
    , testPrimop "word16ToWord#" Primop.word16ToWord# Wrapper.word16ToWord#
    , testPrimop "wordToWord16#" Primop.wordToWord16# Wrapper.wordToWord16#
    , testPrimop "plusWord16#" Primop.plusWord16# Wrapper.plusWord16#
    , testPrimop "subWord16#" Primop.subWord16# Wrapper.subWord16#
    , testPrimop "timesWord16#" Primop.timesWord16# Wrapper.timesWord16#
    , testPrimopDivLike "quotWord16#" Primop.quotWord16# Wrapper.quotWord16#
    , testPrimopDivLike "remWord16#" Primop.remWord16# Wrapper.remWord16#
    , testPrimopDivLike "quotRemWord16#" Primop.quotRemWord16# Wrapper.quotRemWord16#
    , testPrimop "andWord16#" Primop.andWord16# Wrapper.andWord16#
    , testPrimop "orWord16#" Primop.orWord16# Wrapper.orWord16#
    , testPrimop "xorWord16#" Primop.xorWord16# Wrapper.xorWord16#
    , testPrimop "notWord16#" Primop.notWord16# Wrapper.notWord16#
    , testPrimopShift "uncheckedShiftLWord16#" Primop.uncheckedShiftLWord16# Wrapper.uncheckedShiftLWord16#
    , testPrimopShift "uncheckedShiftRLWord16#" Primop.uncheckedShiftRLWord16# Wrapper.uncheckedShiftRLWord16#
    , testPrimop "word16ToInt16#" Primop.word16ToInt16# Wrapper.word16ToInt16#
    , testPrimop "eqWord16#" Primop.eqWord16# Wrapper.eqWord16#
    , testPrimop "geWord16#" Primop.geWord16# Wrapper.geWord16#
    , testPrimop "gtWord16#" Primop.gtWord16# Wrapper.gtWord16#
    , testPrimop "leWord16#" Primop.leWord16# Wrapper.leWord16#
    , testPrimop "ltWord16#" Primop.ltWord16# Wrapper.ltWord16#
    , testPrimop "neWord16#" Primop.neWord16# Wrapper.neWord16#
    , testPrimop "int32ToInt#" Primop.int32ToInt# Wrapper.int32ToInt#
    , testPrimop "intToInt32#" Primop.intToInt32# Wrapper.intToInt32#
    , testPrimop "negateInt32#" Primop.negateInt32# Wrapper.negateInt32#
    , testPrimop "plusInt32#" Primop.plusInt32# Wrapper.plusInt32#
    , testPrimop "subInt32#" Primop.subInt32# Wrapper.subInt32#
    , testPrimop "timesInt32#" Primop.timesInt32# Wrapper.timesInt32#
    , testPrimopDivLike "quotInt32#" Primop.quotInt32# Wrapper.quotInt32#
    , testPrimopDivLike "remInt32#" Primop.remInt32# Wrapper.remInt32#
    , testPrimopDivLike "quotRemInt32#" Primop.quotRemInt32# Wrapper.quotRemInt32#
    , testPrimopShift "uncheckedShiftLInt32#" Primop.uncheckedShiftLInt32# Wrapper.uncheckedShiftLInt32#
    , testPrimopShift "uncheckedShiftRAInt32#" Primop.uncheckedShiftRAInt32# Wrapper.uncheckedShiftRAInt32#
    , testPrimopShift "uncheckedShiftRLInt32#" Primop.uncheckedShiftRLInt32# Wrapper.uncheckedShiftRLInt32#
    , testPrimop "int32ToWord32#" Primop.int32ToWord32# Wrapper.int32ToWord32#
    , testPrimop "eqInt32#" Primop.eqInt32# Wrapper.eqInt32#
    , testPrimop "geInt32#" Primop.geInt32# Wrapper.geInt32#
    , testPrimop "gtInt32#" Primop.gtInt32# Wrapper.gtInt32#
    , testPrimop "leInt32#" Primop.leInt32# Wrapper.leInt32#
    , testPrimop "ltInt32#" Primop.ltInt32# Wrapper.ltInt32#
    , testPrimop "neInt32#" Primop.neInt32# Wrapper.neInt32#
    , testPrimop "word32ToWord#" Primop.word32ToWord# Wrapper.word32ToWord#
    , testPrimop "wordToWord32#" Primop.wordToWord32# Wrapper.wordToWord32#
    , testPrimop "plusWord32#" Primop.plusWord32# Wrapper.plusWord32#
    , testPrimop "subWord32#" Primop.subWord32# Wrapper.subWord32#
    , testPrimop "timesWord32#" Primop.timesWord32# Wrapper.timesWord32#
    , testPrimopDivLike "quotWord32#" Primop.quotWord32# Wrapper.quotWord32#
    , testPrimopDivLike "remWord32#" Primop.remWord32# Wrapper.remWord32#
    , testPrimopDivLike "quotRemWord32#" Primop.quotRemWord32# Wrapper.quotRemWord32#
    , testPrimop "andWord32#" Primop.andWord32# Wrapper.andWord32#
    , testPrimop "orWord32#" Primop.orWord32# Wrapper.orWord32#
    , testPrimop "xorWord32#" Primop.xorWord32# Wrapper.xorWord32#
    , testPrimop "notWord32#" Primop.notWord32# Wrapper.notWord32#
    , testPrimopShift "uncheckedShiftLWord32#" Primop.uncheckedShiftLWord32# Wrapper.uncheckedShiftLWord32#
    , testPrimopShift "uncheckedShiftRLWord32#" Primop.uncheckedShiftRLWord32# Wrapper.uncheckedShiftRLWord32#
    , testPrimop "word32ToInt32#" Primop.word32ToInt32# Wrapper.word32ToInt32#
    , testPrimop "eqWord32#" Primop.eqWord32# Wrapper.eqWord32#
    , testPrimop "geWord32#" Primop.geWord32# Wrapper.geWord32#
    , testPrimop "gtWord32#" Primop.gtWord32# Wrapper.gtWord32#
    , testPrimop "leWord32#" Primop.leWord32# Wrapper.leWord32#
    , testPrimop "ltWord32#" Primop.ltWord32# Wrapper.ltWord32#
    , testPrimop "neWord32#" Primop.neWord32# Wrapper.neWord32#
    , testPrimop "int64ToInt#" Primop.int64ToInt# Wrapper.int64ToInt#
    , testPrimop "intToInt64#" Primop.intToInt64# Wrapper.intToInt64#
    , testPrimop "negateInt64#" Primop.negateInt64# Wrapper.negateInt64#
    , testPrimop "plusInt64#" Primop.plusInt64# Wrapper.plusInt64#
    , testPrimop "subInt64#" Primop.subInt64# Wrapper.subInt64#
    , testPrimop "timesInt64#" Primop.timesInt64# Wrapper.timesInt64#
    , testPrimopDivLike "quotInt64#" Primop.quotInt64# Wrapper.quotInt64#
    , testPrimopDivLike "remInt64#" Primop.remInt64# Wrapper.remInt64#
    , testPrimopShift "uncheckedIShiftL64#" Primop.uncheckedIShiftL64# Wrapper.uncheckedIShiftL64#
    , testPrimopShift "uncheckedIShiftRA64#" Primop.uncheckedIShiftRA64# Wrapper.uncheckedIShiftRA64#
    , testPrimopShift "uncheckedIShiftRL64#" Primop.uncheckedIShiftRL64# Wrapper.uncheckedIShiftRL64#
    , testPrimop "int64ToWord64#" Primop.int64ToWord64# Wrapper.int64ToWord64#
    , testPrimop "eqInt64#" Primop.eqInt64# Wrapper.eqInt64#
    , testPrimop "geInt64#" Primop.geInt64# Wrapper.geInt64#
    , testPrimop "gtInt64#" Primop.gtInt64# Wrapper.gtInt64#
    , testPrimop "leInt64#" Primop.leInt64# Wrapper.leInt64#
    , testPrimop "ltInt64#" Primop.ltInt64# Wrapper.ltInt64#
    , testPrimop "neInt64#" Primop.neInt64# Wrapper.neInt64#
    , testPrimop "word64ToWord#" Primop.word64ToWord# Wrapper.word64ToWord#
    , testPrimop "wordToWord64#" Primop.wordToWord64# Wrapper.wordToWord64#
    , testPrimop "plusWord64#" Primop.plusWord64# Wrapper.plusWord64#
    , testPrimop "subWord64#" Primop.subWord64# Wrapper.subWord64#
    , testPrimop "timesWord64#" Primop.timesWord64# Wrapper.timesWord64#
    , testPrimopDivLike "quotWord64#" Primop.quotWord64# Wrapper.quotWord64#
    , testPrimopDivLike "remWord64#" Primop.remWord64# Wrapper.remWord64#
    , testPrimop "and64#" Primop.and64# Wrapper.and64#
    , testPrimop "or64#" Primop.or64# Wrapper.or64#
    , testPrimop "xor64#" Primop.xor64# Wrapper.xor64#
    , testPrimop "not64#" Primop.not64# Wrapper.not64#
    , testPrimopShift "uncheckedShiftL64#" Primop.uncheckedShiftL64# Wrapper.uncheckedShiftL64#
    , testPrimopShift "uncheckedShiftRL64#" Primop.uncheckedShiftRL64# Wrapper.uncheckedShiftRL64#
    , testPrimop "word64ToInt64#" Primop.word64ToInt64# Wrapper.word64ToInt64#
    , testPrimop "eqWord64#" Primop.eqWord64# Wrapper.eqWord64#
    , testPrimop "geWord64#" Primop.geWord64# Wrapper.geWord64#
    , testPrimop "gtWord64#" Primop.gtWord64# Wrapper.gtWord64#
    , testPrimop "leWord64#" Primop.leWord64# Wrapper.leWord64#
    , testPrimop "ltWord64#" Primop.ltWord64# Wrapper.ltWord64#
    , testPrimop "neWord64#" Primop.neWord64# Wrapper.neWord64#
    , testPrimop "+#" (Primop.+#) (Wrapper.+#)
    , testPrimop "-#" (Primop.-#) (Wrapper.-#)
    , testPrimop "*#" (Primop.*#) (Wrapper.*#)
    , testPrimop "timesInt2#" Primop.timesInt2# Wrapper.timesInt2#
    , testPrimop "mulIntMayOflo#" Primop.mulIntMayOflo# Wrapper.mulIntMayOflo#
    , testPrimopDivLike "quotInt#" Primop.quotInt# Wrapper.quotInt#
    , testPrimopDivLike "remInt#" Primop.remInt# Wrapper.remInt#
    , testPrimopDivLike "quotRemInt#" Primop.quotRemInt# Wrapper.quotRemInt#
    , testPrimop "andI#" Primop.andI# Wrapper.andI#
    , testPrimop "orI#" Primop.orI# Wrapper.orI#
    , testPrimop "xorI#" Primop.xorI# Wrapper.xorI#
    , testPrimop "notI#" Primop.notI# Wrapper.notI#
    , testPrimop "negateInt#" Primop.negateInt# Wrapper.negateInt#
    , testPrimop "addIntC#" Primop.addIntC# Wrapper.addIntC#
    , testPrimop "subIntC#" Primop.subIntC# Wrapper.subIntC#
    , testPrimop ">#" (Primop.>#) (Wrapper.>#)
    , testPrimop ">=#" (Primop.>=#) (Wrapper.>=#)
    , testPrimop "==#" (Primop.==#) (Wrapper.==#)
    , testPrimop "/=#" (Primop./=#) (Wrapper./=#)
    , testPrimop "<#" (Primop.<#) (Wrapper.<#)
    , testPrimop "<=#" (Primop.<=#) (Wrapper.<=#)
    , testPrimop "chr#" Primop.chr# Wrapper.chr#
    , testPrimop "int2Word#" Primop.int2Word# Wrapper.int2Word#
    , testPrimopShift "uncheckedIShiftL#" Primop.uncheckedIShiftL# Wrapper.uncheckedIShiftL#
    , testPrimopShift "uncheckedIShiftRA#" Primop.uncheckedIShiftRA# Wrapper.uncheckedIShiftRA#
    , testPrimopShift "uncheckedIShiftRL#" Primop.uncheckedIShiftRL# Wrapper.uncheckedIShiftRL#
    , testPrimop "plusWord#" Primop.plusWord# Wrapper.plusWord#
    , testPrimop "addWordC#" Primop.addWordC# Wrapper.addWordC#
    , testPrimop "subWordC#" Primop.subWordC# Wrapper.subWordC#
    , testPrimop "plusWord2#" Primop.plusWord2# Wrapper.plusWord2#
    , testPrimop "minusWord#" Primop.minusWord# Wrapper.minusWord#
    , testPrimop "timesWord#" Primop.timesWord# Wrapper.timesWord#
    , testPrimop "timesWord2#" Primop.timesWord2# Wrapper.timesWord2#
    , testPrimopDivLike "quotWord#" Primop.quotWord# Wrapper.quotWord#
    , testPrimopDivLike "remWord#" Primop.remWord# Wrapper.remWord#
    , testPrimopDivLike "quotRemWord#" Primop.quotRemWord# Wrapper.quotRemWord#
    , testPrimop "and#" Primop.and# Wrapper.and#
    , testPrimop "or#" Primop.or# Wrapper.or#
    , testPrimop "xor#" Primop.xor# Wrapper.xor#
    , testPrimop "not#" Primop.not# Wrapper.not#
    , testPrimopShift "uncheckedShiftL#" Primop.uncheckedShiftL# Wrapper.uncheckedShiftL#
    , testPrimopShift "uncheckedShiftRL#" Primop.uncheckedShiftRL# Wrapper.uncheckedShiftRL#
    , testPrimop "word2Int#" Primop.word2Int# Wrapper.word2Int#
    , testPrimop "gtWord#" Primop.gtWord# Wrapper.gtWord#
    , testPrimop "geWord#" Primop.geWord# Wrapper.geWord#
    , testPrimop "eqWord#" Primop.eqWord# Wrapper.eqWord#
    , testPrimop "neWord#" Primop.neWord# Wrapper.neWord#
    , testPrimop "ltWord#" Primop.ltWord# Wrapper.ltWord#
    , testPrimop "leWord#" Primop.leWord# Wrapper.leWord#
    , testPrimop "popCnt8#" Primop.popCnt8# Wrapper.popCnt8#
    , testPrimop "popCnt16#" Primop.popCnt16# Wrapper.popCnt16#
    , testPrimop "popCnt32#" Primop.popCnt32# Wrapper.popCnt32#
    , testPrimop "popCnt64#" Primop.popCnt64# Wrapper.popCnt64#
    , testPrimop "popCnt#" Primop.popCnt# Wrapper.popCnt#
    , testPrimop "pdep8#" Primop.pdep8# Wrapper.pdep8#
    , testPrimop "pdep16#" Primop.pdep16# Wrapper.pdep16#
    , testPrimop "pdep32#" Primop.pdep32# Wrapper.pdep32#
    , testPrimop "pdep64#" Primop.pdep64# Wrapper.pdep64#
    , testPrimop "pdep#" Primop.pdep# Wrapper.pdep#
    , testPrimop "pext8#" Primop.pext8# Wrapper.pext8#
    , testPrimop "pext16#" Primop.pext16# Wrapper.pext16#
    , testPrimop "pext32#" Primop.pext32# Wrapper.pext32#
    , testPrimop "pext64#" Primop.pext64# Wrapper.pext64#
    , testPrimop "pext#" Primop.pext# Wrapper.pext#
    , testPrimop "clz8#" Primop.clz8# Wrapper.clz8#
    , testPrimop "clz16#" Primop.clz16# Wrapper.clz16#
    , testPrimop "clz32#" Primop.clz32# Wrapper.clz32#
    , testPrimop "clz64#" Primop.clz64# Wrapper.clz64#
    , testPrimop "clz#" Primop.clz# Wrapper.clz#
    , testPrimop "ctz8#" Primop.ctz8# Wrapper.ctz8#
    , testPrimop "ctz16#" Primop.ctz16# Wrapper.ctz16#
    , testPrimop "ctz32#" Primop.ctz32# Wrapper.ctz32#
    , testPrimop "ctz64#" Primop.ctz64# Wrapper.ctz64#
    , testPrimop "ctz#" Primop.ctz# Wrapper.ctz#
    , testPrimop "byteSwap16#" (16 `LowerBitsAreDefined` Primop.byteSwap16#) (16 `LowerBitsAreDefined` Wrapper.byteSwap16#)
    , testPrimop "byteSwap32#" (32 `LowerBitsAreDefined` Primop.byteSwap32#) (32 `LowerBitsAreDefined` Wrapper.byteSwap32#)
    , testPrimop "byteSwap64#" Primop.byteSwap64# Wrapper.byteSwap64#
    , testPrimop "byteSwap#" Primop.byteSwap# Wrapper.byteSwap#
    , testPrimop "bitReverse8#" (8 `LowerBitsAreDefined` Primop.bitReverse8#) (8 `LowerBitsAreDefined` Wrapper.bitReverse8#)
    , testPrimop "bitReverse16#" (16 `LowerBitsAreDefined` Primop.bitReverse16#) (16 `LowerBitsAreDefined` Wrapper.bitReverse16#)
    , testPrimop "bitReverse32#" (32 `LowerBitsAreDefined` Primop.bitReverse32#) (32 `LowerBitsAreDefined` Wrapper.bitReverse32#)
    , testPrimop "bitReverse64#" Primop.bitReverse64# Wrapper.bitReverse64#
    , testPrimop "bitReverse#" Primop.bitReverse# Wrapper.bitReverse#
    , testPrimop "narrow8Int#" Primop.narrow8Int# Wrapper.narrow8Int#
    , testPrimop "narrow16Int#" Primop.narrow16Int# Wrapper.narrow16Int#
    , testPrimop "narrow32Int#" Primop.narrow32Int# Wrapper.narrow32Int#
    , testPrimop "narrow8Word#" Primop.narrow8Word# Wrapper.narrow8Word#
    , testPrimop "narrow16Word#" Primop.narrow16Word# Wrapper.narrow16Word#
    , testPrimop "narrow32Word#" Primop.narrow32Word# Wrapper.narrow32Word#
    ]
  
  instance TestPrimop (Char# -> Char# -> Int#) where
    testPrimop s l r = Property s $ \ (uChar#-> x0) (uChar#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Char# -> Int#) where
    testPrimop s l r = Property s $ \ (uChar#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int# -> Int# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) (uInt#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt#-> x0) (uInt#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uInt#-> x0) (BoundedShiftAmount @Int shift) -> wInt# (l x0 (uInt# shift)) === wInt# (r x0 (uInt# shift))
  
  instance TestPrimop (Int# -> Int# -> (# Int#,Int# #)) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP2(wInt#,wInt#, (l x0 x1)) === WTUP2(wInt#,wInt#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP2(wInt#,wInt#, (l x0 x1)) === WTUP2(wInt#,wInt#, (r x0 x1))
  
  instance TestPrimop (Int# -> Int# -> (# Int#,Int#,Int# #)) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP3(wInt#,wInt#,wInt#, (l x0 x1)) === WTUP3(wInt#,wInt#,wInt#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP3(wInt#,wInt#,wInt#, (l x0 x1)) === WTUP3(wInt#,wInt#,wInt#, (r x0 x1))
  
  instance TestPrimop (Int# -> Char#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wChar# (l x0) === wChar# (r x0)
  
  instance TestPrimop (Int# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int# -> Int16#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wInt16# (l x0) === wInt16# (r x0)
  
  instance TestPrimop (Int# -> Int32#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wInt32# (l x0) === wInt32# (r x0)
  
  instance TestPrimop (Int# -> Int64#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wInt64# (l x0) === wInt64# (r x0)
  
  instance TestPrimop (Int# -> Int8#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wInt8# (l x0) === wInt8# (r x0)
  
  instance TestPrimop (Int# -> Word#) where
    testPrimop s l r = Property s $ \ (uInt#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Int16# -> Int# -> Int16#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) (uInt#-> x1) -> wInt16# (l x0 x1) === wInt16# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uInt16#-> x0) (BoundedShiftAmount @Int16 shift) -> wInt16# (l x0 (uInt# shift)) === wInt16# (r x0 (uInt# shift))
  
  instance TestPrimop (Int16# -> Int16# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) (uInt16#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt16#-> x0) (uInt16#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Int16# -> Int16# -> Int16#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) (uInt16#-> x1) -> wInt16# (l x0 x1) === wInt16# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt16#-> x0) (uInt16#-> x1) -> wInt16# (l x0 x1) === wInt16# (r x0 x1)
  
  instance TestPrimop (Int16# -> Int16# -> (# Int16#,Int16# #)) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) (uInt16#-> x1) -> WTUP2(wInt16#,wInt16#, (l x0 x1)) === WTUP2(wInt16#,wInt16#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt16#-> x0) (uInt16#-> x1) -> WTUP2(wInt16#,wInt16#, (l x0 x1)) === WTUP2(wInt16#,wInt16#, (r x0 x1))
  
  instance TestPrimop (Int16# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int16# -> Int16#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) -> wInt16# (l x0) === wInt16# (r x0)
  
  instance TestPrimop (Int16# -> Word16#) where
    testPrimop s l r = Property s $ \ (uInt16#-> x0) -> wWord16# (l x0) === wWord16# (r x0)
  
  instance TestPrimop (Int32# -> Int# -> Int32#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) (uInt#-> x1) -> wInt32# (l x0 x1) === wInt32# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uInt32#-> x0) (BoundedShiftAmount @Int32 shift) -> wInt32# (l x0 (uInt# shift)) === wInt32# (r x0 (uInt# shift))
  
  instance TestPrimop (Int32# -> Int32# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) (uInt32#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt32#-> x0) (uInt32#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Int32# -> Int32# -> Int32#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) (uInt32#-> x1) -> wInt32# (l x0 x1) === wInt32# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt32#-> x0) (uInt32#-> x1) -> wInt32# (l x0 x1) === wInt32# (r x0 x1)
  
  instance TestPrimop (Int32# -> Int32# -> (# Int32#,Int32# #)) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) (uInt32#-> x1) -> WTUP2(wInt32#,wInt32#, (l x0 x1)) === WTUP2(wInt32#,wInt32#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt32#-> x0) (uInt32#-> x1) -> WTUP2(wInt32#,wInt32#, (l x0 x1)) === WTUP2(wInt32#,wInt32#, (r x0 x1))
  
  instance TestPrimop (Int32# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int32# -> Int32#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) -> wInt32# (l x0) === wInt32# (r x0)
  
  instance TestPrimop (Int32# -> Word32#) where
    testPrimop s l r = Property s $ \ (uInt32#-> x0) -> wWord32# (l x0) === wWord32# (r x0)
  
  instance TestPrimop (Int64# -> Int# -> Int64#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) (uInt#-> x1) -> wInt64# (l x0 x1) === wInt64# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uInt64#-> x0) (BoundedShiftAmount @Int64 shift) -> wInt64# (l x0 (uInt# shift)) === wInt64# (r x0 (uInt# shift))
  
  instance TestPrimop (Int64# -> Int64# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) (uInt64#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt64#-> x0) (uInt64#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Int64# -> Int64# -> Int64#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) (uInt64#-> x1) -> wInt64# (l x0 x1) === wInt64# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt64#-> x0) (uInt64#-> x1) -> wInt64# (l x0 x1) === wInt64# (r x0 x1)
  
  instance TestPrimop (Int64# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int64# -> Int64#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) -> wInt64# (l x0) === wInt64# (r x0)
  
  instance TestPrimop (Int64# -> Word64#) where
    testPrimop s l r = Property s $ \ (uInt64#-> x0) -> wWord64# (l x0) === wWord64# (r x0)
  
  instance TestPrimop (Int8# -> Int# -> Int8#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) (uInt#-> x1) -> wInt8# (l x0 x1) === wInt8# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uInt8#-> x0) (BoundedShiftAmount @Int8 shift) -> wInt8# (l x0 (uInt# shift)) === wInt8# (r x0 (uInt# shift))
  
  instance TestPrimop (Int8# -> Int8# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) (uInt8#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt8#-> x0) (uInt8#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Int8# -> Int8# -> Int8#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) (uInt8#-> x1) -> wInt8# (l x0 x1) === wInt8# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt8#-> x0) (uInt8#-> x1) -> wInt8# (l x0 x1) === wInt8# (r x0 x1)
  
  instance TestPrimop (Int8# -> Int8# -> (# Int8#,Int8# #)) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) (uInt8#-> x1) -> WTUP2(wInt8#,wInt8#, (l x0 x1)) === WTUP2(wInt8#,wInt8#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt8#-> x0) (uInt8#-> x1) -> WTUP2(wInt8#,wInt8#, (l x0 x1)) === WTUP2(wInt8#,wInt8#, (r x0 x1))
  
  instance TestPrimop (Int8# -> Int#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Int8# -> Int8#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) -> wInt8# (l x0) === wInt8# (r x0)
  
  instance TestPrimop (Int8# -> Word8#) where
    testPrimop s l r = Property s $ \ (uInt8#-> x0) -> wWord8# (l x0) === wWord8# (r x0)
  
  instance TestPrimop (Word# -> Int# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) (uInt#-> x1) -> wWord# (l x0 x1) === wWord# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uWord#-> x0) (BoundedShiftAmount @Word shift) -> wWord# (l x0 (uInt# shift)) === wWord# (r x0 (uInt# shift))
  
  instance TestPrimop (Word# -> Word# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) (uWord#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord#-> x0) (uWord#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Word# -> Word# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) (uWord#-> x1) -> wWord# (l x0 x1) === wWord# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord#-> x0) (uWord#-> x1) -> wWord# (l x0 x1) === wWord# (r x0 x1)
  
  instance TestPrimop (Word# -> Word# -> (# Word#,Int# #)) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) (uWord#-> x1) -> WTUP2(wWord#,wInt#, (l x0 x1)) === WTUP2(wWord#,wInt#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord#-> x0) (uWord#-> x1) -> WTUP2(wWord#,wInt#, (l x0 x1)) === WTUP2(wWord#,wInt#, (r x0 x1))
  
  instance TestPrimop (Word# -> Word# -> (# Word#,Word# #)) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) (uWord#-> x1) -> WTUP2(wWord#,wWord#, (l x0 x1)) === WTUP2(wWord#,wWord#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord#-> x0) (uWord#-> x1) -> WTUP2(wWord#,wWord#, (l x0 x1)) === WTUP2(wWord#,wWord#, (r x0 x1))
  
  instance TestPrimop (Word# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wInt# (l x0) === wInt# (r x0)
  
  instance TestPrimop (Word# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Word# -> Word16#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wWord16# (l x0) === wWord16# (r x0)
  
  instance TestPrimop (Word# -> Word32#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wWord32# (l x0) === wWord32# (r x0)
  
  instance TestPrimop (Word# -> Word64#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wWord64# (l x0) === wWord64# (r x0)
  
  instance TestPrimop (Word# -> Word8#) where
    testPrimop s l r = Property s $ \ (uWord#-> x0) -> wWord8# (l x0) === wWord8# (r x0)
  
  instance TestPrimop (Word16# -> Int# -> Word16#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) (uInt#-> x1) -> wWord16# (l x0 x1) === wWord16# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uWord16#-> x0) (BoundedShiftAmount @Word16 shift) -> wWord16# (l x0 (uInt# shift)) === wWord16# (r x0 (uInt# shift))
  
  instance TestPrimop (Word16# -> Word16# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) (uWord16#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord16#-> x0) (uWord16#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Word16# -> Word16# -> Word16#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) (uWord16#-> x1) -> wWord16# (l x0 x1) === wWord16# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord16#-> x0) (uWord16#-> x1) -> wWord16# (l x0 x1) === wWord16# (r x0 x1)
  
  instance TestPrimop (Word16# -> Word16# -> (# Word16#,Word16# #)) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) (uWord16#-> x1) -> WTUP2(wWord16#,wWord16#, (l x0 x1)) === WTUP2(wWord16#,wWord16#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord16#-> x0) (uWord16#-> x1) -> WTUP2(wWord16#,wWord16#, (l x0 x1)) === WTUP2(wWord16#,wWord16#, (r x0 x1))
  
  instance TestPrimop (Word16# -> Int16#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) -> wInt16# (l x0) === wInt16# (r x0)
  
  instance TestPrimop (Word16# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Word16# -> Word16#) where
    testPrimop s l r = Property s $ \ (uWord16#-> x0) -> wWord16# (l x0) === wWord16# (r x0)
  
  instance TestPrimop (Word32# -> Int# -> Word32#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) (uInt#-> x1) -> wWord32# (l x0 x1) === wWord32# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uWord32#-> x0) (BoundedShiftAmount @Word32 shift) -> wWord32# (l x0 (uInt# shift)) === wWord32# (r x0 (uInt# shift))
  
  instance TestPrimop (Word32# -> Word32# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) (uWord32#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord32#-> x0) (uWord32#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Word32# -> Word32# -> Word32#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) (uWord32#-> x1) -> wWord32# (l x0 x1) === wWord32# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord32#-> x0) (uWord32#-> x1) -> wWord32# (l x0 x1) === wWord32# (r x0 x1)
  
  instance TestPrimop (Word32# -> Word32# -> (# Word32#,Word32# #)) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) (uWord32#-> x1) -> WTUP2(wWord32#,wWord32#, (l x0 x1)) === WTUP2(wWord32#,wWord32#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord32#-> x0) (uWord32#-> x1) -> WTUP2(wWord32#,wWord32#, (l x0 x1)) === WTUP2(wWord32#,wWord32#, (r x0 x1))
  
  instance TestPrimop (Word32# -> Int32#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) -> wInt32# (l x0) === wInt32# (r x0)
  
  instance TestPrimop (Word32# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Word32# -> Word32#) where
    testPrimop s l r = Property s $ \ (uWord32#-> x0) -> wWord32# (l x0) === wWord32# (r x0)
  
  instance TestPrimop (Word64# -> Int# -> Word64#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) (uInt#-> x1) -> wWord64# (l x0 x1) === wWord64# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uWord64#-> x0) (BoundedShiftAmount @Word64 shift) -> wWord64# (l x0 (uInt# shift)) === wWord64# (r x0 (uInt# shift))
  
  instance TestPrimop (Word64# -> Word64# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) (uWord64#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord64#-> x0) (uWord64#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Word64# -> Word64# -> Word64#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) (uWord64#-> x1) -> wWord64# (l x0 x1) === wWord64# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord64#-> x0) (uWord64#-> x1) -> wWord64# (l x0 x1) === wWord64# (r x0 x1)
  
  instance TestPrimop (Word64# -> Int64#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) -> wInt64# (l x0) === wInt64# (r x0)
  
  instance TestPrimop (Word64# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Word64# -> Word64#) where
    testPrimop s l r = Property s $ \ (uWord64#-> x0) -> wWord64# (l x0) === wWord64# (r x0)
  
  instance TestPrimop (Word8# -> Int# -> Word8#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) (uInt#-> x1) -> wWord8# (l x0 x1) === wWord8# (r x0 x1)
    testPrimopShift s l r = Property s $ \ (uWord8#-> x0) (BoundedShiftAmount @Word8 shift) -> wWord8# (l x0 (uInt# shift)) === wWord8# (r x0 (uInt# shift))
  
  instance TestPrimop (Word8# -> Word8# -> Int#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) (uWord8#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord8#-> x0) (uWord8#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
  
  instance TestPrimop (Word8# -> Word8# -> Word8#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) (uWord8#-> x1) -> wWord8# (l x0 x1) === wWord8# (r x0 x1)
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord8#-> x0) (uWord8#-> x1) -> wWord8# (l x0 x1) === wWord8# (r x0 x1)
  
  instance TestPrimop (Word8# -> Word8# -> (# Word8#,Word8# #)) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) (uWord8#-> x1) -> WTUP2(wWord8#,wWord8#, (l x0 x1)) === WTUP2(wWord8#,wWord8#, (r x0 x1))
    testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uWord8#-> x0) (uWord8#-> x1) -> WTUP2(wWord8#,wWord8#, (l x0 x1)) === WTUP2(wWord8#,wWord8#, (r x0 x1))
  
  instance TestPrimop (Word8# -> Int8#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) -> wInt8# (l x0) === wInt8# (r x0)
  
  instance TestPrimop (Word8# -> Word#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) -> wWord# (l x0) === wWord# (r x0)
  
  instance TestPrimop (Word8# -> Word8#) where
    testPrimop s l r = Property s $ \ (uWord8#-> x0) -> wWord8# (l x0) === wWord8# (r x0)
  