{-# LINE 1 "Numeric/LBFGS/Raw.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface, GeneralizedNewtypeDeriving #-}
{-# LINE 2 "Numeric/LBFGS/Raw.hsc" #-}


{-# LINE 4 "Numeric/LBFGS/Raw.hsc" #-}

{-# LINE 5 "Numeric/LBFGS/Raw.hsc" #-}

module Numeric.LBFGS.Raw (CLineSearchAlgorithm, CLBFGSParameter(..),
                          CEvaluateFun, CProgressFun,
                          defaultCParam, c_lbfgs, c_lbfgs_malloc,
                          c_lbfgs_free, c_lbfgs_evaluate_t_wrap,
                          c_lbfgs_progress_t_wrap,

                          defaultLineSearch, moreThuente, backtrackingArmijo,
                          backtracking, backtrackingWolfe,
                          backtrackingStrongWolfe,

                          CLBFGSResult(..),
                          lbfgsSuccess,
                          lbfgsConvergence,
                          lbfgsStop,
                          lbfgsAlreadyMinimized,
                          lbfgserrUnknownerror,
                          lbfgserrLogicerror,
                          lbfgserrOutofmemory,
                          lbfgserrCanceled,
                          lbfgserrInvalidN,
                          lbfgserrInvalidNSse,
                          lbfgserrInvalidXSse,
                          lbfgserrInvalidEpsilon,
                          lbfgserrInvalidTestperiod,
                          lbfgserrInvalidDelta,
                          lbfgserrInvalidLinesearch,
                          lbfgserrInvalidMinstep,
                          lbfgserrInvalidMaxstep,
                          lbfgserrInvalidFtol,
                          lbfgserrInvalidWolfe,
                          lbfgserrInvalidGtol,
                          lbfgserrInvalidXtol,
                          lbfgserrInvalidMaxlinesearch,
                          lbfgserrInvalidOrthantwise,
                          lbfgserrInvalidOrthantwiseStart,
                          lbfgserrInvalidOrthantwiseEnd,
                          lbfgserrOutofinterval,
                          lbfgserrIncorrectTminmax,
                          lbfgserrRoundingError,
                          lbfgserrMinimumstep,
                          lbfgserrMaximumstep,
                          lbfgserrMaximumlinesearch,
                          lbfgserrMaximumiteration,
                          lbfgserrWidthtoosmall,
                          lbfgserrInvalidparameters,
                          lbfgserrIncreasegradient

) where

import Foreign.Storable (Storable(..))
import Foreign.C.Types (CDouble(..), CInt(..))
import Foreign.Ptr (FunPtr, Ptr)
import Foreign.StablePtr (StablePtr)

newtype CLineSearchAlgorithm =
    CLineSearchAlgorithm { unCLineSearchAlgorithm :: CInt }
    deriving (Storable, Show)

defaultLineSearch  :: CLineSearchAlgorithm
defaultLineSearch  = CLineSearchAlgorithm 0
moreThuente  :: CLineSearchAlgorithm
moreThuente  = CLineSearchAlgorithm 0
backtrackingArmijo  :: CLineSearchAlgorithm
backtrackingArmijo  = CLineSearchAlgorithm 1
backtracking  :: CLineSearchAlgorithm
backtracking  = CLineSearchAlgorithm 2
backtrackingWolfe  :: CLineSearchAlgorithm
backtrackingWolfe  = CLineSearchAlgorithm 2
backtrackingStrongWolfe  :: CLineSearchAlgorithm
backtrackingStrongWolfe  = CLineSearchAlgorithm 3

{-# LINE 72 "Numeric/LBFGS/Raw.hsc" #-}

newtype CLBFGSResult =
    CLBFGSResult { unCLBFGSResult :: CInt }
    deriving (Eq, Show)

lbfgsSuccess :: CLBFGSResult
lbfgsSuccess = CLBFGSResult 0
lbfgsConvergence :: CLBFGSResult
lbfgsConvergence = CLBFGSResult 0
lbfgsStop :: CLBFGSResult
lbfgsStop = CLBFGSResult 1
lbfgsAlreadyMinimized :: CLBFGSResult
lbfgsAlreadyMinimized = CLBFGSResult 2
lbfgserrUnknownerror :: CLBFGSResult
lbfgserrUnknownerror = CLBFGSResult (-1024)
lbfgserrLogicerror :: CLBFGSResult
lbfgserrLogicerror = CLBFGSResult (-1023)
lbfgserrOutofmemory :: CLBFGSResult
lbfgserrOutofmemory = CLBFGSResult (-1022)
lbfgserrCanceled :: CLBFGSResult
lbfgserrCanceled = CLBFGSResult (-1021)
lbfgserrInvalidN :: CLBFGSResult
lbfgserrInvalidN = CLBFGSResult (-1020)
lbfgserrInvalidNSse :: CLBFGSResult
lbfgserrInvalidNSse = CLBFGSResult (-1019)
lbfgserrInvalidXSse :: CLBFGSResult
lbfgserrInvalidXSse = CLBFGSResult (-1018)
lbfgserrInvalidEpsilon :: CLBFGSResult
lbfgserrInvalidEpsilon = CLBFGSResult (-1017)
lbfgserrInvalidTestperiod :: CLBFGSResult
lbfgserrInvalidTestperiod = CLBFGSResult (-1016)
lbfgserrInvalidDelta :: CLBFGSResult
lbfgserrInvalidDelta = CLBFGSResult (-1015)
lbfgserrInvalidLinesearch :: CLBFGSResult
lbfgserrInvalidLinesearch = CLBFGSResult (-1014)
lbfgserrInvalidMinstep :: CLBFGSResult
lbfgserrInvalidMinstep = CLBFGSResult (-1013)
lbfgserrInvalidMaxstep :: CLBFGSResult
lbfgserrInvalidMaxstep = CLBFGSResult (-1012)
lbfgserrInvalidFtol :: CLBFGSResult
lbfgserrInvalidFtol = CLBFGSResult (-1011)
lbfgserrInvalidWolfe :: CLBFGSResult
lbfgserrInvalidWolfe = CLBFGSResult (-1010)
lbfgserrInvalidGtol :: CLBFGSResult
lbfgserrInvalidGtol = CLBFGSResult (-1009)
lbfgserrInvalidXtol :: CLBFGSResult
lbfgserrInvalidXtol = CLBFGSResult (-1008)
lbfgserrInvalidMaxlinesearch :: CLBFGSResult
lbfgserrInvalidMaxlinesearch = CLBFGSResult (-1007)
lbfgserrInvalidOrthantwise :: CLBFGSResult
lbfgserrInvalidOrthantwise = CLBFGSResult (-1006)
lbfgserrInvalidOrthantwiseStart :: CLBFGSResult
lbfgserrInvalidOrthantwiseStart = CLBFGSResult (-1005)
lbfgserrInvalidOrthantwiseEnd :: CLBFGSResult
lbfgserrInvalidOrthantwiseEnd = CLBFGSResult (-1004)
lbfgserrOutofinterval :: CLBFGSResult
lbfgserrOutofinterval = CLBFGSResult (-1003)
lbfgserrIncorrectTminmax :: CLBFGSResult
lbfgserrIncorrectTminmax = CLBFGSResult (-1002)
lbfgserrRoundingError :: CLBFGSResult
lbfgserrRoundingError = CLBFGSResult (-1001)
lbfgserrMinimumstep :: CLBFGSResult
lbfgserrMinimumstep = CLBFGSResult (-1000)
lbfgserrMaximumstep :: CLBFGSResult
lbfgserrMaximumstep = CLBFGSResult (-999)
lbfgserrMaximumlinesearch :: CLBFGSResult
lbfgserrMaximumlinesearch = CLBFGSResult (-998)
lbfgserrMaximumiteration :: CLBFGSResult
lbfgserrMaximumiteration = CLBFGSResult (-997)
lbfgserrWidthtoosmall :: CLBFGSResult
lbfgserrWidthtoosmall = CLBFGSResult (-996)
lbfgserrInvalidparameters :: CLBFGSResult
lbfgserrInvalidparameters = CLBFGSResult (-995)
lbfgserrIncreasegradient  :: CLBFGSResult
lbfgserrIncreasegradient  = CLBFGSResult (-994)

{-# LINE 95 "Numeric/LBFGS/Raw.hsc" #-}

data CLBFGSParameter = CLBFGSParameter {
      m :: CInt,
      epsilon :: CDouble,
      past :: CInt,
      delta :: CDouble,
      max_iterations :: CInt,
      linesearch :: CLineSearchAlgorithm,
      max_linesearch :: CInt,
      min_step :: CDouble,
      max_step :: CDouble,
      ftol :: CDouble,
      wolfe :: CDouble,
      gtol :: CDouble,
      xtol :: CDouble,
      orthantwise_c :: CDouble,
      orthantwise_start :: CInt,
      orthantwise_end :: CInt
} deriving Show

defaultCParam :: CLBFGSParameter
defaultCParam = CLBFGSParameter 6 1e-5 0 1e-5 0 defaultLineSearch 40 1e-20
                1e20 1e-4 0.9 0.9 1.0e-16 0.0 0 (-1)

instance Storable CLBFGSParameter where
    sizeOf _ = (112)
{-# LINE 121 "Numeric/LBFGS/Raw.hsc" #-}
    alignment _ = 8
{-# LINE 122 "Numeric/LBFGS/Raw.hsc" #-}
    peek ptr = do
      m                 <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr
{-# LINE 124 "Numeric/LBFGS/Raw.hsc" #-}
      epsilon           <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) ptr
{-# LINE 125 "Numeric/LBFGS/Raw.hsc" #-}
      past              <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) ptr
{-# LINE 126 "Numeric/LBFGS/Raw.hsc" #-}
      delta             <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) ptr
{-# LINE 127 "Numeric/LBFGS/Raw.hsc" #-}
      max_iterations    <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) ptr
{-# LINE 128 "Numeric/LBFGS/Raw.hsc" #-}
      linesearch        <- ((\hsc_ptr -> peekByteOff hsc_ptr 36)) ptr
{-# LINE 129 "Numeric/LBFGS/Raw.hsc" #-}
      max_linesearch    <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) ptr
{-# LINE 130 "Numeric/LBFGS/Raw.hsc" #-}
      min_step          <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) ptr
{-# LINE 131 "Numeric/LBFGS/Raw.hsc" #-}
      max_step          <- ((\hsc_ptr -> peekByteOff hsc_ptr 56)) ptr
{-# LINE 132 "Numeric/LBFGS/Raw.hsc" #-}
      ftol              <- ((\hsc_ptr -> peekByteOff hsc_ptr 64)) ptr
{-# LINE 133 "Numeric/LBFGS/Raw.hsc" #-}
      wolfe             <- ((\hsc_ptr -> peekByteOff hsc_ptr 72)) ptr
{-# LINE 134 "Numeric/LBFGS/Raw.hsc" #-}
      gtol              <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) ptr
{-# LINE 135 "Numeric/LBFGS/Raw.hsc" #-}
      xtol              <- ((\hsc_ptr -> peekByteOff hsc_ptr 88)) ptr
{-# LINE 136 "Numeric/LBFGS/Raw.hsc" #-}
      orthantwise_c     <- ((\hsc_ptr -> peekByteOff hsc_ptr 96)) ptr
{-# LINE 137 "Numeric/LBFGS/Raw.hsc" #-}
      orthantwise_start <- ((\hsc_ptr -> peekByteOff hsc_ptr 104)) ptr
{-# LINE 138 "Numeric/LBFGS/Raw.hsc" #-}
      orthantwise_end   <- ((\hsc_ptr -> peekByteOff hsc_ptr 108)) ptr
{-# LINE 139 "Numeric/LBFGS/Raw.hsc" #-}
      return $ CLBFGSParameter m epsilon past delta max_iterations
             linesearch max_linesearch min_step max_step
             ftol wolfe gtol xtol orthantwise_c
             orthantwise_start orthantwise_end
    poke ptr (CLBFGSParameter m epsilon past delta max_iterations
                              linesearch max_linesearch min_step max_step
                              ftol wolfe gtol xtol orthantwise_c
                              orthantwise_start orthantwise_end
             ) = do
      ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr m
{-# LINE 149 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) ptr epsilon
{-# LINE 150 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) ptr past
{-# LINE 151 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 24)) ptr delta
{-# LINE 152 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 32)) ptr max_iterations
{-# LINE 153 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 36)) ptr linesearch
{-# LINE 154 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 40)) ptr max_linesearch
{-# LINE 155 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 48)) ptr min_step
{-# LINE 156 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 56)) ptr max_step
{-# LINE 157 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 64)) ptr ftol
{-# LINE 158 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 72)) ptr wolfe
{-# LINE 159 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 80)) ptr gtol
{-# LINE 160 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 88)) ptr xtol
{-# LINE 161 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 96)) ptr orthantwise_c
{-# LINE 162 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 104)) ptr orthantwise_start
{-# LINE 163 "Numeric/LBFGS/Raw.hsc" #-}
      ((\hsc_ptr -> pokeByteOff hsc_ptr 108)) ptr orthantwise_end
{-# LINE 164 "Numeric/LBFGS/Raw.hsc" #-}

type CEvaluateFun a = (StablePtr a -> Ptr CDouble -> Ptr CDouble -> CInt ->
                      CDouble -> IO (CDouble))

type CProgressFun a = (StablePtr a -> Ptr CDouble -> Ptr CDouble -> CDouble ->
                      CDouble -> CDouble -> CDouble -> CInt -> CInt ->
                      CInt -> IO (CInt))

foreign import ccall "wrapper"
        c_lbfgs_evaluate_t_wrap :: CEvaluateFun a -> IO (FunPtr (CEvaluateFun a))

foreign import ccall "wrapper"
        c_lbfgs_progress_t_wrap :: CProgressFun a -> IO (FunPtr (CProgressFun a))

foreign import ccall safe "lbfgs.h lbfgs" c_lbfgs ::
    CInt -> Ptr CDouble -> Ptr CDouble -> FunPtr (CEvaluateFun a) ->
    FunPtr (CProgressFun a) -> StablePtr a -> Ptr (CLBFGSParameter) -> IO (CInt)

foreign import ccall unsafe "lbfgs.h lbfgs_malloc" c_lbfgs_malloc ::
    CInt -> IO (Ptr CDouble)

foreign import ccall unsafe "lbfgs.h lbfgs_free" c_lbfgs_free ::
    Ptr CDouble -> IO ()