import System.Environment import System.TimeIt import Options.Applicative import Control.Monad import Control.Monad.State import Text.Read (readMaybe) import Options.Applicative import Foreign.C.Types import Foreign.Ptr import Data.Number.Flint main = timeItNamed "time" $ run =<< customExecParser (prefs showHelpOnEmpty) opts where desc = "Calculates class polynomial for negative discriminant." opts = info (parameters <**> helper) ( fullDesc <> progDesc desc <> header desc) run (Parameters d num_threads) = do flint_set_num_threads num_threads res <- newFmpzPoly withFmpzPoly res $ \res -> acb_modular_hilbert_class_poly res d when (abs d <= 100) $ print res data Parameters = Parameters { d :: CLong , num_threads :: CInt } deriving Show parameters :: Parser Parameters parameters = Parameters <$> argument discriminant ( help "absolute value of (-D)" <> metavar "D") <*> option auto ( help "number of threads" <> long "threads" <> value 1 <> metavar "threads") discriminant :: (Read a, Integral a, Show a) => ReadM a discriminant = eitherReader $ \s -> do let d = negate $ read s if d < 0 then if d `mod` 4 == 1 || d `mod` 4 == 0 then Right d else Left $ "discriminant D (=" ++ show d ++ ") `mod` 4 /= 0, 1." else Left $ "discriminant D (=" ++ show d ++ ") > 0."