    {-# LANGUAGE Strict #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}

    -- | @futhark dataset@
    module Futhark.CLI.Dataset (main) where

    import Control.Monad
    import Control.Monad.ST
    import Data.Binary qualified as Bin
    import Data.ByteString.Lazy.Char8 qualified as BS
    import Data.Text qualified as T
    import Data.Text.IO qualified as T
    import Data.Vector.Generic (freeze)
    import Data.Vector.Storable qualified as SVec
    import Data.Vector.Storable.Mutable qualified as USVec
    import Data.Word
    import Futhark.Data qualified as V
    import Futhark.Data.Reader (readValues)
    import Futhark.Util (convFloat)
    import Futhark.Util.Options
    import Language.Futhark.Parser
    import Language.Futhark.Pretty ()
    import Language.Futhark.Prop (UncheckedTypeExp)
    import Language.Futhark.Syntax hiding
      ( FloatValue (..),
        IntValue (..),
        PrimValue (..),
        ValueType,
      )
    import System.Exit
    import System.IO
    import System.Random (mkStdGen, uniformR)
    import System.Random.Stateful (UniformRange (..))

    -- | Run @futhark dataset@.
    main :: String -> [String] -> IO ()
    main :: String -> [String] -> IO ()
    main = DataOptions
    -> [FunOptDescr DataOptions]
    -> String
    -> ([String] -> DataOptions -> Maybe (IO ()))
    -> String
    -> [String]
    -> IO ()
    forall cfg.
    cfg
    -> [FunOptDescr cfg]
    -> String
    -> ([String] -> cfg -> Maybe (IO ()))
    -> String
    -> [String]
    -> IO ()
    mainWithOptions DataOptions
    initialDataOptions [FunOptDescr DataOptions]
    commandLineOptions String
    "options..." [String] -> DataOptions -> Maybe (IO ())
    forall {a}. [a] -> DataOptions -> Maybe (IO ())
    f
      where
        f :: [a] -> DataOptions -> Maybe (IO ())
    f [] DataOptions
    config
          | [Word64 -> IO ()] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([Word64 -> IO ()] -> Bool) -> [Word64 -> IO ()] -> Bool
    forall a b. (a -> b) -> a -> b
    $ DataOptions -> [Word64 -> IO ()]
    optOrders DataOptions
    config = IO () -> Maybe (IO ())
    forall a. a -> Maybe a
    Just (IO () -> Maybe (IO ())) -> IO () -> Maybe (IO ())
    forall a b. (a -> b) -> a -> b
    $ do
              Maybe [Value]
    maybe_vs <- ByteString -> Maybe [Value]
    readValues (ByteString -> Maybe [Value])
    -> IO ByteString -> IO (Maybe [Value])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO ByteString
    BS.getContents
              case Maybe [Value]
    maybe_vs of
                Maybe [Value]
    Nothing -> do
                  Handle -> String -> IO ()
    hPutStrLn Handle
    stderr String
    "Malformed data on standard input."
                  IO ()
    forall a. IO a
    exitFailure
                Just [Value]
    vs ->
                  case DataOptions -> OutputFormat
    format DataOptions
    config of
                    OutputFormat
    Text -> (Value -> IO ()) -> [Value] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (Text -> IO ()
    T.putStrLn (Text -> IO ()) -> (Value -> Text) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Text
    V.valueText) [Value]
    vs
                    OutputFormat
    Binary -> (Value -> IO ()) -> [Value] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (ByteString -> IO ()
    BS.putStr (ByteString -> IO ()) -> (Value -> ByteString) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> ByteString
    forall a. Binary a => a -> ByteString
    Bin.encode) [Value]
    vs
                    OutputFormat
    Type -> (Value -> IO ()) -> [Value] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (Text -> IO ()
    T.putStrLn (Text -> IO ()) -> (Value -> Text) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ValueType -> Text
    V.valueTypeText (ValueType -> Text) -> (Value -> ValueType) -> Value -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> ValueType
    V.valueType) [Value]
    vs
          | Bool
    otherwise =
              IO () -> Maybe (IO ())
    forall a. a -> Maybe a
    Just (IO () -> Maybe (IO ())) -> IO () -> Maybe (IO ())
    forall a b. (a -> b) -> a -> b
    $
                ((Word64 -> IO ()) -> Word64 -> IO ())
    -> [Word64 -> IO ()] -> [Word64] -> IO ()
    forall (m :: * -> *) a b c.
    Applicative m =>
    (a -> b -> m c) -> [a] -> [b] -> m ()
    zipWithM_
                  (Word64 -> IO ()) -> Word64 -> IO ()
    forall a b. (a -> b) -> a -> b
    ($)
                  (DataOptions -> [Word64 -> IO ()]
    optOrders DataOptions
    config)
                  [Int -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (DataOptions -> Int
    optSeed DataOptions
    config) ..]
        f [a]
    _ DataOptions
    _ =
          Maybe (IO ())
    forall a. Maybe a
    Nothing

    data OutputFormat
      = Text
      | Binary
      | Type
      deriving (OutputFormat -> OutputFormat -> Bool
    (OutputFormat -> OutputFormat -> Bool)
    -> (OutputFormat -> OutputFormat -> Bool) -> Eq OutputFormat
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: OutputFormat -> OutputFormat -> Bool
    == :: OutputFormat -> OutputFormat -> Bool
    $c/= :: OutputFormat -> OutputFormat -> Bool
    /= :: OutputFormat -> OutputFormat -> Bool
    Eq, Eq OutputFormat
    Eq OutputFormat =>
    (OutputFormat -> OutputFormat -> Ordering)
    -> (OutputFormat -> OutputFormat -> Bool)
    -> (OutputFormat -> OutputFormat -> Bool)
    -> (OutputFormat -> OutputFormat -> Bool)
    -> (OutputFormat -> OutputFormat -> Bool)
    -> (OutputFormat -> OutputFormat -> OutputFormat)
    -> (OutputFormat -> OutputFormat -> OutputFormat)
    -> Ord OutputFormat
    OutputFormat -> OutputFormat -> Bool
    OutputFormat -> OutputFormat -> Ordering
    OutputFormat -> OutputFormat -> OutputFormat
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: OutputFormat -> OutputFormat -> Ordering
    compare :: OutputFormat -> OutputFormat -> Ordering
    $c< :: OutputFormat -> OutputFormat -> Bool
    < :: OutputFormat -> OutputFormat -> Bool
    $c<= :: OutputFormat -> OutputFormat -> Bool
    <= :: OutputFormat -> OutputFormat -> Bool
    $c> :: OutputFormat -> OutputFormat -> Bool
    > :: OutputFormat -> OutputFormat -> Bool
    $c>= :: OutputFormat -> OutputFormat -> Bool
    >= :: OutputFormat -> OutputFormat -> Bool
    $cmax :: OutputFormat -> OutputFormat -> OutputFormat
    max :: OutputFormat -> OutputFormat -> OutputFormat
    $cmin :: OutputFormat -> OutputFormat -> OutputFormat
    min :: OutputFormat -> OutputFormat -> OutputFormat
    Ord, Int -> OutputFormat -> ShowS
    [OutputFormat] -> ShowS
    OutputFormat -> String
    (Int -> OutputFormat -> ShowS)
    -> (OutputFormat -> String)
    -> ([OutputFormat] -> ShowS)
    -> Show OutputFormat
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> OutputFormat -> ShowS
    showsPrec :: Int -> OutputFormat -> ShowS
    $cshow :: OutputFormat -> String
    show :: OutputFormat -> String
    $cshowList :: [OutputFormat] -> ShowS
    showList :: [OutputFormat] -> ShowS
    Show)

    data DataOptions = DataOptions
      { DataOptions -> Int
    optSeed :: Int,
        DataOptions -> RandomConfiguration
    optRange :: RandomConfiguration,
        DataOptions -> [Word64 -> IO ()]
    optOrders :: [Word64 -> IO ()],
        DataOptions -> OutputFormat
    format :: OutputFormat
      }

    initialDataOptions :: DataOptions
    initialDataOptions :: DataOptions
    initialDataOptions = Int
    -> RandomConfiguration
    -> [Word64 -> IO ()]
    -> OutputFormat
    -> DataOptions
    DataOptions Int
    1 RandomConfiguration
    initialRandomConfiguration [] OutputFormat
    Text

    commandLineOptions :: [FunOptDescr DataOptions]
    commandLineOptions :: [FunOptDescr DataOptions]
    commandLineOptions =
      [ String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
          String
    "s"
          [String
    "seed"]
          ( (String -> Either (IO ()) (DataOptions -> DataOptions))
    -> String -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg
              ( \String
    n ->
                  case ReadS Int
    forall a. Read a => ReadS a
    reads String
    n of
                    [(Int
    n', String
    "")] ->
                      (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    config -> DataOptions
    config {optSeed = n'}
                    [(Int, String)]
    _ ->
                      IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. a -> Either a b
    Left (IO () -> Either (IO ()) (DataOptions -> DataOptions))
    -> IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ do
                        Handle -> String -> IO ()
    hPutStrLn Handle
    stderr (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String
    "'" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    n String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "' is not an integer."
                        IO ()
    forall a. IO a
    exitFailure
              )
              String
    "SEED"
          )
          String
    "The seed to use when initialising the RNG.",
        String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
          String
    "g"
          [String
    "generate"]
          ( (String -> Either (IO ()) (DataOptions -> DataOptions))
    -> String -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg
              ( \String
    t ->
                  case String
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    tryMakeGenerator String
    t of
                    Right RandomConfiguration -> OutputFormat -> Word64 -> IO ()
    g ->
                      (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    config ->
                        DataOptions
    config
                          { optOrders =
                              optOrders config
                                ++ [g (optRange config) (format config)]
                          }
                    Left Text
    err ->
                      IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. a -> Either a b
    Left (IO () -> Either (IO ()) (DataOptions -> DataOptions))
    -> IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ do
                        Handle -> Text -> IO ()
    T.hPutStrLn Handle
    stderr Text
    err
                        IO ()
    forall a. IO a
    exitFailure
              )
              String
    "TYPE"
          )
          String
    "Generate a random value of this type.",
        String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
          []
          [String
    "text"]
          (Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. a -> ArgDescr a
    NoArg (Either (IO ()) (DataOptions -> DataOptions)
     -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions)))
    -> Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a b. (a -> b) -> a -> b
    $ (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    opts -> DataOptions
    opts {format = Text})
          String
    "Output data in text format (default; must precede --generate).",
        String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
          String
    "b"
          [String
    "binary"]
          (Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. a -> ArgDescr a
    NoArg (Either (IO ()) (DataOptions -> DataOptions)
     -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions)))
    -> Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a b. (a -> b) -> a -> b
    $ (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    opts -> DataOptions
    opts {format = Binary})
          String
    "Output data in binary Futhark format (must precede --generate).",
        String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
          String
    "t"
          [String
    "type"]
          (Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. a -> ArgDescr a
    NoArg (Either (IO ()) (DataOptions -> DataOptions)
     -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions)))
    -> Either (IO ()) (DataOptions -> DataOptions)
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a b. (a -> b) -> a -> b
    $ (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    opts -> DataOptions
    opts {format = Type})
          String
    "Output the type (textually) rather than the value (must precede --generate).",
        String
    -> (Range Int8 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "i8" Range Int8 -> RandomConfiguration -> RandomConfiguration
    seti8Range,
        String
    -> (Range Int16 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "i16" Range Int16 -> RandomConfiguration -> RandomConfiguration
    seti16Range,
        String
    -> (Range Int32 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "i32" Range Int32 -> RandomConfiguration -> RandomConfiguration
    seti32Range,
        String
    -> (Range Int64 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "i64" Range Int64 -> RandomConfiguration -> RandomConfiguration
    seti64Range,
        String
    -> (Range Word8 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "u8" Range Word8 -> RandomConfiguration -> RandomConfiguration
    setu8Range,
        String
    -> (Range Word16 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "u16" Range Word16 -> RandomConfiguration -> RandomConfiguration
    setu16Range,
        String
    -> (Range Word32 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "u32" Range Word32 -> RandomConfiguration -> RandomConfiguration
    setu32Range,
        String
    -> (Range Word64 -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "u64" Range Word64 -> RandomConfiguration -> RandomConfiguration
    setu64Range,
        String
    -> (Range Half -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "f16" Range Half -> RandomConfiguration -> RandomConfiguration
    setf16Range,
        String
    -> (Range Float -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "f32" Range Float -> RandomConfiguration -> RandomConfiguration
    setf32Range,
        String
    -> (Range Double -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    "f64" Range Double -> RandomConfiguration -> RandomConfiguration
    setf64Range
      ]

    setRangeOption ::
      (Read a) =>
      String ->
      (Range a -> RandomConfiguration -> RandomConfiguration) ->
      FunOptDescr DataOptions
    setRangeOption :: forall a.
    Read a =>
    String
    -> (Range a -> RandomConfiguration -> RandomConfiguration)
    -> FunOptDescr DataOptions
    setRangeOption String
    tname Range a -> RandomConfiguration -> RandomConfiguration
    set =
      String
    -> [String]
    -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    -> String
    -> FunOptDescr DataOptions
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option
        String
    ""
        [String
    name]
        ( (String -> Either (IO ()) (DataOptions -> DataOptions))
    -> String -> ArgDescr (Either (IO ()) (DataOptions -> DataOptions))
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg
            ( \String
    b ->
                let (String
    lower, String
    rest) = (Char -> Bool) -> String -> (String, String)
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    ':') String
    b
                    upper :: String
    upper = Int -> ShowS
    forall a. Int -> [a] -> [a]
    drop Int
    1 String
    rest
                 in case (ReadS a
    forall a. Read a => ReadS a
    reads String
    lower, ReadS a
    forall a. Read a => ReadS a
    reads String
    upper) of
                      ([(a
    lower', String
    "")], [(a
    upper', String
    "")]) ->
                        (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. b -> Either a b
    Right ((DataOptions -> DataOptions)
     -> Either (IO ()) (DataOptions -> DataOptions))
    -> (DataOptions -> DataOptions)
    -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ \DataOptions
    config ->
                          DataOptions
    config {optRange = set (lower', upper') $ optRange config}
                      ([(a, String)], [(a, String)])
    _ ->
                        IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. a -> Either a b
    Left (IO () -> Either (IO ()) (DataOptions -> DataOptions))
    -> IO () -> Either (IO ()) (DataOptions -> DataOptions)
    forall a b. (a -> b) -> a -> b
    $ do
                          Handle -> String -> IO ()
    hPutStrLn Handle
    stderr (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Invalid bounds for " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    tname String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    ": " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    b
                          IO ()
    forall a. IO a
    exitFailure
            )
            String
    "MIN:MAX"
        )
        (String -> FunOptDescr DataOptions)
    -> String -> FunOptDescr DataOptions
    forall a b. (a -> b) -> a -> b
    $ String
    "Range of " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    tname String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " values."
      where
        name :: String
    name = String
    tname String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "-bounds"

    tryMakeGenerator ::
      String ->
      Either T.Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    tryMakeGenerator :: String
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    tryMakeGenerator String
    t
      | Just [Value]
    vs <- ByteString -> Maybe [Value]
    readValues (ByteString -> Maybe [Value]) -> ByteString -> Maybe [Value]
    forall a b. (a -> b) -> a -> b
    $ String -> ByteString
    BS.pack String
    t =
          (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ((RandomConfiguration -> OutputFormat -> Word64 -> IO ())
     -> Either
          Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ()))
    -> (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    forall a b. (a -> b) -> a -> b
    $ \RandomConfiguration
    _ OutputFormat
    fmt Word64
    _ -> (Value -> IO ()) -> [Value] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (OutputFormat -> Value -> IO ()
    outValue OutputFormat
    fmt) [Value]
    vs
      | Bool
    otherwise = do
          ValueType
    t' <- UncheckedTypeExp -> Either Text ValueType
    toValueType (UncheckedTypeExp -> Either Text ValueType)
    -> Either Text UncheckedTypeExp -> Either Text ValueType
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< (SyntaxError -> Either Text UncheckedTypeExp)
    -> (UncheckedTypeExp -> Either Text UncheckedTypeExp)
    -> Either SyntaxError UncheckedTypeExp
    -> Either Text UncheckedTypeExp
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (Text -> Either Text UncheckedTypeExp
    forall a b. a -> Either a b
    Left (Text -> Either Text UncheckedTypeExp)
    -> (SyntaxError -> Text)
    -> SyntaxError
    -> Either Text UncheckedTypeExp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SyntaxError -> Text
    syntaxErrorMsg) UncheckedTypeExp -> Either Text UncheckedTypeExp
    forall a b. b -> Either a b
    Right (String -> Text -> Either SyntaxError UncheckedTypeExp
    parseType String
    name (String -> Text
    T.pack String
    t))
          (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ((RandomConfiguration -> OutputFormat -> Word64 -> IO ())
     -> Either
          Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ()))
    -> (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    -> Either
         Text (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
    forall a b. (a -> b) -> a -> b
    $ \RandomConfiguration
    conf OutputFormat
    fmt Word64
    seed -> do
            let v :: Value
    v = RandomConfiguration -> ValueType -> Word64 -> Value
    randomValue RandomConfiguration
    conf ValueType
    t' Word64
    seed
            OutputFormat -> Value -> IO ()
    outValue OutputFormat
    fmt Value
    v
      where
        name :: String
    name = String
    "option " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    t
        outValue :: OutputFormat -> Value -> IO ()
    outValue OutputFormat
    Text = Text -> IO ()
    T.putStrLn (Text -> IO ()) -> (Value -> Text) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Text
    V.valueText
        outValue OutputFormat
    Binary = ByteString -> IO ()
    BS.putStr (ByteString -> IO ()) -> (Value -> ByteString) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> ByteString
    forall a. Binary a => a -> ByteString
    Bin.encode
        outValue OutputFormat
    Type = Text -> IO ()
    T.putStrLn (Text -> IO ()) -> (Value -> Text) -> Value -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ValueType -> Text
    V.valueTypeText (ValueType -> Text) -> (Value -> ValueType) -> Value -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> ValueType
    V.valueType

    toValueType :: UncheckedTypeExp -> Either T.Text V.ValueType
    toValueType :: UncheckedTypeExp -> Either Text ValueType
    toValueType TETuple {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot handle tuples yet."
    toValueType TERecord {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot handle records yet."
    toValueType TEApply {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot handle type applications yet."
    toValueType TEArrow {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot generate functions."
    toValueType TESum {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot handle sumtypes yet."
    toValueType TEDim {} = Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left Text
    "Cannot handle existential sizes."
    toValueType (TEParens UncheckedTypeExp
    t SrcLoc
    _) = UncheckedTypeExp -> Either Text ValueType
    toValueType UncheckedTypeExp
    t
    toValueType (TEUnique UncheckedTypeExp
    t SrcLoc
    _) = UncheckedTypeExp -> Either Text ValueType
    toValueType UncheckedTypeExp
    t
    toValueType (TEArray SizeExp UncheckedExp
    d UncheckedTypeExp
    t SrcLoc
    _) = do
      Int
    d' <- SizeExp UncheckedExp -> Either Text Int
    forall {b} {a} {f :: * -> *} {vn}.
    (Num b, IsString a) =>
    SizeExp (ExpBase f vn) -> Either a b
    constantDim SizeExp UncheckedExp
    d
      V.ValueType [Int]
    ds PrimType
    t' <- UncheckedTypeExp -> Either Text ValueType
    toValueType UncheckedTypeExp
    t
      ValueType -> Either Text ValueType
    forall a. a -> Either Text a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ValueType -> Either Text ValueType)
    -> ValueType -> Either Text ValueType
    forall a b. (a -> b) -> a -> b
    $ [Int] -> PrimType -> ValueType
    V.ValueType (Int
    d' Int -> [Int] -> [Int]
    forall a. a -> [a] -> [a]
    : [Int]
    ds) PrimType
    t'
      where
        constantDim :: SizeExp (ExpBase f vn) -> Either a b
    constantDim (SizeExp (IntLit Integer
    k f StructType
    _ SrcLoc
    _) SrcLoc
    _) = b -> Either a b
    forall a b. b -> Either a b
    Right (b -> Either a b) -> b -> Either a b
    forall a b. (a -> b) -> a -> b
    $ Integer -> b
    forall a. Num a => Integer -> a
    fromInteger Integer
    k
        constantDim SizeExp (ExpBase f vn)
    _ = a -> Either a b
    forall a b. a -> Either a b
    Left a
    "Array has non-constant dimension declaration."
    toValueType (TEVar (QualName [] Name
    v) SrcLoc
    _)
      | Just PrimType
    t <- Name -> [(Name, PrimType)] -> Maybe PrimType
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup Name
    v [(Name, PrimType)]
    m = ValueType -> Either Text ValueType
    forall a b. b -> Either a b
    Right (ValueType -> Either Text ValueType)
    -> ValueType -> Either Text ValueType
    forall a b. (a -> b) -> a -> b
    $ [Int] -> PrimType -> ValueType
    V.ValueType [] PrimType
    t
      where
        m :: [(Name, PrimType)]
    m = (PrimType -> (Name, PrimType)) -> [PrimType] -> [(Name, PrimType)]
    forall a b. (a -> b) -> [a] -> [b]
    map PrimType -> (Name, PrimType)
    f [PrimType
    forall a. Bounded a => a
    minBound .. PrimType
    forall a. Bounded a => a
    maxBound]
        f :: PrimType -> (Name, PrimType)
    f PrimType
    t = (Text -> Name
    nameFromText (PrimType -> Text
    V.primTypeText PrimType
    t), PrimType
    t)
    toValueType (TEVar QualName Name
    v SrcLoc
    _) =
      Text -> Either Text ValueType
    forall a b. a -> Either a b
    Left (Text -> Either Text ValueType) -> Text -> Either Text ValueType
    forall a b. (a -> b) -> a -> b
    $ Text
    "Unknown type " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> QualName Name -> Text
    forall a. Pretty a => a -> Text
    prettyText QualName Name
    v

    -- | Closed interval, as in @System.Random@.
    type Range a = (a, a)

    data RandomConfiguration = RandomConfiguration
      { RandomConfiguration -> Range Int8
    i8Range :: Range Int8,
        RandomConfiguration -> Range Int16
    i16Range :: Range Int16,
        RandomConfiguration -> Range Int32
    i32Range :: Range Int32,
        RandomConfiguration -> Range Int64
    i64Range :: Range Int64,
        RandomConfiguration -> Range Word8
    u8Range :: Range Word8,
        RandomConfiguration -> Range Word16
    u16Range :: Range Word16,
        RandomConfiguration -> Range Word32
    u32Range :: Range Word32,
        RandomConfiguration -> Range Word64
    u64Range :: Range Word64,
        RandomConfiguration -> Range Half
    f16Range :: Range Half,
        RandomConfiguration -> Range Float
    f32Range :: Range Float,
        RandomConfiguration -> Range Double
    f64Range :: Range Double
      }

    -- The following lines provide evidence about how Haskells record
    -- system sucks.
    seti8Range :: Range Int8 -> RandomConfiguration -> RandomConfiguration
    seti8Range :: Range Int8 -> RandomConfiguration -> RandomConfiguration
    seti8Range Range Int8
    bounds RandomConfiguration
    config = RandomConfiguration
    config {i8Range = bounds}

    seti16Range :: Range Int16 -> RandomConfiguration -> RandomConfiguration
    seti16Range :: Range Int16 -> RandomConfiguration -> RandomConfiguration
    seti16Range Range Int16
    bounds RandomConfiguration
    config = RandomConfiguration
    config {i16Range = bounds}

    seti32Range :: Range Int32 -> RandomConfiguration -> RandomConfiguration
    seti32Range :: Range Int32 -> RandomConfiguration -> RandomConfiguration
    seti32Range Range Int32
    bounds RandomConfiguration
    config = RandomConfiguration
    config {i32Range = bounds}

    seti64Range :: Range Int64 -> RandomConfiguration -> RandomConfiguration
    seti64Range :: Range Int64 -> RandomConfiguration -> RandomConfiguration
    seti64Range Range Int64
    bounds RandomConfiguration
    config = RandomConfiguration
    config {i64Range = bounds}

    setu8Range :: Range Word8 -> RandomConfiguration -> RandomConfiguration
    setu8Range :: Range Word8 -> RandomConfiguration -> RandomConfiguration
    setu8Range Range Word8
    bounds RandomConfiguration
    config = RandomConfiguration
    config {u8Range = bounds}

    setu16Range :: Range Word16 -> RandomConfiguration -> RandomConfiguration
    setu16Range :: Range Word16 -> RandomConfiguration -> RandomConfiguration
    setu16Range Range Word16
    bounds RandomConfiguration
    config = RandomConfiguration
    config {u16Range = bounds}

    setu32Range :: Range Word32 -> RandomConfiguration -> RandomConfiguration
    setu32Range :: Range Word32 -> RandomConfiguration -> RandomConfiguration
    setu32Range Range Word32
    bounds RandomConfiguration
    config = RandomConfiguration
    config {u32Range = bounds}

    setu64Range :: Range Word64 -> RandomConfiguration -> RandomConfiguration
    setu64Range :: Range Word64 -> RandomConfiguration -> RandomConfiguration
    setu64Range Range Word64
    bounds RandomConfiguration
    config = RandomConfiguration
    config {u64Range = bounds}

    setf16Range :: Range Half -> RandomConfiguration -> RandomConfiguration
    setf16Range :: Range Half -> RandomConfiguration -> RandomConfiguration
    setf16Range Range Half
    bounds RandomConfiguration
    config = RandomConfiguration
    config {f16Range = bounds}

    setf32Range :: Range Float -> RandomConfiguration -> RandomConfiguration
    setf32Range :: Range Float -> RandomConfiguration -> RandomConfiguration
    setf32Range Range Float
    bounds RandomConfiguration
    config = RandomConfiguration
    config {f32Range = bounds}

    setf64Range :: Range Double -> RandomConfiguration -> RandomConfiguration
    setf64Range :: Range Double -> RandomConfiguration -> RandomConfiguration
    setf64Range Range Double
    bounds RandomConfiguration
    config = RandomConfiguration
    config {f64Range = bounds}

    initialRandomConfiguration :: RandomConfiguration
    initialRandomConfiguration :: RandomConfiguration
    initialRandomConfiguration =
      Range Int8
    -> Range Int16
    -> Range Int32
    -> Range Int64
    -> Range Word8
    -> Range Word16
    -> Range Word32
    -> Range Word64
    -> Range Half
    -> Range Float
    -> Range Double
    -> RandomConfiguration
    RandomConfiguration
        (Int8
    forall a. Bounded a => a
    minBound, Int8
    forall a. Bounded a => a
    maxBound)
        (Int16
    forall a. Bounded a => a
    minBound, Int16
    forall a. Bounded a => a
    maxBound)
        (Int32
    forall a. Bounded a => a
    minBound, Int32
    forall a. Bounded a => a
    maxBound)
        (Int64
    forall a. Bounded a => a
    minBound, Int64
    forall a. Bounded a => a
    maxBound)
        (Word8
    forall a. Bounded a => a
    minBound, Word8
    forall a. Bounded a => a
    maxBound)
        (Word16
    forall a. Bounded a => a
    minBound, Word16
    forall a. Bounded a => a
    maxBound)
        (Word32
    forall a. Bounded a => a
    minBound, Word32
    forall a. Bounded a => a
    maxBound)
        (Word64
    forall a. Bounded a => a
    minBound, Word64
    forall a. Bounded a => a
    maxBound)
        (Half
    0.0, Half
    1.0)
        (Float
    0.0, Float
    1.0)
        (Double
    0.0, Double
    1.0)

    randomValue :: RandomConfiguration -> V.ValueType -> Word64 -> V.Value
    randomValue :: RandomConfiguration -> ValueType -> Word64 -> Value
    randomValue RandomConfiguration
    conf (V.ValueType [Int]
    ds PrimType
    t) Word64
    seed =
      case PrimType
    t of
        PrimType
    V.I8 -> (RandomConfiguration -> Range Int8)
    -> (Vector Int -> Vector Int8 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Int8
    i8Range Vector Int -> Vector Int8 -> Value
    V.I8Value
        PrimType
    V.I16 -> (RandomConfiguration -> Range Int16)
    -> (Vector Int -> Vector Int16 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Int16
    i16Range Vector Int -> Vector Int16 -> Value
    V.I16Value
        PrimType
    V.I32 -> (RandomConfiguration -> Range Int32)
    -> (Vector Int -> Vector Int32 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Int32
    i32Range Vector Int -> Vector Int32 -> Value
    V.I32Value
        PrimType
    V.I64 -> (RandomConfiguration -> Range Int64)
    -> (Vector Int -> Vector Int64 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Int64
    i64Range Vector Int -> Vector Int64 -> Value
    V.I64Value
        PrimType
    V.U8 -> (RandomConfiguration -> Range Word8)
    -> (Vector Int -> Vector Word8 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Word8
    u8Range Vector Int -> Vector Word8 -> Value
    V.U8Value
        PrimType
    V.U16 -> (RandomConfiguration -> Range Word16)
    -> (Vector Int -> Vector Word16 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Word16
    u16Range Vector Int -> Vector Word16 -> Value
    V.U16Value
        PrimType
    V.U32 -> (RandomConfiguration -> Range Word32)
    -> (Vector Int -> Vector Word32 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Word32
    u32Range Vector Int -> Vector Word32 -> Value
    V.U32Value
        PrimType
    V.U64 -> (RandomConfiguration -> Range Word64)
    -> (Vector Int -> Vector Word64 -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Word64
    u64Range Vector Int -> Vector Word64 -> Value
    V.U64Value
        PrimType
    V.F16 -> (RandomConfiguration -> Range Half)
    -> (Vector Int -> Vector Half -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Half
    f16Range Vector Int -> Vector Half -> Value
    V.F16Value
        PrimType
    V.F32 -> (RandomConfiguration -> Range Float)
    -> (Vector Int -> Vector Float -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Float
    f32Range Vector Int -> Vector Float -> Value
    V.F32Value
        PrimType
    V.F64 -> (RandomConfiguration -> Range Double)
    -> (Vector Int -> Vector Double -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range Double
    f64Range Vector Int -> Vector Double -> Value
    V.F64Value
        PrimType
    V.Bool -> (RandomConfiguration -> Range Bool)
    -> (Vector Int -> Vector Bool -> Value) -> Value
    forall {v}.
    (Storable v, UniformRange v) =>
    (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen (Range Bool -> RandomConfiguration -> Range Bool
    forall a b. a -> b -> a
    const (Bool
    False, Bool
    True)) Vector Int -> Vector Bool -> Value
    V.BoolValue
      where
        gen :: (RandomConfiguration -> Range v)
    -> (Vector Int -> Vector v -> Value) -> Value
    gen RandomConfiguration -> Range v
    range Vector Int -> Vector v -> Value
    final = Range v
    -> (Vector Int -> Vector v -> Value) -> [Int] -> Word64 -> Value
    forall v.
    (Storable v, UniformRange v) =>
    Range v
    -> (Vector Int -> Vector v -> Value) -> [Int] -> Word64 -> Value
    randomVector (RandomConfiguration -> Range v
    range RandomConfiguration
    conf) Vector Int -> Vector v -> Value
    final [Int]
    ds Word64
    seed

    randomVector ::
      (SVec.Storable v, UniformRange v) =>
      Range v ->
      (SVec.Vector Int -> SVec.Vector v -> V.Value) ->
      [Int] ->
      Word64 ->
      V.Value
    randomVector :: forall v.
    (Storable v, UniformRange v) =>
    Range v
    -> (Vector Int -> Vector v -> Value) -> [Int] -> Word64 -> Value
    randomVector Range v
    range Vector Int -> Vector v -> Value
    final [Int]
    ds Word64
    seed = (forall s. ST s Value) -> Value
    forall a. (forall s. ST s a) -> a
    runST ((forall s. ST s Value) -> Value)
    -> (forall s. ST s Value) -> Value
    forall a b. (a -> b) -> a -> b
    $ do
      -- Use some nice impure computation where we can preallocate a
      -- vector of the desired size, populate it via the random number
      -- generator, and then finally reutrn a frozen binary vector.
      MVector (PrimState (ST s)) v
    arr <- Int -> ST s (MVector (PrimState (ST s)) v)
    forall (m :: * -> *) a.
    (PrimMonad m, Storable a) =>
    Int -> m (MVector (PrimState m) a)
    USVec.new Int
    n
      let fill :: t -> Int -> ST s ()
    fill t
    g Int
    i
            | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n = do
                let (v
    v, t
    g') = Range v -> t -> (v, t)
    forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
    uniformR Range v
    range t
    g
                MVector (PrimState (ST s)) v -> Int -> v -> ST s ()
    forall (m :: * -> *) a.
    (PrimMonad m, Storable a) =>
    MVector (PrimState m) a -> Int -> a -> m ()
    USVec.write MVector (PrimState (ST s)) v
    arr Int
    i v
    v
                t
    g' t -> ST s () -> ST s ()
    forall a b. a -> b -> b
    `seq` t -> Int -> ST s ()
    fill t
    g' (Int -> ST s ()) -> Int -> ST s ()
    forall a b. (a -> b) -> a -> b
    $! Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
            | Bool
    otherwise =
                () -> ST s ()
    forall a. a -> ST s a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
      StdGen -> Int -> ST s ()
    forall {t}. RandomGen t => t -> Int -> ST s ()
    fill (Int -> StdGen
    mkStdGen (Int -> StdGen) -> Int -> StdGen
    forall a b. (a -> b) -> a -> b
    $ Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word64
    seed) Int
    0
      Vector Int -> Vector v -> Value
    final ([Int] -> Vector Int
    forall a. Storable a => [a] -> Vector a
    SVec.fromList [Int]
    ds) (Vector v -> Value) -> (Vector v -> Vector v) -> Vector v -> Value
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Vector v -> Vector v
    forall (v :: * -> *) a (w :: * -> *).
    (Vector v a, Vector w a) =>
    v a -> w a
    SVec.convert (Vector v -> Value) -> ST s (Vector v) -> ST s Value
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Mutable Vector (PrimState (ST s)) v -> ST s (Vector v)
    forall (m :: * -> *) (v :: * -> *) a.
    (PrimMonad m, Vector v a) =>
    Mutable v (PrimState m) a -> m (v a)
    freeze Mutable Vector (PrimState (ST s)) v
    MVector (PrimState (ST s)) v
    arr
      where
        n :: Int
    n = [Int] -> Int
    forall a. Num a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    product [Int]
    ds

    -- XXX: The following instance is an orphan.  Maybe it could be
    -- avoided with some newtype trickery or refactoring, but it's so
    -- convenient this way.
    instance UniformRange Half where
      uniformRM :: forall g (m :: * -> *).
    StatefulGen g m =>
    Range Half -> g -> m Half
    uniformRM (Half
    a, Half
    b) g
    g =
        (Float -> Half
    forall from to. (RealFloat from, RealFloat to) => from -> to
    convFloat :: Float -> Half) (Float -> Half) -> m Float -> m Half
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Range Float -> g -> m Float
    forall a g (m :: * -> *).
    (UniformRange a, StatefulGen g m) =>
    (a, a) -> g -> m a
    forall g (m :: * -> *).
    StatefulGen g m =>
    Range Float -> g -> m Float
    uniformRM (Half -> Float
    forall from to. (RealFloat from, RealFloat to) => from -> to
    convFloat Half
    a, Half -> Float
    forall from to. (RealFloat from, RealFloat to) => from -> to
    convFloat Half
    b) g
    g