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

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

import Control.Monad
import Control.Monad.ST
import qualified Data.Binary as Bin
import qualified Data.ByteString.Lazy.Char8 as BS
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Vector.Generic (freeze)
import qualified Data.Vector.Storable as SVec
import qualified Data.Vector.Storable.Mutable as USVec
import Data.Word
import qualified Futhark.Data 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 (..),
    Value,
    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 (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
/= :: OutputFormat -> OutputFormat -> Bool
$c/= :: OutputFormat -> OutputFormat -> Bool
== :: OutputFormat -> OutputFormat -> Bool
$c== :: 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
min :: OutputFormat -> OutputFormat -> OutputFormat
$cmin :: OutputFormat -> OutputFormat -> OutputFormat
max :: OutputFormat -> OutputFormat -> OutputFormat
$cmax :: OutputFormat -> OutputFormat -> OutputFormat
>= :: OutputFormat -> OutputFormat -> Bool
$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
compare :: OutputFormat -> OutputFormat -> Ordering
$ccompare :: OutputFormat -> OutputFormat -> Ordering
$cp1Ord :: Eq 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
showList :: [OutputFormat] -> ShowS
$cshowList :: [OutputFormat] -> ShowS
show :: OutputFormat -> String
$cshow :: OutputFormat -> String
showsPrec :: Int -> OutputFormat -> ShowS
$cshowsPrec :: Int -> 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 :: Int
optSeed = Int
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
     String (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 :: [Word64 -> IO ()]
optOrders =
                          DataOptions -> [Word64 -> IO ()]
optOrders DataOptions
config
                            [Word64 -> IO ()] -> [Word64 -> IO ()] -> [Word64 -> IO ()]
forall a. [a] -> [a] -> [a]
++ [RandomConfiguration -> OutputFormat -> Word64 -> IO ()
g (DataOptions -> RandomConfiguration
optRange DataOptions
config) (DataOptions -> OutputFormat
format DataOptions
config)]
                      }
                Left String
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 -> String -> IO ()
hPutStrLn Handle
stderr String
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 :: OutputFormat
format = OutputFormat
Text})
      String
"Output data in text 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
"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 :: OutputFormat
format = OutputFormat
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 :: OutputFormat
format = OutputFormat
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 :: 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 :: RandomConfiguration
optRange = Range a -> RandomConfiguration -> RandomConfiguration
set (a
lower', a
upper') (RandomConfiguration -> RandomConfiguration)
-> RandomConfiguration -> RandomConfiguration
forall a b. (a -> b) -> a -> b
$ DataOptions -> RandomConfiguration
optRange DataOptions
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 String (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
tryMakeGenerator :: String
-> Either
     String (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
     String (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
forall (m :: * -> *) a. Monad m => a -> m a
return ((RandomConfiguration -> OutputFormat -> Word64 -> IO ())
 -> Either
      String (RandomConfiguration -> OutputFormat -> Word64 -> IO ()))
-> (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
-> Either
     String (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 String ValueType
toValueType (UncheckedTypeExp -> Either String ValueType)
-> Either String UncheckedTypeExp -> Either String ValueType
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (ParseError -> Either String UncheckedTypeExp)
-> (UncheckedTypeExp -> Either String UncheckedTypeExp)
-> Either ParseError UncheckedTypeExp
-> Either String UncheckedTypeExp
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> Either String UncheckedTypeExp
forall a b. a -> Either a b
Left (String -> Either String UncheckedTypeExp)
-> (ParseError -> String)
-> ParseError
-> Either String UncheckedTypeExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseError -> String
forall a. Show a => a -> String
show) UncheckedTypeExp -> Either String UncheckedTypeExp
forall a b. b -> Either a b
Right (String -> Text -> Either ParseError UncheckedTypeExp
parseType String
name (String -> Text
T.pack String
t))
    (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
-> Either
     String (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
forall (m :: * -> *) a. Monad m => a -> m a
return ((RandomConfiguration -> OutputFormat -> Word64 -> IO ())
 -> Either
      String (RandomConfiguration -> OutputFormat -> Word64 -> IO ()))
-> (RandomConfiguration -> OutputFormat -> Word64 -> IO ())
-> Either
     String (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 String V.ValueType
toValueType :: UncheckedTypeExp -> Either String ValueType
toValueType TETuple {} = String -> Either String ValueType
forall a b. a -> Either a b
Left String
"Cannot handle tuples yet."
toValueType TERecord {} = String -> Either String ValueType
forall a b. a -> Either a b
Left String
"Cannot handle records yet."
toValueType TEApply {} = String -> Either String ValueType
forall a b. a -> Either a b
Left String
"Cannot handle type applications yet."
toValueType TEArrow {} = String -> Either String ValueType
forall a b. a -> Either a b
Left String
"Cannot generate functions."
toValueType TESum {} = String -> Either String ValueType
forall a b. a -> Either a b
Left String
"Cannot handle sumtypes yet."
toValueType (TEUnique UncheckedTypeExp
t SrcLoc
_) = UncheckedTypeExp -> Either String ValueType
toValueType UncheckedTypeExp
t
toValueType (TEArray UncheckedTypeExp
t DimExp Name
d SrcLoc
_) = do
  Int
d' <- DimExp Name -> Either String Int
forall a vn. IsString a => DimExp vn -> Either a Int
constantDim DimExp Name
d
  V.ValueType [Int]
ds PrimType
t' <- UncheckedTypeExp -> Either String ValueType
toValueType UncheckedTypeExp
t
  ValueType -> Either String ValueType
forall (m :: * -> *) a. Monad m => a -> m a
return (ValueType -> Either String ValueType)
-> ValueType -> Either String 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 :: DimExp vn -> Either a Int
constantDim (DimExpConst Int
k SrcLoc
_) = Int -> Either a Int
forall a b. b -> Either a b
Right Int
k
    constantDim DimExp vn
_ = a -> Either a Int
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 String ValueType
forall a b. b -> Either a b
Right (ValueType -> Either String ValueType)
-> ValueType -> Either String 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
_) =
  String -> Either String ValueType
forall a b. a -> Either a b
Left (String -> Either String ValueType)
-> String -> Either String ValueType
forall a b. (a -> b) -> a -> b
$ String
"Unknown type " String -> ShowS
forall a. [a] -> [a] -> [a]
++ QualName Name -> String
forall a. Pretty a => a -> String
pretty 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 :: Range Int8
i8Range = Range Int8
bounds}

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

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

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

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

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

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

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

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

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

setf64Range :: Range Double -> RandomConfiguration -> RandomConfiguration
setf64Range :: Range Double -> RandomConfiguration -> RandomConfiguration
setf64Range Range Double
bounds RandomConfiguration
config = RandomConfiguration
config {f64Range :: Range Double
f64Range = Range Double
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 :: 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 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 s v
MVector (PrimState (ST s)) v
arr Int
i v
v
          t
g' t -> ST s () -> ST s ()
`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 (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 MVector s v
Mutable Vector (PrimState (ST s)) v
arr
  where
    n :: Int
n = [Int] -> Int
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 :: 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
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