packages feed

Flint2-Examples-0.1.0.0: app/multi_crt/Main.hs

{-# language ScopedTypeVariables #-}
import Options.Applicative

import Control.Monad
import Foreign.C.Types
import Foreign.Ptr 
import Foreign.Marshal.Array
import Foreign.Storable

import Data.Number.Flint

main = run =<< customExecParser (prefs showHelpOnEmpty) opts where
  desc = "Reconstruct integer using the chinese remainder theorem."
  hdesc = "Fast tree version of the integer Chinese Remainder code."
  opts = info (parameters <**> helper) (
         fullDesc
      <> progDesc desc
      <> header desc)

run params@(Parameters n num_primes) = do
  print params
  primes <- mapM n_nth_prime [1..fromIntegral num_primes]
  withArray primes $ \primes -> do
    comb <- newFmpzComb (castPtr primes) (fromIntegral num_primes)
    withFmpzComb comb $ \comb -> do
      comb_temp <- newFmpzCombTemp comb
      withFmpzCombTemp comb_temp $ \comb_temp -> do
        withFmpz n $ \x -> do
          withNewFmpz $ \y -> do
            allocaArray num_primes $ \(residues :: Ptr CLong) -> do
              --  Reduce modulo all primes 
              fmpz_multi_mod_ui (castPtr residues) x comb comb_temp
              -- Reconstruct
              fmpz_multi_CRT_ui y (castPtr residues) comb comb_temp 1
              forM_ [0 .. fromIntegral num_primes - 1] $ \i -> do
                p <- peek (primes   `advancePtr` i)
                r <- peek (residues `advancePtr` i)
                putStrLn $ "residue mod " ++ show p ++ " = " ++ show r
              putStr "reconstruction = "
              fmpz_print y
              putStr "\n"
  
data Parameters = Parameters {
    n :: Fmpz
  , num_primes :: Int
} deriving Show

parameters :: Parser Parameters
parameters = Parameters
  <$> argument auto (
      help "n to be reconstructed"
   <> metavar "n")
  <*> option auto (
      help "number of primes [2, 3, ...] to use"
   <> long "np"
   <> value 1
   <> metavar "num_primes")