import Options.Applicative import Control.Monad import System.TimeIt import Foreign.C.Types import Data.Number.Flint main = timeItNamed "binet" $ run =<< customExecParser (prefs showHelpOnEmpty) opts where desc = "This program computes the n-th Fibonacci number using Binet’s formula" opts = info (parameters <**> helper) ( fullDesc <> progDesc desc <> header desc) run params@(Parameters n limit) = do ctx <- newCaCtx [sqrt5, phi, psi, t, u] <- replicateM 5 (newCa ctx) withCaCtx ctx $ \ctx -> do case limit of Just prec -> ca_ctx_set_option ctx ca_opt_prec_limit prec _ -> return () withCa sqrt5 $ \sqrt5 -> do withCa phi $ \phi -> do withCa psi $ \psi -> do withCa t $ \t -> do withCa u $ \u -> do ca_sqrt_ui sqrt5 5 ctx ca_add_ui phi sqrt5 1 ctx ca_div_ui phi phi 2 ctx ca_ui_sub psi 1 phi ctx withFmpz n $ \n -> do ca_pow_fmpz t phi n ctx ca_pow_fmpz u psi n ctx ca_sub t t u ctx ca_div t t sqrt5 ctx ca_print t ctx; putStr "\n" -- Parser ---------------------------------------------------------------------- data Parameters = Parameters { n :: Fmpz , limit :: Maybe CLong } deriving Show parameters :: Parser Parameters parameters = Parameters <$> argument auto ( help "nth power" <> metavar "n") <*> optional optionLimit optionLimit = option auto ( help "limiting precision" <> long "limit" <> metavar "limit")