    {- |
    Module      :  Numeric.GSL.Interpolation
    Copyright   :  (c) Matthew Peddie 2015
    License     :  GPL
    Maintainer  :  Alberto Ruiz
    Stability   :  provisional

    Simulated annealing routines.

    <https://www.gnu.org/software/gsl/manual/html_node/Simulated-Annealing.html#Simulated-Annealing>

    Here is a translation of the simple example given in
    <https://www.gnu.org/software/gsl/manual/html_node/Trivial-example.html#Trivial-example the GSL manual>:

    > import Numeric.GSL.SimulatedAnnealing
    > import Numeric.LinearAlgebra.HMatrix
    >
    > main = print $ simanSolve 0 1 exampleParams 15.5 exampleE exampleM exampleS (Just show)
    >
    > exampleParams = SimulatedAnnealingParams 200 1000 1.0 1.0 0.008 1.003 2.0e-6
    >
    > exampleE x = exp (-(x - 1)**2) * sin (8 * x)
    >
    > exampleM x y = abs $ x - y
    >
    > exampleS rands stepSize current = (rands ! 0) * 2 * stepSize - stepSize + current

    The manual states:

    >     The first example, in one dimensional Cartesian space, sets up an
    >     energy function which is a damped sine wave; this has many local
    >     minima, but only one global minimum, somewhere between 1.0 and
    >     1.5. The initial guess given is 15.5, which is several local minima
    >     away from the global minimum.

    This global minimum is around 1.36.

    -}
    {-# OPTIONS_GHC -Wall #-}

    module Numeric.GSL.SimulatedAnnealing (
      -- * Searching for minima
      simanSolve
      -- * Configuring the annealing process
      , SimulatedAnnealingParams(..)
      ) where

    import Numeric.GSL.Internal
    import Numeric.LinearAlgebra.HMatrix hiding(step)

    import Data.Vector.Storable(generateM)
    import Foreign.Storable(Storable(..))
    import Foreign.Marshal.Utils(with)
    import Foreign.Ptr(Ptr, FunPtr, nullFunPtr)
    import Foreign.StablePtr(StablePtr, newStablePtr, deRefStablePtr, freeStablePtr)
    import Foreign.C.Types
    import System.IO.Unsafe(unsafePerformIO)

    import System.IO (hFlush, stdout)

    import Data.IORef (IORef, newIORef, writeIORef, readIORef, modifyIORef')

    -- | 'SimulatedAnnealingParams' is a translation of the
    -- @gsl_siman_params_t@ structure documented in
    -- <https://www.gnu.org/software/gsl/manual/html_node/Simulated-Annealing-functions.html#Simulated-Annealing-functions the GSL manual>,
    -- which controls the simulated annealing algorithm.
    --
    -- The annealing process is parameterized by the Boltzmann
    -- distribution and the /cooling schedule/.  For more details, see
    -- <https://www.gnu.org/software/gsl/manual/html_node/Simulated-Annealing-algorithm.html#Simulated-Annealing-algorithm the relevant section of the manual>.
    data SimulatedAnnealingParams = SimulatedAnnealingParams {
      SimulatedAnnealingParams -> CInt
    n_tries :: CInt  -- ^ The number of points to try for each step.
      , SimulatedAnnealingParams -> CInt
    iters_fixed_T :: CInt  -- ^ The number of iterations at each temperature
      , SimulatedAnnealingParams -> Double
    step_size :: Double    -- ^ The maximum step size in the random walk
      , SimulatedAnnealingParams -> Double
    boltzmann_k :: Double  -- ^ Boltzmann distribution parameter
      , SimulatedAnnealingParams -> Double
    cooling_t_initial :: Double -- ^ Initial temperature
      , SimulatedAnnealingParams -> Double
    cooling_mu_t :: Double      -- ^ Cooling rate parameter
      , SimulatedAnnealingParams -> Double
    cooling_t_min :: Double     -- ^ Final temperature
      } deriving (SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool
    (SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool)
    -> (SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool)
    -> Eq SimulatedAnnealingParams
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool
    == :: SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool
    $c/= :: SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool
    /= :: SimulatedAnnealingParams -> SimulatedAnnealingParams -> Bool
    Eq, Int -> SimulatedAnnealingParams -> ShowS
    [SimulatedAnnealingParams] -> ShowS
    SimulatedAnnealingParams -> String
    (Int -> SimulatedAnnealingParams -> ShowS)
    -> (SimulatedAnnealingParams -> String)
    -> ([SimulatedAnnealingParams] -> ShowS)
    -> Show SimulatedAnnealingParams
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> SimulatedAnnealingParams -> ShowS
    showsPrec :: Int -> SimulatedAnnealingParams -> ShowS
    $cshow :: SimulatedAnnealingParams -> String
    show :: SimulatedAnnealingParams -> String
    $cshowList :: [SimulatedAnnealingParams] -> ShowS
    showList :: [SimulatedAnnealingParams] -> ShowS
    Show, ReadPrec [SimulatedAnnealingParams]
    ReadPrec SimulatedAnnealingParams
    Int -> ReadS SimulatedAnnealingParams
    ReadS [SimulatedAnnealingParams]
    (Int -> ReadS SimulatedAnnealingParams)
    -> ReadS [SimulatedAnnealingParams]
    -> ReadPrec SimulatedAnnealingParams
    -> ReadPrec [SimulatedAnnealingParams]
    -> Read SimulatedAnnealingParams
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS SimulatedAnnealingParams
    readsPrec :: Int -> ReadS SimulatedAnnealingParams
    $creadList :: ReadS [SimulatedAnnealingParams]
    readList :: ReadS [SimulatedAnnealingParams]
    $creadPrec :: ReadPrec SimulatedAnnealingParams
    readPrec :: ReadPrec SimulatedAnnealingParams
    $creadListPrec :: ReadPrec [SimulatedAnnealingParams]
    readListPrec :: ReadPrec [SimulatedAnnealingParams]
    Read)

    instance Storable SimulatedAnnealingParams where
      sizeOf :: SimulatedAnnealingParams -> Int
    sizeOf SimulatedAnnealingParams
    p = CInt -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> CInt
    n_tries SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 CInt -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> CInt
    iters_fixed_T SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> Double
    step_size SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> Double
    boltzmann_k SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> Double
    cooling_t_initial SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> Double
    cooling_mu_t SimulatedAnnealingParams
    p) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +
                 Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (SimulatedAnnealingParams -> Double
    cooling_t_min SimulatedAnnealingParams
    p)
      -- TODO(MP): is this safe?
      alignment :: SimulatedAnnealingParams -> Int
    alignment SimulatedAnnealingParams
    p = Double -> Int
    forall a. Storable a => a -> Int
    alignment (SimulatedAnnealingParams -> Double
    step_size SimulatedAnnealingParams
    p)
      -- TODO(MP): Is there a more automatic way to write these?
      peek :: Ptr SimulatedAnnealingParams -> IO SimulatedAnnealingParams
    peek Ptr SimulatedAnnealingParams
    ptr = CInt
    -> CInt
    -> Double
    -> Double
    -> Double
    -> Double
    -> Double
    -> SimulatedAnnealingParams
    SimulatedAnnealingParams (CInt
     -> CInt
     -> Double
     -> Double
     -> Double
     -> Double
     -> Double
     -> SimulatedAnnealingParams)
    -> IO CInt
    -> IO
         (CInt
          -> Double
          -> Double
          -> Double
          -> Double
          -> Double
          -> SimulatedAnnealingParams)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                 Ptr SimulatedAnnealingParams -> Int -> IO CInt
    forall b. Ptr b -> Int -> IO CInt
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr Int
    0 IO
      (CInt
       -> Double
       -> Double
       -> Double
       -> Double
       -> Double
       -> SimulatedAnnealingParams)
    -> IO CInt
    -> IO
         (Double
          -> Double
          -> Double
          -> Double
          -> Double
          -> SimulatedAnnealingParams)
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO CInt
    forall b. Ptr b -> Int -> IO CInt
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr Int
    i IO
      (Double
       -> Double
       -> Double
       -> Double
       -> Double
       -> SimulatedAnnealingParams)
    -> IO Double
    -> IO
         (Double -> Double -> Double -> Double -> SimulatedAnnealingParams)
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO Double
    forall b. Ptr b -> Int -> IO Double
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i) IO
      (Double -> Double -> Double -> Double -> SimulatedAnnealingParams)
    -> IO Double
    -> IO (Double -> Double -> Double -> SimulatedAnnealingParams)
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO Double
    forall b. Ptr b -> Int -> IO Double
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    d) IO (Double -> Double -> Double -> SimulatedAnnealingParams)
    -> IO Double -> IO (Double -> Double -> SimulatedAnnealingParams)
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO Double
    forall b. Ptr b -> Int -> IO Double
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d) IO (Double -> Double -> SimulatedAnnealingParams)
    -> IO Double -> IO (Double -> SimulatedAnnealingParams)
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO Double
    forall b. Ptr b -> Int -> IO Double
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d) IO (Double -> SimulatedAnnealingParams)
    -> IO Double -> IO SimulatedAnnealingParams
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
                 Ptr SimulatedAnnealingParams -> Int -> IO Double
    forall b. Ptr b -> Int -> IO Double
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d)
        where
          i :: Int
    i = CInt -> Int
    forall a. Storable a => a -> Int
    sizeOf (CInt
    0 :: CInt)
          d :: Int
    d = Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (Double
    0 :: Double)
      poke :: Ptr SimulatedAnnealingParams -> SimulatedAnnealingParams -> IO ()
    poke Ptr SimulatedAnnealingParams
    ptr SimulatedAnnealingParams
    sap = do
        Ptr SimulatedAnnealingParams -> Int -> CInt -> IO ()
    forall b. Ptr b -> Int -> CInt -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr Int
    0 (SimulatedAnnealingParams -> CInt
    n_tries SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> CInt -> IO ()
    forall b. Ptr b -> Int -> CInt -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr Int
    i (SimulatedAnnealingParams -> CInt
    iters_fixed_T SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> Double -> IO ()
    forall b. Ptr b -> Int -> Double -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i) (SimulatedAnnealingParams -> Double
    step_size SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> Double -> IO ()
    forall b. Ptr b -> Int -> Double -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    d) (SimulatedAnnealingParams -> Double
    boltzmann_k SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> Double -> IO ()
    forall b. Ptr b -> Int -> Double -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d) (SimulatedAnnealingParams -> Double
    cooling_t_initial SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> Double -> IO ()
    forall b. Ptr b -> Int -> Double -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d) (SimulatedAnnealingParams -> Double
    cooling_mu_t SimulatedAnnealingParams
    sap)
        Ptr SimulatedAnnealingParams -> Int -> Double -> IO ()
    forall b. Ptr b -> Int -> Double -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr SimulatedAnnealingParams
    ptr (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    d) (SimulatedAnnealingParams -> Double
    cooling_t_min SimulatedAnnealingParams
    sap)
        where
          i :: Int
    i = CInt -> Int
    forall a. Storable a => a -> Int
    sizeOf (CInt
    0 :: CInt)
          d :: Int
    d = Double -> Int
    forall a. Storable a => a -> Int
    sizeOf (Double
    0 :: Double)

    -- We use a StablePtr to an IORef so that we can keep hold of
    -- StablePtr values but mutate their contents.  A simple 'StablePtr a'
    -- won't work, since we'd have no way to write 'copyConfig'.
    type P a = StablePtr (IORef a)

    copyConfig :: P a -> P a -> IO ()
    copyConfig :: forall a. P a -> P a -> IO ()
    copyConfig P a
    src' P a
    dest' = do
      dest <- P a -> IO (IORef a)
    forall a. StablePtr a -> IO a
    deRefStablePtr P a
    dest'
      src <- deRefStablePtr src'
      readIORef src >>= writeIORef dest

    copyConstructConfig :: P a -> IO (P a)
    copyConstructConfig :: forall a. P a -> IO (P a)
    copyConstructConfig P a
    x = do
      conf <- P a -> IO a
    forall a. P a -> IO a
    deRefRead P a
    x
      newconf <- newIORef conf
      newStablePtr newconf

    destroyConfig :: P a -> IO ()
    destroyConfig :: forall a. P a -> IO ()
    destroyConfig P a
    p = do
      P a -> IO ()
    forall a. StablePtr a -> IO ()
    freeStablePtr P a
    p

    deRefRead :: P a -> IO a
    deRefRead :: forall a. P a -> IO a
    deRefRead P a
    p = P a -> IO (IORef a)
    forall a. StablePtr a -> IO a
    deRefStablePtr P a
    p IO (IORef a) -> (IORef a -> IO a) -> IO a
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= IORef a -> IO a
    forall a. IORef a -> IO a
    readIORef

    wrapEnergy :: (a -> Double) -> P a -> Double
    wrapEnergy :: forall a. (a -> Double) -> P a -> Double
    wrapEnergy a -> Double
    f P a
    p = IO Double -> Double
    forall a. IO a -> a
    unsafePerformIO (IO Double -> Double) -> IO Double -> Double
    forall a b. (a -> b) -> a -> b
    $ a -> Double
    f (a -> Double) -> IO a -> IO Double
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> P a -> IO a
    forall a. P a -> IO a
    deRefRead P a
    p

    wrapMetric :: (a -> a -> Double) -> P a -> P a -> Double
    wrapMetric :: forall a. (a -> a -> Double) -> P a -> P a -> Double
    wrapMetric a -> a -> Double
    f P a
    x P a
    y = IO Double -> Double
    forall a. IO a -> a
    unsafePerformIO (IO Double -> Double) -> IO Double -> Double
    forall a b. (a -> b) -> a -> b
    $ a -> a -> Double
    f (a -> a -> Double) -> IO a -> IO (a -> Double)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> P a -> IO a
    forall a. P a -> IO a
    deRefRead P a
    x IO (a -> Double) -> IO a -> IO Double
    forall a b. IO (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> P a -> IO a
    forall a. P a -> IO a
    deRefRead P a
    y

    wrapStep :: Int
             -> (Vector Double -> Double -> a -> a)
             -> GSLRNG
             -> P a
             -> Double
             -> IO ()
    wrapStep :: forall a.
    Int
    -> (Vector Double -> Double -> a -> a)
    -> GSLRNG
    -> P a
    -> Double
    -> IO ()
    wrapStep Int
    nrand Vector Double -> Double -> a -> a
    f (GSLRNG Ptr GSLRNG
    rng) P a
    confptr Double
    stepSize = do
      v <- Int -> (Int -> IO Double) -> IO (Vector Double)
    forall (m :: * -> *) a.
    (Monad m, Storable a) =>
    Int -> (Int -> m a) -> m (Vector a)
    generateM Int
    nrand (\Int
    _ -> Ptr GSLRNG -> IO Double
    gslRngUniform Ptr GSLRNG
    rng)
      conf <- deRefStablePtr confptr
      modifyIORef' conf $ f v stepSize

    wrapPrint :: (a -> String) -> P a -> IO ()
    wrapPrint :: forall a. (a -> String) -> P a -> IO ()
    wrapPrint a -> String
    pf P a
    ptr = P a -> IO a
    forall a. P a -> IO a
    deRefRead P a
    ptr IO a -> (a -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> IO ()
    putStr (String -> IO ()) -> (a -> String) -> a -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> String
    pf IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Handle -> IO ()
    hFlush Handle
    stdout

    foreign import ccall safe "wrapper"
      mkEnergyFun :: (P a -> Double) -> IO (FunPtr (P a -> Double))

    foreign import ccall safe "wrapper"
      mkMetricFun :: (P a -> P a -> Double) -> IO (FunPtr (P a -> P a -> Double))

    foreign import ccall safe "wrapper"
      mkStepFun :: (GSLRNG -> P a -> Double -> IO ())
                -> IO (FunPtr (GSLRNG -> P a -> Double -> IO ()))

    foreign import ccall safe "wrapper"
      mkCopyFun :: (P a -> P a -> IO ()) -> IO (FunPtr (P a -> P a -> IO ()))

    foreign import ccall safe "wrapper"
      mkCopyConstructorFun :: (P a -> IO (P a)) -> IO (FunPtr (P a -> IO (P a)))

    foreign import ccall safe "wrapper"
      mkDestructFun :: (P a -> IO ()) -> IO (FunPtr (P a -> IO ()))

    newtype GSLRNG = GSLRNG (Ptr GSLRNG)

    foreign import ccall safe "gsl_rng.h gsl_rng_uniform"
      gslRngUniform :: Ptr GSLRNG -> IO Double

    foreign import ccall safe "gsl-aux.h siman"
      siman :: CInt     -- ^ RNG seed (for repeatability)
            -> Ptr SimulatedAnnealingParams    -- ^ params
            -> P a                             -- ^ Configuration
            -> FunPtr (P a -> Double)          -- ^ Energy functional
            -> FunPtr (P a -> P a -> Double) -- ^ Metric definition
            -> FunPtr (GSLRNG -> P a -> Double -> IO ())  -- ^ Step evaluation
            -> FunPtr (P a -> P a -> IO ())  -- ^ Copy config
            -> FunPtr (P a -> IO (P a))      -- ^ Copy constructor for config
            -> FunPtr (P a -> IO ())           -- ^ Destructor for config
            -> FunPtr (P a -> IO ())           -- ^ Print function
            -> IO CInt

    -- |
    -- Calling
    --
    -- > simanSolve seed nrand params x0 e m step print
    --
    -- performs a simulated annealing search through a given space. So
    -- that any configuration type may be used, the space is specified by
    -- providing the functions @e@ (the energy functional) and @m@ (the
    -- metric definition).  @x0@ is the initial configuration of the
    -- system.  The simulated annealing steps are generated using the
    -- user-provided function @step@, which should randomly construct a
    -- new system configuration.
    --
    -- If 'Nothing' is passed instead of a printing function, no
    -- incremental output will be generated.  Otherwise, the GSL-formatted
    -- output, including the configuration description the user function
    -- generates, will be printed to stdout.
    --
    -- Each time the step function is called, it is supplied with a random
    -- vector containing @nrand@ 'Double' values, uniformly distributed in
    -- @[0, 1)@.  It should use these values to generate its new
    -- configuration.
    simanSolve :: Int   -- ^ Seed for the random number generator
               -> Int   -- ^ @nrand@, the number of random 'Double's the
                        -- step function requires
               -> SimulatedAnnealingParams  -- ^ Parameters to configure the solver
               -> a                    -- ^ Initial configuration @x0@
               -> (a -> Double)        -- ^ Energy functional @e@
               -> (a -> a -> Double)   -- ^ Metric definition @m@
               -> (Vector Double -> Double -> a -> a)  -- ^ Stepping function @step@
               -> Maybe (a -> String)  -- ^ Optional printing function
               -> a          -- ^ Best configuration the solver has found
    simanSolve :: forall a.
    Int
    -> Int
    -> SimulatedAnnealingParams
    -> a
    -> (a -> Double)
    -> (a -> a -> Double)
    -> (Vector Double -> Double -> a -> a)
    -> Maybe (a -> String)
    -> a
    simanSolve Int
    seed Int
    nrand SimulatedAnnealingParams
    params a
    conf a -> Double
    e a -> a -> Double
    m Vector Double -> Double -> a -> a
    step Maybe (a -> String)
    printfun =
      IO a -> a
    forall a. IO a -> a
    unsafePerformIO (IO a -> a) -> IO a -> a
    forall a b. (a -> b) -> a -> b
    $ SimulatedAnnealingParams
    -> (Ptr SimulatedAnnealingParams -> IO a) -> IO a
    forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
    with SimulatedAnnealingParams
    params ((Ptr SimulatedAnnealingParams -> IO a) -> IO a)
    -> (Ptr SimulatedAnnealingParams -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr SimulatedAnnealingParams
    paramptr -> do
        ewrap <- (P a -> Double) -> IO (FunPtr (P a -> Double))
    forall a. (P a -> Double) -> IO (FunPtr (P a -> Double))
    mkEnergyFun ((P a -> Double) -> IO (FunPtr (P a -> Double)))
    -> (P a -> Double) -> IO (FunPtr (P a -> Double))
    forall a b. (a -> b) -> a -> b
    $ (a -> Double) -> P a -> Double
    forall a. (a -> Double) -> P a -> Double
    wrapEnergy a -> Double
    e
        mwrap <- mkMetricFun $ wrapMetric m
        stepwrap <- mkStepFun $ wrapStep nrand step
        confptr <- newIORef conf >>= newStablePtr
        cpwrap <- mkCopyFun copyConfig
        ccwrap <- mkCopyConstructorFun copyConstructConfig
        dwrap <- mkDestructFun destroyConfig
        pwrap <- case printfun of
          Maybe (a -> String)
    Nothing -> FunPtr (P a -> IO ()) -> IO (FunPtr (P a -> IO ()))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FunPtr (P a -> IO ())
    forall a. FunPtr a
    nullFunPtr
          Just a -> String
    pf -> (P a -> IO ()) -> IO (FunPtr (P a -> IO ()))
    forall a. (P a -> IO ()) -> IO (FunPtr (P a -> IO ()))
    mkDestructFun ((P a -> IO ()) -> IO (FunPtr (P a -> IO ())))
    -> (P a -> IO ()) -> IO (FunPtr (P a -> IO ()))
    forall a b. (a -> b) -> a -> b
    $ (a -> String) -> P a -> IO ()
    forall a. (a -> String) -> P a -> IO ()
    wrapPrint a -> String
    pf
        siman (fromIntegral seed)
          paramptr confptr
          ewrap mwrap stepwrap cpwrap ccwrap dwrap pwrap // check "siman"
        result <- deRefRead confptr
        freeStablePtr confptr
        return result