never executed always true always false
    1 -- GENERATED by C->Haskell Compiler, version 0.28.8 Switcheroo, 25 November 2017 (Haskell)
    2 -- Edit the ORIGNAL .chs file instead!
    3 
    4 
    5 -- |Monte Carlo path generation ('pathGenerator'\/'sobolPathGenerator'\/'next'\/'asset') plus
    6 -- 'lsmRegress', a standalone Longstaff-Schwartz early-exercise regression primitive.
    7 --
    8 -- === Custom early exercise with a Haskell payoff
    9 --
   10 -- 'lsmRegress' lets a Haskell-defined payoff drive early exercise, something no bound pricing
   11 -- engine offers: every early-exercise engine in "QuantLib.PricingEngine" (e.g.
   12 -- @mcAmericanEngine@) computes its payoff entirely on the C++ side against a bound @Payoff@.
   13 -- 'lsmRegress' is pure regression -- it never sees a payoff at all, so it works for any
   14 -- underlying-state-dependent early-exercise payoff, not just a vanilla put\/call. The pattern,
   15 -- worked in full in @test\/example\/QuantLib\/Example\/AmericanLSM.hs@:
   16 --
   17 -- 1. Draw two path sets with 'pathGenerator': a /calibration/ set used only to fit each date's
   18 --    regression, and a separate /pricing/ set evaluated against the frozen fit. Splitting the
   19 --    sets avoids the in-sample bias a single-pass fit-and-price would have (the same reason
   20 --    @mcAmericanEngine@ exposes its own @nCalibrationSamples@ parameter). Use a fixed nonzero
   21 --    seed for each -- seed @0@ means \"seed from entropy\" for 'PseudoRandom'.
   22 -- 2. Read out the state at every exercise date, across all paths, with 'asset' (or 'assetAt'),
   23 --    and transpose ('Data.List.transpose') into one state list per exercise date.
   24 -- 3. Walk exercise dates *strictly backward*. At each date:
   25 --
   26 --     * discount both the calibration and pricing cashflow vectors by the one-step discount
   27 --       factor (@discount(t[i+1]) \/ discount(t[i])@ from the underlying yield curve);
   28 --     * compute the Haskell payoff at this date for every path in both sets;
   29 --     * restrict the regression's fit inputs to *in-the-money calibration paths only*
   30 --       (@fitStates@\/@fitTargets@ below);
   31 --     * call 'lsmRegress' twice against that one fit -- once evaluating at the calibration
   32 --       states (to keep the backward recursion's own targets self-consistent), once at the
   33 --       pricing states (the actual out-of-sample continuation-value estimate);
   34 --     * exercise wherever @payoff > continuationValue@ (@max(exercise, continuation)@), on each
   35 --       path set independently.
   36 --
   37 -- 4. The pricing set's cashflows, discounted all the way back and averaged, are the estimated
   38 --    price. Never evaluate the fit on the calibration set's own state for the reported price --
   39 --    that reintroduces the in-sample bias step 1 split the paths to avoid.
   40 --
   41 -- A rough sketch (see the full example for discounting, ITM filtering, and the backward
   42 -- recursion itself):
   43 --
   44 -- > step df calibS priceS calibCF priceCF = do
   45 -- >   let calibTargets = map (* df) calibCF  -- discount to this date
   46 -- >       (fitStates, fitTargets) = -- ITM calibration paths only
   47 -- >         unzip $ filter (inTheMoney . fst) $ zip calibS calibTargets
   48 -- >   contCalib <- lsmRegress Monomial order fitStates fitTargets calibS
   49 -- >   contPrice <- lsmRegress Monomial order fitStates fitTargets priceS
   50 -- >   -- exercise wherever payoff > continuation, on each path set
   51 -- >   ...
   52 --
   53 -- Validated in the example against both @mcAmericanEngine@ pricing the equivalent bound vanilla
   54 -- option (same process\/grid\/seed) and the published Longstaff-Schwartz (2001) reference value
   55 -- for the same benchmark fixture.
   56 --
   57 -- The same pattern extends to a Haskell-defined /basket/ payoff (several correlated underlyings)
   58 -- via 'lsmRegressMulti' \/ 'lsmBasisSize' in place of 'lsmRegress': read each exercise date's state
   59 -- for every underlying (still with 'asset'\/'assetAt', once per underlying) into a 'Matrix' of one
   60 -- row per path, and guard the ITM-fit-size check with 'lsmBasisSize' instead of the basis order --
   61 -- the multi-asset basis has combinatorially many more terms than the scalar case.
   62 --
   63 -- To keep a fit and evaluate it later, split the combined call: 'lsmFit' returns the basis
   64 -- coefficients and 'lsmEvaluate' applies them to new states. Both pick the basis by the state
   65 -- matrix's column count -- the scalar basis of 'lsmRegress' at one column, the basis of
   66 -- 'lsmRegressMulti' at several -- and share the combined calls' native code, so within one build
   67 -- fitting then evaluating gives the combined call's values bit for bit. Across builds the bits are
   68 -- not promised: 'lsmEvaluatorIdentity' names the basis revision, QuantLib version, compiler and
   69 -- architecture, so a stored fit can be refused elsewhere. It is necessary, not sufficient: a
   70 -- library rebuilt under the same version string keeps it.
   71 --
   72 -- Both Chebyshev types are QuantLib's weighted bases, undefined outside (-1, 1): with a state there
   73 -- the least-squares solve of every regression above does not return. Scale the states into that
   74 -- interval or choose another 'PolynomialType'.
   75 --
   76 -- @test\/example\/QuantLib\/Example\/HaskellLSM.hs@ benchmarks 'lsmRegress' against the same
   77 -- backward induction with the per-date regression reimplemented from scratch in plain Haskell
   78 -- (QuantLib used only for path generation) -- a worked illustration of why this module exposes
   79 -- the regression as a batched primitive instead of leaving callers to reinvent it.
   80 --
   81 -- === Finite-difference PDE solving
   82 --
   83 -- This module also binds a full-grid finite-difference (FDM) driver, built up across two related
   84 -- issues (custom step-condition\/operator hooks, then custom inner-value calculators) and spread
   85 -- across several functions with no single overview until now. Worked in full in
   86 -- @test\/example\/QuantLib\/Example\/Fdm.hs@ -- every snippet below is a trimmed extract from that
   87 -- file; read it end to end for the full picture (discounting, fixtures, imports).
   88 --
   89 -- In one sentence, for anyone new to FDM pricing: instead of an integral (Monte Carlo) or a
   90 -- closed-form formula (an @analytic*Engine@), you discretize the underlying's state space (e.g.
   91 -- log-spot) into a grid of points, put the option's payoff on the grid at maturity, and step it
   92 -- /backward/ to today, solving a small local linear system at each timestep. Reach for it when you
   93 -- need American\/Bermudan-style early exercise (a plain Monte Carlo run can't do backward induction
   94 -- the way a grid can) or a process\/payoff with no closed-form price. If a bound @analytic*Engine@
   95 -- or @mc*Engine@ already covers your case (see "QuantLib.PricingEngine"), prefer that instead --
   96 -- it's simpler, and this module's own examples validate their FDM results against exactly those
   97 -- engines.
   98 --
   99 -- ==== Walkthrough: which function do I actually want?
  100 --
  101 -- Start here rather than at the reference list below -- picking the right entry point up front
  102 -- avoids reading five functions' haddock only to discover a sixth was the one you needed.
  103 --
  104 -- [@\"I have a grid already, just roll it back\"@] 'fdmRollback'. Supply the grid as a plain
  105 --   @[Double]@ (one value per state, at maturity) plus three Haskell closures describing the PDE
  106 --   operator, and get the same grid rolled back to today -- no mesher, no
  107 --   'FdmInnerValueCalculator', the simplest possible entry point:
  108 --
  109 --   > let grid0 = map (\x -> max (exp x - strike) 0) xs   -- payoff at maturity, one value per grid point
  110 --   > fdmEuro <- fdmRollback 1 applyFn applyDirFn solveFn Nothing [] Douglas grid0 tMat 0 nSteps 0
  111 --
  112 -- [@\"...and I need early exercise\"@] the same 'fdmRollback' call, plus a /step condition/: a
  113 --   @t -> [Double] -> [Double]@ closure called once per outer timestep with the whole current grid,
  114 --   returning it clamped to whatever the early-exercise rule requires:
  115 --
  116 --   > let stepCond _t u = zipWith max u grid0   -- American: value can never fall below intrinsic
  117 --   > fdmAmerican <- fdmRollback 1 applyFn applyDirFn solveFn (Just stepCond) stepTimes Douglas grid0 tMat 0 nSteps 0
  118 --
  119 -- [@\"I'd rather not hand-build the initial grid myself\"@] 'fdmSolve' -- 'fdmRollback''s sibling.
  120 --   Same operator\/step-condition\/scheme machinery, but the initial condition comes from an
  121 --   'FdmMesher' plus an 'FdmInnerValueCalculator' evaluated at each node, instead of a grid you
  122 --   assembled by hand. Worth it once the mesher is doing real work (e.g. concentrating points near
  123 --   a strike or barrier) rather than just wrapping a list you already had:
  124 --
  125 --   > mesh1d <- predefined1dMesher xs
  126 --   > mesher <- fdmMesherComposite [mesh1d]
  127 --   > let ivFn _t loc = case loc of [x] -> intrinsicAt x; _ -> error "expected a 1D location"
  128 --   > withCustomFdmInnerValueCalculator mesher ivFn ivFn $ \calc ->
  129 --   >   fdmSolve mesher calc 1 applyFn applyDirFn solveFn Nothing [] Douglas tMat 0 nSteps 0
  130 --
  131 -- [@\"my payoff is a standard vanilla\/log payoff, I don't want a per-node callback\"@] skip
  132 --   'withCustomFdmInnerValueCalculator' and reach for one of the /native/ calculators instead --
  133 --   QuantLib's own built-in 'FdmInnerValueCalculator' subclasses, bound directly so pricing a plain
  134 --   payoff doesn't pay a Haskell round-trip per grid node:
  135 --
  136 --   > logCalc <- fdmLogInnerValue payoff mesher 0        -- striked payoff on a log-spot grid
  137 --   > fdmLogEuro <- fdmSolve mesher logCalc 1 applyFn applyDirFn solveFn Nothing [] Douglas tMat 0 nSteps 0
  138 --
  139 --   'fdmZeroInnerValue' (always 0), 'fdmCellAveragingInnerValue'\/'withCustomCellAveragingInnerValue'
  140 --   (identity or custom @gridMapping@), and 'fdmLogInnerValue' (@gridMapping = exp@, the common case
  141 --   on a log-spot grid) round out the set -- see the reference entries below for the exact
  142 --   cell-averaging-vs-point-evaluation contract each one has. Reach for
  143 --   'withCustomFdmInnerValueCalculator' only once none of these fit your payoff shape.
  144 --
  145 -- [@\"my payoff depends on more than one underlying\"@] build one 'Fdm1dMesher' per underlying and
  146 --   combine them with 'fdmMesherComposite'; 'fdmLogBasketInnerValue' takes a basket payoff (e.g.
  147 --   @Max@, see "QuantLib.Instrument.Option") evaluated across all dimensions at once:
  148 --
  149 --   > basketMesher <- fdmMesherComposite [mesh1d, mesh1d]   -- two correlated log-spot dimensions
  150 --   > basketCalc <- fdmLogBasketInnerValue (Max payoff) basketMesher
  151 --   > val <- fdmAvgInnerValue basketCalc basketMesher [i, j] tMat   -- inspect one node directly
  152 --
  153 -- [@\"I want to price a swap\/swaption under a calibrated short-rate model\"@] the most specialized
  154 --   entry points here: 'fdmAffineG2ModelSwapInnerValue'\/'fdmAffineHullWhiteModelSwapInnerValue'
  155 --   drive the same calculator @fdG2SwaptionEngine@\/@fdHullWhiteSwaptionEngine@ already use
  156 --   internally. Reach for these directly only when composing your own custom FDM pipeline around
  157 --   this calculator; if a plain Bermudan-swaption NPV is all you need, prefer those two
  158 --   already-bound black-box engines from "QuantLib.PricingEngine" instead.
  159 --
  160 -- [@\"I just want one node's value, no PDE solve\"@] 'fdmInnerValue'\/'fdmAvgInnerValue' evaluate
  161 --   any bound calculator -- custom or native -- at a single mesher node directly, without
  162 --   assembling a whole 'fdmSolve'. Handy as a sanity check while developing (as @Fdm.hs@'s own
  163 --   tests do throughout), or whenever a single point's intrinsic value is all you actually need.
  164 --
  165 -- ==== Technical reference
  166 --
  167 -- The terse version of the above, for a reader who already knows the vocabulary and wants the
  168 -- exact contract rather than the walkthrough's prose.
  169 --
  170 -- [@Rolling a grid back@] 'fdmRollback' takes a precomputed initial grid (a plain @[Double]@) and
  171 --   rolls it back through time via three Haskell-defined operator callbacks
  172 --   (@withFdmApply@ et al. below) plus an optional step condition (e.g.
  173 --   American\/Bermudan early exercise). These callbacks cross the language boundary once per outer
  174 --   timestep, over the /whole/ grid. 'fdmSolve' is the sibling that instead derives its own
  175 --   initial grid from a mesher and
  176 --   an 'FdmInnerValueCalculator' (below), reusing the same operator\/step-condition machinery.
  177 --
  178 -- [@Building a grid@] 'Fdm1dMesher's ('predefined1dMesher', 'uniform1dMesher',
  179 --   'concentrating1dMesher', 'fdmBlackScholesMesher', and the other process-specific meshers) each
  180 --   describe one PDE dimension; 'fdmMesherComposite' combines one or more into the multi-dimensional
  181 --   'FdmMesher' 'fdmSolve' and 'FdmInnerValueCalculator' operate over. 'fdmMesherLocations' reads a
  182 --   dimension's real-valued node locations back out, e.g. to map a flat result array back to
  183 --   coordinates. 'gluedMesher' splices two 'Fdm1dMesher's end to end (e.g. a fine mesh near a
  184 --   barrier glued to a coarse one further out) -- their ranges must already be ordered and
  185 --   non-overlapping, and a shared boundary point is deduplicated automatically.
  186 --
  187 -- [@Custom inner values, fully general@] 'withCustomFdmInnerValueCalculator' wraps a Haskell
  188 --   @t -> location -> value@ pair of functions as an 'FdmInnerValueCalculator'. Unlike every
  189 --   callback above, this one crosses the language boundary once /per grid node/ -- there is no
  190 --   batched shape for it anywhere in QuantLib or QuantLib-SWIG, so the real per-call cost is
  191 --   accepted, matching QuantLib-SWIG's own @FdmInnerValueCalculatorDelegate@ precedent.
  192 --   The calculator and native dependents retain both callbacks after the continuation returns;
  193 --   callback exceptions are rethrown by the enclosing Haskell call.
  194 --
  195 -- [@Custom inner values, native@] QuantLib's own concrete 'FdmInnerValueCalculator' subclasses are
  196 --   bound directly, for the common cases that don't need a per-node Haskell callback at all:
  197 --   'fdmZeroInnerValue' (always 0), 'fdmCellAveragingInnerValue'\/'fdmLogInnerValue' (a payoff
  198 --   cell-averaged -- Simpson-integrated across each grid cell, not just evaluated at its center --
  199 --   with an identity or @exp@ value mapping respectively), and 'fdmLogBasketInnerValue' (the
  200 --   multi-asset counterpart, one @exp@ mapping per dimension). These retain their payoff,
  201 --   including any Haskell callback it owns. There is also
  202 --   'withCustomCellAveragingInnerValue', the one native constructor that /does/ take an explicit
  203 --   @gridMapping@ callback, retained by the native calculator. 'fdmAffineG2ModelSwapInnerValue'\/'fdmAffineHullWhiteModelSwapInnerValue' price a swap
  204 --   under a calibrated 'QuantLib.Model.G2'\/'QuantLib.Model.HullWhite' model directly -- the same
  205 --   calculator @fdG2SwaptionEngine@\/@fdHullWhiteSwaptionEngine@ use internally.
  206 --
  207 -- [@Inspecting a calculator directly@] 'fdmInnerValue'\/'fdmAvgInnerValue' evaluate any bound
  208 --   calculator (custom or native) at a single mesher node, without assembling a whole 'fdmSolve' --
  209 --   useful for a targeted self-consistency check, as @Fdm.hs@'s own tests do throughout.
  210 --
  211 -- === What's deliberately not bound: operators, schemes, boundary conditions
  212 --
  213 -- QuantLib-SWIG also exposes QuantLib's concrete 'FdmLinearOpComposite' subclasses (@FdmBlackScholesOp@,
  214 -- @FdmHestonOp@, @FdmG2Op@, ...), its scheme objects (@DouglasScheme@, @CraigSneydScheme@,
  215 -- @HundsdorferScheme@, ...), and its @FdmBoundaryCondition@ family as real C++ objects. hasquant does
  216 -- not mirror these, and won't by default -- it's a design boundary already crossed once, not a gap.
  217 --
  218 -- 'fdmRollback'\/'fdmSolve' take the operator, the implicit-solve step, and the scheme all as Haskell
  219 -- closures instead (@applyFn@\/@applyDirFn@\/@solveFn@ above). That's the same "coarsen the
  220 -- language-boundary crossing" call already made for step conditions: bind the reusable numerical
  221 -- /primitive/ (rollback through a fixed timestep, of an arbitrary tridiagonal\/multi-dimensional
  222 -- operator) and let Haskell drive it, rather than bind every concrete operator\/scheme QuantLib ships
  223 -- as its own object. @test\/example\/QuantLib\/Example\/Fdm.hs@'s hand-rolled 'operatorBands'\/'applyOp'
  224 -- /is/ the replacement for @FdmBlackScholesOp@ + @DouglasScheme@, not a stand-in waiting for those to
  225 -- get bound -- pricing a new payoff\/process combination here means writing its operator once in
  226 -- Haskell, not calling into fifteen QuantLib operator classes one by one.
  227 --
  228 -- Binding the operator\/scheme family as objects would add a second, redundant way to drive the same
  229 -- 'fdmSolve'\/'fdmRollback' backbone, without extending what's actually solvable -- anything a bound
  230 -- @FdmXxxOp@ could do, a Haskell @applyFn@ already can. Revisit only if a concrete need shows up that
  231 -- the callback shape genuinely can't express (none has, so far).
  232 module QuantLib.Method
  233   (
  234     -- * Types
  235     -- ** Path and random sequences
  236     PathGenerator
  237   , SamplePath
  238   , GaussianRsg
  239 
  240     -- ** Finite differences
  241   , Fdm1dMesher
  242   , FdmMesher
  243   , FdmInnerValueCalculator
  244 
  245     -- * Constructors
  246     -- ** Path generation
  247   , pathGenerator
  248   , sobolPathGenerator
  249     -- ** Random sequence generation
  250   , gaussianRsg
  251   , sobolGaussianRsg
  252     -- ** Finite-difference meshers
  253   , predefined1dMesher
  254   , uniform1dMesher
  255   , concentrating1dMesher
  256   , concentrating1dMesherMulti
  257   , gluedMesher
  258   , fdmBlackScholesMesher
  259   , fdmCev1dMesher
  260   , exponentialJump1dMesher
  261   , fdmSimpleProcess1dMesher
  262   , fdmHestonVarianceMesher
  263   , fdmHestonLocalVolatilityVarianceMesher
  264   , fdmMesherComposite
  265     -- ** Finite-difference inner-value calculators
  266   , withCustomFdmInnerValueCalculator
  267   , fdmZeroInnerValue
  268   , fdmCellAveragingInnerValue
  269   , withCustomCellAveragingInnerValue
  270   , fdmLogInnerValue
  271   , fdmLogBasketInnerValue
  272   , fdmAffineG2ModelSwapInnerValue
  273   , fdmAffineHullWhiteModelSwapInnerValue
  274 
  275     -- * Inspectors
  276     -- ** Path and random sequences
  277   , next
  278   , antithetic
  279   , nextSequence
  280     -- ** Longstaff-Schwartz regression
  281   , lsmRegress
  282   , lsmBasisSize
  283   , lsmRegressMulti
  284   , lsmFit
  285   , lsmEvaluate
  286   , lsmEvaluatorIdentity
  287     -- ** Finite differences
  288   , fdmRollback
  289   , fdmInnerValue
  290   , fdmAvgInnerValue
  291   , fdmSolve
  292     -- ** Paths
  293   , weight
  294   , assetNumber
  295   , pathSize
  296   , assetAt
  297   , asset
  298     -- ** Random sequences and meshers
  299   , rsgDimension
  300   , lastSequence
  301   , pathGeneratorSequence
  302   , fdmMesherLocations
  303   ) where
  304 import qualified Foreign.C.Types as C2HSImp
  305 import qualified Foreign.ForeignPtr as C2HSImp
  306 import qualified Foreign.Marshal.Utils as C2HSImp
  307 import qualified Foreign.Ptr as C2HSImp
  308 import qualified System.IO.Unsafe as C2HSImp
  309 
  310 
  311 
  312 
  313 
  314 
  315 
  316 import QuantLib.Internal
  317 import qualified QuantLib.Internal.Callback as Callback
  318 import QuantLib.Internal.Type hiding (ptr) -- c2hs {#get#} binds its own `ptr'
  319 import QuantLib.Internal.Common
  320 import QuantLib.Math
  321 
  322 import Foreign.C.String(peekCString)
  323 import Foreign.C.Types(CDouble)
  324 import Foreign.Ptr(Ptr, nullPtr, castPtr)
  325 import Foreign.Marshal.Alloc(alloca)
  326 import Foreign.Marshal.Array(moveArray)
  327 import Control.Exception(throwIO)
  328 import qualified Data.Vector.Storable as V
  329 
  330 
  331 
  332 
  333 
  334 
  335 
  336 
  337 
  338 
  339 
  340 
  341 
  342 
  343 
  344 
  345 
  346 
  347 
  348 
  349 
  350 
  351 
  352 
  353 
  354 
  355 
  356 
  357 
  358 
  359 
  360 
  361 
  362 
  363 
  364 
  365 
  366 
  367 
  368 
  369 -- A step condition may return its borrowed input, which shares the output buffer.
  370 pokeFdmResult :: Int -> Ptr CDouble -> RealVector -> IO ()
  371 pokeFdmResult expected out result
  372   | V.length result /= expected = throwIO (CallbackResultLength expected (V.length result))
  373   | otherwise = V.unsafeWith result $ \p -> moveArray out (castPtr p) expected
  374 
  375 withFdmResult :: (Callback.CallbackArgs -> RealVector -> RealVector) -> (Ptr () -> IO b) -> IO b
  376 withFdmResult f use = Callback.withCallback call (`withCallbackPtr` use)
  377   where
  378     call args = do
  379       x <- borrowRealVector (Callback.callbackInput args) (fromIntegral (Callback.callbackSize args))
  380       pokeFdmResult (Callback.callbackSize args) (Callback.callbackOutput args) (f args x)
  381 
  382 withFdmApply :: ((Double, Double) -> RealVector -> RealVector) -> (Ptr () -> IO b) -> IO b
  383 withFdmApply f = withFdmResult $ \args -> f (Callback.callbackTime1 args, Callback.callbackTime2 args)
  384 
  385 withFdmApplyDirection :: (Int -> (Double, Double) -> RealVector -> RealVector) -> (Ptr () -> IO b) -> IO b
  386 withFdmApplyDirection f = withFdmResult $ \args ->
  387   f (Callback.callbackDirection args) (Callback.callbackTime1 args, Callback.callbackTime2 args)
  388 
  389 withFdmSolveSplitting :: (Int -> Double -> (Double, Double) -> RealVector -> RealVector) -> (Ptr () -> IO b) -> IO b
  390 withFdmSolveSplitting f = withFdmResult $ \args ->
  391   f (Callback.callbackDirection args) (Callback.callbackScalar args) (Callback.callbackTime1 args, Callback.callbackTime2 args)
  392 
  393 withMaybeFdmStepCondition :: Maybe (Double -> RealVector -> RealVector) -> (Ptr () -> IO b) -> IO b
  394 withMaybeFdmStepCondition Nothing use = use nullPtr
  395 withMaybeFdmStepCondition (Just f) use = withFdmResult (f . Callback.callbackTime1) use
  396 
  397 -- |build a multi-asset path generator driven by a pseudo-random number generator (Mersenne Twister, Poisson, or Ziggurat, chosen by the RNG trait) over the given process and time grid.
  398 pathGenerator :: (RngTrait) -> (GenStochasticProcess p) -> (TimeGrid) -> (Word) -- ^seed
  399  -> (Word) -- ^dimension
  400  -> (Bool) -- ^brownian bridge
  401  -> IO ((PathGenerator))
  402 pathGenerator a1 a2 a3 a4 a5 a6 =
  403   let {a1' = fromEnumC a1} in 
  404   withStochasticProcess a2 $ \a2' -> 
  405   withTimeGrid a3 $ \a3' -> 
  406   let {a4' = fromIntegral a4} in 
  407   let {a5' = fromIntegral a5} in 
  408   let {a6' = C2HSImp.fromBool a6} in 
  409   preErrorCheck $ \a7' -> 
  410   pathGenerator'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
  411   peekPathGenerator res >>= \res' ->
  412   errorCheck  a7'>>
  413   return (res')
  414 
  415 
  416 
  417 -- |build a multi-asset path generator driven by a low-discrepancy (Sobol) sequence, using the given direction integers, over the given process and time grid.
  418 sobolPathGenerator :: (SobolDirectionIntegers) -> (GenStochasticProcess p) -> (TimeGrid) -> (Word) -- ^seed
  419  -> (Word) -- ^dimension
  420  -> (Bool) -- ^brownian bridge
  421  -> IO ((PathGenerator))
  422 sobolPathGenerator a1 a2 a3 a4 a5 a6 =
  423   let {a1' = fromEnumC a1} in 
  424   withStochasticProcess a2 $ \a2' -> 
  425   withTimeGrid a3 $ \a3' -> 
  426   let {a4' = fromIntegral a4} in 
  427   let {a5' = fromIntegral a5} in 
  428   let {a6' = C2HSImp.fromBool a6} in 
  429   preErrorCheck $ \a7' -> 
  430   sobolPathGenerator'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
  431   peekPathGenerator res >>= \res' ->
  432   errorCheck  a7'>>
  433   return (res')
  434 
  435 
  436 
  437 -- |The gaussian sequence generator a 'pathGenerator' drives its evolution with, exposed on its own
  438 -- so a Haskell-defined SDE can be simulated with no FFI call in the inner loop -- the same
  439 -- decomposition 'lsmRegress' applies to @LongstaffSchwartzPathPricer@, one level lower down.
  440 --
  441 -- QuantLib's @StochasticProcess@ has no Haskell-subclassable hook here by design: @MultiPathGenerator@
  442 -- (which 'pathGenerator' wraps) calls @process->evolve@ once per timestep /per path/, so binding
  443 -- that virtual as a callback would put an FFI crossing in the hottest loop there is. Drawing the
  444 -- normals with 'nextSequence' and writing @evolve@ in Haskell instead costs one crossing per
  445 -- /path/, and the result composes with 'lsmRegress' into a complete custom-SDE American Monte
  446 -- Carlo. The trade-off is that the result is a set of paths, not a @StochasticProcess@ object, so
  447 -- it cannot be fed to 'fdmSimpleProcess1dMesher' or to a pricing engine -- but no stock QuantLib
  448 -- engine would have accepted a custom process anyway: their constructors are typed on concrete
  449 -- process classes (@GeneralizedBlackScholesProcess@ and friends), not on the abstract base.
  450 --
  451 -- @dimension@ is the length of each drawn sequence: (normals drawn per step) * timesteps. For
  452 -- 'pathGenerator' parity the per-step count is the process's @factors@; a Haskell-evolved model
  453 -- may draw more normals per step than it has Brownian drivers. The construction mirrors
  454 -- 'pathGenerator''s exactly (same trait, same seed, same direction integers), so a
  455 -- Haskell-evolved path can be compared draw for draw against a 'pathGenerator' one on a bound
  456 -- process.
  457 gaussianRsg :: (RngTrait) -> (Word) -- ^dimension
  458  -> (Word) -- ^seed
  459  -> IO ((GaussianRsg))
  460 gaussianRsg a1 a2 a3 =
  461   let {a1' = fromEnumC a1} in 
  462   let {a2' = fromIntegral a2} in 
  463   let {a3' = fromIntegral a3} in 
  464   preErrorCheck $ \a4' -> 
  465   gaussianRsg'_ a1' a2' a3' a4' >>= \res ->
  466   peekGaussianRsg res >>= \res' ->
  467   errorCheck  a4'>>
  468   return (res')
  469 
  470 
  471 
  472 -- |'gaussianRsg' driven by a low-discrepancy (Sobol) sequence with the given direction integers --
  473 -- the 'sobolPathGenerator' counterpart. The maximum @dimension@ depends on the direction-integer
  474 -- set and on QuantLib's build-time @PPMT_MAX_DIM@; a larger one raises an exception.
  475 sobolGaussianRsg :: (SobolDirectionIntegers) -> (Word) -- ^dimension
  476  -> (Word) -- ^seed
  477  -> IO ((GaussianRsg))
  478 sobolGaussianRsg a1 a2 a3 =
  479   let {a1' = fromEnumC a1} in 
  480   let {a2' = fromIntegral a2} in 
  481   let {a3' = fromIntegral a3} in 
  482   preErrorCheck $ \a4' -> 
  483   sobolGaussianRsg'_ a1' a2' a3' a4' >>= \res ->
  484   peekGaussianRsg res >>= \res' ->
  485   errorCheck  a4'>>
  486   return (res')
  487 
  488 
  489 
  490 -- |the length of each sequence the generator draws.
  491 rsgDimension :: (GaussianRsg) -> (Word)
  492 rsgDimension a1 =
  493   C2HSImp.unsafePerformIO $
  494   withGaussianRsg a1 $ \a1' -> 
  495   rsgDimension'_ a1' >>= \res ->
  496   let {res' = fromIntegral res} in
  497   return (res')
  498 
  499 
  500 
  501 -- |draw the next sequence of standard normal variates, with its sample weight (1 for every trait
  502 -- bound here, carried through for symmetry with 'weight').
  503 nextSequence :: (GaussianRsg) -> IO ((RealVector), (Double))
  504 nextSequence a1 =
  505   withGaussianRsg a1 $ \a1' -> 
  506   preDoubleArray $ \(a2'1, a2'2) -> 
  507   alloca $ \a3' -> 
  508   preErrorCheck $ \a4' -> 
  509   nextSequence'_ a1' a2'1  a2'2 a3' a4' >>
  510   peekRealVector  a2'1  a2'2>>= \a2'' -> 
  511   peekDouble  a3'>>= \a3'' -> 
  512   errorCheck  a4'>>
  513   return (a2'', a3'')
  514 
  515 
  516 
  517 -- |re-read the sequence 'nextSequence' last drew, without advancing the generator.
  518 lastSequence :: (GaussianRsg) -> IO ((RealVector), (Double))
  519 lastSequence a1 =
  520   withGaussianRsg a1 $ \a1' -> 
  521   preDoubleArray $ \(a2'1, a2'2) -> 
  522   alloca $ \a3' -> 
  523   preErrorCheck $ \a4' -> 
  524   lastSequence'_ a1' a2'1  a2'2 a3' a4' >>
  525   peekRealVector  a2'1  a2'2>>= \a2'' -> 
  526   peekDouble  a3'>>= \a3'' -> 
  527   errorCheck  a4'>>
  528   return (a2'', a3'')
  529 
  530 
  531 
  532 -- |The random sequence consumed by the last 'next', with its sample weight, without advancing
  533 -- the generator. Refuses before the first draw. These are variates before process correlation;
  534 -- 'antithetic' uses their negatives and leaves this original sequence unchanged.
  535 pathGeneratorSequence :: (PathGenerator) -- ^generator
  536  -> IO ((RealVector), (Double))
  537 pathGeneratorSequence a1 =
  538   withPathGenerator a1 $ \a1' -> 
  539   preDoubleArray $ \(a2'1, a2'2) -> 
  540   alloca $ \a3' -> 
  541   preErrorCheck $ \a4' -> 
  542   pathGeneratorSequence'_ a1' a2'1  a2'2 a3' a4' >>
  543   peekRealVector  a2'1  a2'2>>= \a2'' -> 
  544   peekDouble  a3'>>= \a3'' -> 
  545   errorCheck  a4'>>
  546   return (a2'', a3'')
  547 
  548 
  549 
  550 -- |draw the next weighted sample path from the generator.
  551 next :: (PathGenerator) -> IO ((SamplePath))
  552 next a1 =
  553   withPathGenerator a1 $ \a1' -> 
  554   preErrorCheck $ \a2' -> 
  555   next'_ a1' a2' >>= \res ->
  556   peekSamplePath res >>= \res' ->
  557   errorCheck  a2'>>
  558   return (res')
  559 
  560 
  561 
  562 -- |draw the antithetic (sign-flipped) counterpart of the last drawn sample path.
  563 antithetic :: (PathGenerator) -> IO ((SamplePath))
  564 antithetic a1 =
  565   withPathGenerator a1 $ \a1' -> 
  566   preErrorCheck $ \a2' -> 
  567   antithetic'_ a1' a2' >>= \res ->
  568   peekSamplePath res >>= \res' ->
  569   errorCheck  a2'>>
  570   return (res')
  571 
  572 
  573 
  574 -- |the weight associated with a sample path.
  575 weight :: (SamplePath) -> (Double)
  576 weight a1 =
  577   C2HSImp.unsafePerformIO $
  578   withSamplePath a1 $ \a1' -> 
  579   weight'_ a1' >>= \res ->
  580   let {res' = realToFrac res} in
  581   return (res')
  582 
  583 
  584 
  585 -- |the number of correlated asset paths in a sample.
  586 assetNumber :: (SamplePath) -> (Word)
  587 assetNumber a1 =
  588   C2HSImp.unsafePerformIO $
  589   withSamplePath a1 $ \a1' -> 
  590   assetNumber'_ a1' >>= \res ->
  591   let {res' = fromIntegral res} in
  592   return (res')
  593 
  594 
  595 
  596 -- |the number of time steps in each asset path of a sample.
  597 pathSize :: (SamplePath) -> (Word)
  598 pathSize a1 =
  599   C2HSImp.unsafePerformIO $
  600   withSamplePath a1 $ \a1' -> 
  601   pathSize'_ a1' >>= \res ->
  602   let {res' = fromIntegral res} in
  603   return (res')
  604 
  605 
  606 
  607 -- |the value of one asset's path at a given time step.
  608 assetAt :: (SamplePath) -> (Word) -- ^asset
  609  -> (Word) -- ^point
  610  -> IO ((Double))
  611 assetAt a1 a2 a3 =
  612   withSamplePath a1 $ \a1' -> 
  613   let {a2' = fromIntegral a2} in 
  614   let {a3' = fromIntegral a3} in 
  615   preErrorCheck $ \a4' -> 
  616   assetAt'_ a1' a2' a3' a4' >>= \res ->
  617   let {res' = realToFrac res} in
  618   errorCheck  a4'>>
  619   return (res')
  620 
  621 
  622 
  623 -- |The full simulated path (values at every time step) of a single asset.
  624 asset :: (SamplePath) -> (Word) -> IO ((RealVector))
  625 asset a1 a2 =
  626   withSamplePath a1 $ \a1' -> 
  627   let {a2' = fromIntegral a2} in 
  628   preDoubleArray $ \(a3'1, a3'2) -> 
  629   preErrorCheck $ \a4' -> 
  630   asset'_ a1' a2' a3'1  a3'2 a4' >>
  631   peekRealVector  a3'1  a3'2>>= \a3'' -> 
  632   errorCheck  a4'>>
  633   return (a3'')
  634 
  635 
  636 
  637 -- |one step of Longstaff-Schwartz early-exercise regression: fit a polynomial basis of the given
  638 -- order/type against the (in-the-money) fit states and their continuation targets, then evaluate the
  639 -- fitted continuation value at each of the given eval states. This is the same per-exercise-date
  640 -- regression @LongstaffSchwartzPathPricer@ performs internally against a bound @Payoff@, exposed so it
  641 -- can be driven from a Haskell-defined payoff instead: call it once per exercise date, walking dates
  642 -- strictly backward, batched across all paths rather than per path. See this module's header for the
  643 -- full backward-induction pattern.
  644 lsmRegress :: (PolynomialType) -> (Word) -- ^basis order
  645  -> (RealVector) -- ^fit states (in-the-money paths only)
  646  -> (RealVector) -- ^fit targets (continuation value at these states)
  647  -> (RealVector) -- ^eval states (all paths' state at this date)
  648  -> IO ((RealVector))
  649 lsmRegress a1 a2 a3 a4 a5 =
  650   let {a1' = (fromIntegral . fromEnum) a1} in 
  651   let {a2' = fromIntegral a2} in 
  652   withRealVector a3 $ \(a3'1, a3'2) -> 
  653   withRealVector a4 $ \(a4'1, a4'2) -> 
  654   withRealVector a5 $ \(a5'1, a5'2) -> 
  655   preDoubleArray $ \(a6'1, a6'2) -> 
  656   preErrorCheck $ \a7' -> 
  657   lsmRegress'_ a1' a2' a3'1  a3'2 a4'1  a4'2 a5'1  a5'2 a6'1  a6'2 a7' >>
  658   peekRealVector  a6'1  a6'2>>= \a6'' -> 
  659   errorCheck  a7'>>
  660   return (a6'')
  661 
  662 
  663 
  664 -- |number of basis terms 'lsmRegressMulti' fits for a given number of underlyings and order --
  665 -- @C(dim+order, order)@, the binomial coefficient @LsmBasisSystem::multiPathBasisSystem@ actually
  666 -- returns (not @order+1@, which only coincides at @dim=1@ -- 'lsmRegress' uses that special case
  667 -- directly rather than calling this). Use it to size the \"enough in-the-money calibration paths to
  668 -- fit\" guard before calling 'lsmRegressMulti': the underlying least-squares solve requires at least
  669 -- this many fit rows, and undershooting it throws rather than returning a degenerate fit.
  670 lsmBasisSize :: Word -> Word -> Word
  671 lsmBasisSize dim order = fromInteger $ binomial (toInteger dim + toInteger order) (toInteger order)
  672   where binomial n k = product [n - k + 1 .. n] `div` product [1 .. k]
  673 
  674 -- |multi-asset counterpart of 'lsmRegress', for a Haskell-defined basket (several correlated
  675 -- underlyings) early-exercise payoff -- 'lsmRegress' itself only regresses against one state
  676 -- variable. Fit\/eval states are contiguous row-major 'RealMatrix' values: one row per path, one column per underlying, and the
  677 -- two matrices' column counts must agree. Regresses against
  678 -- @LsmBasisSystem::multiPathBasisSystem@'s combinatorial basis; see 'lsmBasisSize' for its size and
  679 -- this module's header for the surrounding backward-induction pattern (identical to the scalar case,
  680 -- just with 'Matrix'-shaped states).
  681 lsmRegressMulti :: PolynomialType -> Word -> RealMatrix -- ^fit states (in-the-money paths only)
  682   -> RealVector -- ^fit targets (continuation value at these states)
  683   -> RealMatrix -- ^eval states (all paths' state at this date)
  684   -> IO RealVector -- ^continuation value estimate per eval row
  685 lsmRegressMulti p order (RealMatrix fr fc fd) t (RealMatrix er ec ed) = qlLsmRegressMulti p order fr fc fd t er ec ed
  686 qlLsmRegressMulti :: (PolynomialType) -> (Word) -- ^basis order
  687  -> (Word) -- ^fit rows
  688  -> (Word) -- ^fit columns (underlyings)
  689  -> (RealVector) -- ^fit states, row-major
  690  -> (RealVector) -- ^fit targets
  691  -> (Word) -- ^eval rows
  692  -> (Word) -- ^eval columns (underlyings)
  693  -> (RealVector) -- ^eval states, row-major
  694  -> IO ((RealVector))
  695 qlLsmRegressMulti a1 a2 a3 a4 a5 a6 a7 a8 a9 =
  696   let {a1' = (fromIntegral . fromEnum) a1} in 
  697   let {a2' = fromIntegral a2} in 
  698   let {a3' = fromIntegral a3} in 
  699   let {a4' = fromIntegral a4} in 
  700   withRealVectorRaw a5 $ \a5' -> 
  701   withRealVector a6 $ \(a6'1, a6'2) -> 
  702   let {a7' = fromIntegral a7} in 
  703   let {a8' = fromIntegral a8} in 
  704   withRealVectorRaw a9 $ \a9' -> 
  705   preDoubleArray $ \(a10'1, a10'2) -> 
  706   preErrorCheck $ \a11' -> 
  707   qlLsmRegressMulti'_ a1' a2' a3' a4' a5' a6'1  a6'2 a7' a8' a9' a10'1  a10'2 a11' >>
  708   peekRealVector  a10'1  a10'2>>= \a10'' -> 
  709   errorCheck  a11'>>
  710   return (a10'')
  711 
  712 
  713 
  714 -- |basis coefficients of one Longstaff-Schwartz fit, the fitting half of 'lsmRegress' (one state
  715 -- column) or 'lsmRegressMulti' (several): fit states are a row-major 'RealMatrix', one row per
  716 -- path. There are 'lsmBasisSize' of them, in QuantLib's basis order; evaluate them with 'lsmEvaluate'.
  717 lsmFit :: PolynomialType -> Word -> RealMatrix -- ^fit states (in-the-money paths only)
  718   -> RealVector -- ^fit targets (continuation value at these states)
  719   -> IO RealVector -- ^basis coefficients
  720 lsmFit p order (RealMatrix r c d) = qlLsmFit p order r c d
  721 qlLsmFit :: (PolynomialType) -> (Word) -- ^basis order
  722  -> (Word) -- ^rows
  723  -> (Word) -- ^columns
  724  -> (RealVector) -- ^states, row-major
  725  -> (RealVector) -- ^targets
  726  -> IO ((RealVector))
  727 qlLsmFit a1 a2 a3 a4 a5 a6 =
  728   let {a1' = (fromIntegral . fromEnum) a1} in 
  729   let {a2' = fromIntegral a2} in 
  730   let {a3' = fromIntegral a3} in 
  731   let {a4' = fromIntegral a4} in 
  732   withRealVectorRaw a5 $ \a5' -> 
  733   withRealVector a6 $ \(a6'1, a6'2) -> 
  734   preDoubleArray $ \(a7'1, a7'2) -> 
  735   preErrorCheck $ \a8' -> 
  736   qlLsmFit'_ a1' a2' a3' a4' a5' a6'1  a6'2 a7'1  a7'2 a8' >>
  737   peekRealVector  a7'1  a7'2>>= \a7'' -> 
  738   errorCheck  a8'>>
  739   return (a7'')
  740 
  741 
  742 
  743 -- |continuation value of 'lsmFit' coefficients at each row of the given states, which must have
  744 -- the fit's column count; the polynomial type and order must be the fit's too. Throws unless there
  745 -- are 'lsmBasisSize' coefficients for that column count.
  746 lsmEvaluate :: PolynomialType -> Word -> RealVector -- ^coefficients
  747   -> RealMatrix -- ^eval states (one row per path)
  748   -> IO RealVector -- ^continuation value estimate per row
  749 lsmEvaluate p order coefficients (RealMatrix r c d) = qlLsmEvaluate p order coefficients r c d
  750 qlLsmEvaluate :: (PolynomialType) -> (Word) -- ^basis order
  751  -> (RealVector) -- ^coefficients
  752  -> (Word) -- ^rows
  753  -> (Word) -- ^columns
  754  -> (RealVector) -- ^states, row-major
  755  -> IO ((RealVector))
  756 qlLsmEvaluate a1 a2 a3 a4 a5 a6 =
  757   let {a1' = (fromIntegral . fromEnum) a1} in 
  758   let {a2' = fromIntegral a2} in 
  759   withRealVector a3 $ \(a3'1, a3'2) -> 
  760   let {a4' = fromIntegral a4} in 
  761   let {a5' = fromIntegral a5} in 
  762   withRealVectorRaw a6 $ \a6' -> 
  763   preDoubleArray $ \(a7'1, a7'2) -> 
  764   preErrorCheck $ \a8' -> 
  765   qlLsmEvaluate'_ a1' a2' a3'1  a3'2 a4' a5' a6' a7'1  a7'2 a8' >>
  766   peekRealVector  a7'1  a7'2>>= \a7'' -> 
  767   errorCheck  a8'>>
  768   return (a7'')
  769 
  770 
  771 
  772 -- |the build that 'lsmFit' and 'lsmEvaluate' belong to: the shim's basis revision, the QuantLib
  773 -- version, the compiler and the architecture. Store it beside coefficients meant for later use.
  774 lsmEvaluatorIdentity :: (String)
  775 lsmEvaluatorIdentity =
  776   C2HSImp.unsafePerformIO $
  777   lsmEvaluatorIdentity'_ >>= \res ->
  778   peekCString res >>= \res' ->
  779   return (res')
  780 
  781 
  782 
  783 -- |Drive @FdmBackwardSolver::rollback@ with a Haskell-defined 'FdmLinearOpComposite' (the
  784 -- @apply@\/@apply_direction@\/@solve_splitting@ callbacks) and an optional Haskell-defined step
  785 -- condition (e.g. American\/Bermudan early exercise, or a barrier), instead of a bound mesher +
  786 -- @FdmInnerValueCalculator@ as every concrete FDM pricing engine in "QuantLib.PricingEngine"
  787 -- uses. This coarsened callback shape is modeled on QuantLib-SWIG's
  788 -- @FdmLinearOpCompositeDelegate@\/
  789 -- @FdmStepConditionDelegate@ (@SWIG\/fdm.i@): each callback crosses once per outer iteration over
  790 -- the whole grid array, not once per grid node.
  791 -- Internally each callback receives one native argument record, avoiding a wide mixed-argument
  792 -- callback ABI at the Haskell boundary; this does not affect the public callback types.
  793 --
  794 -- The grid is a plain @[Double]@ in and out -- no mesher, no @FdmInnerValueCalculator@, no
  795 -- @FdmSolverDesc@ is bound; callers manage their own grid geometry entirely in Haskell. Boundary
  796 -- conditions are always the empty @FdmBoundaryConditionSet()@ (not bound). Every callback must
  797 -- return an array of its input's length; any other length throws 'QuantLib.Context.CallbackResultLength'.
  798 --
  799 -- /Only DouglasScheme::step's three virtuals are implemented -- 'apply', 'apply_direction' and/
  800 -- /'solve_splitting'; @apply_mixed@\/@preconditioner@ are unimplemented and @QL_FAIL@ at the C++/
  801 -- /level if called./ This makes 'fdmRollback' safe to drive with 'QuantLib.Internal.Common.Douglas'
  802 -- or 'QuantLib.Internal.Common.CrankNicolson' in one dimension (the two schemes
  803 -- @DouglasScheme::step@ itself is used for) -- anything needing mixed derivatives across more than
  804 -- one PDE direction (Craig-Sneyd, Hundsdorfer, or any genuinely multi-dimensional operator) will
  805 -- throw partway through 'fdmRollback' rather than silently mispricing.
  806 fdmRollback :: (Int) -- ^number of PDE directions\/dimensions the operator has (e.g. 1 for a 1D Black-Scholes-in-log-spot operator) -- /not/ the grid array length, which is the length of every @[Double]@ passed to\/returned from the callbacks below
  807  -> ((Double,Double) -> RealVector -> RealVector) -- ^@apply(r)@: whole-grid operator application at the current @(t1,t2)@ time pair (no direction argument -- QuantLib's own 'FdmLinearOp' base method)
  808  -> (Int -> (Double,Double) -> RealVector -> RealVector) -- ^@apply_direction(direction, r)@
  809  -> (Int -> Double -> (Double,Double) -> RealVector -> RealVector) -- ^@solve_splitting(direction, r, s)@ -- the implicit per-direction solve (e.g. a tridiagonal\/Thomas-algorithm solve for a 1D operator)
  810  -> (Maybe (Double -> RealVector -> RealVector)) -- ^optional step condition @applyTo(a, t)@, e.g. American\/Bermudan early exercise (@max(a_i, intrinsic_i)@ at every step) or a barrier knockout
  811  -> (RealVector) -- ^stopping times at which the step condition above is applied (ignored if there is no step condition); pass every rollback step's time to apply it at every step
  812  -> (FdmScheme) -- ^the finite-difference scheme (see the haddock above for which schemes are actually safe to use here)
  813  -> (RealVector) -- ^initial grid values, at time \'from\'
  814  -> (Double) -- ^from (start time of the rollback, e.g. option maturity)
  815  -> (Double) -- ^to (end time of the rollback, e.g. 0)
  816  -> (Int) -- ^steps
  817  -> (Int) -- ^dampingSteps
  818  -> IO ((RealVector))
  819 fdmRollback a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 =
  820   let {a1' = fromIntegral a1} in 
  821   withFdmApply a2 $ \a2' -> 
  822   withFdmApplyDirection a3 $ \a3' -> 
  823   withFdmSolveSplitting a4 $ \a4' -> 
  824   withMaybeFdmStepCondition a5 $ \a5' -> 
  825   withRealVector a6 $ \(a6'1, a6'2) -> 
  826   withFdmSchemeDesc a7 $ \a7' -> 
  827   withRealVector a8 $ \(a8'1, a8'2) -> 
  828   let {a9' = realToFrac a9} in 
  829   let {a10' = realToFrac a10} in 
  830   let {a11' = fromIntegral a11} in 
  831   let {a12' = fromIntegral a12} in 
  832   preDoubleArray $ \(a13'1, a13'2) -> 
  833   preErrorCheck $ \a14' -> 
  834   fdmRollback'_ a1' a2' a3' a4' a5' a6'1  a6'2 a7' a8'1  a8'2 a9' a10' a11' a12' a13'1  a13'2 a14' >>
  835   peekRealVector  a13'1  a13'2>>= \a13'' -> 
  836   errorCheck  a14'>>
  837   return (a13'')
  838 
  839 
  840 
  841 -- |'Predefined1dMesher(points)' -- an 'Fdm1dMesher' over an explicit, caller-supplied set of grid points.
  842 predefined1dMesher :: (RealVector) -- ^points
  843  -> IO ((Fdm1dMesher))
  844 predefined1dMesher a1 =
  845   withRealVector a1 $ \(a1'1, a1'2) -> 
  846   preErrorCheck $ \a2' -> 
  847   predefined1dMesher'_ a1'1  a1'2 a2' >>= \res ->
  848   peekFdm1dMesher res >>= \res' ->
  849   errorCheck  a2'>>
  850   return (res')
  851 
  852 
  853 
  854 -- |'Uniform1dMesher(start, end, size)' -- an evenly spaced 'Fdm1dMesher'.
  855 uniform1dMesher :: (Double) -- ^start
  856  -> (Double) -- ^end
  857  -> (Word) -- ^size
  858  -> IO ((Fdm1dMesher))
  859 uniform1dMesher a1 a2 a3 =
  860   let {a1' = realToFrac a1} in 
  861   let {a2' = realToFrac a2} in 
  862   let {a3' = fromIntegral a3} in 
  863   preErrorCheck $ \a4' -> 
  864   uniform1dMesher'_ a1' a2' a3' a4' >>= \res ->
  865   peekFdm1dMesher res >>= \res' ->
  866   errorCheck  a4'>>
  867   return (res')
  868 
  869 
  870 
  871 -- |'Concentrating1dMesher(start, end, size, cPoint, requireCPoint)' -- an 'Fdm1dMesher' with grid
  872 -- points concentrated near @cPoint@ (e.g. a strike or barrier), or plain uniform spacing when
  873 -- @cPoint@ is 'Nothing' for both coordinates.
  874 concentrating1dMesher :: (Double) -- ^start
  875  -> (Double) -- ^end
  876  -> (Word) -- ^size
  877  -> (Maybe Double) -- ^concentration point location
  878  -> (Maybe Double) -- ^concentration point density
  879  -> (Bool) -- ^requireCPoint: force the concentration point itself onto the grid
  880  -> IO ((Fdm1dMesher))
  881 concentrating1dMesher a1 a2 a3 a4 a5 a6 =
  882   let {a1' = realToFrac a1} in 
  883   let {a2' = realToFrac a2} in 
  884   let {a3' = fromIntegral a3} in 
  885   let {a4' = fromMaybeDouble a4} in 
  886   let {a5' = fromMaybeDouble a5} in 
  887   let {a6' = C2HSImp.fromBool a6} in 
  888   preErrorCheck $ \a7' -> 
  889   concentrating1dMesher'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
  890   peekFdm1dMesher res >>= \res' ->
  891   errorCheck  a7'>>
  892   return (res')
  893 
  894 
  895 
  896 -- |Multi-concentration-point overload of 'concentrating1dMesher'
  897 -- (@Concentrating1dMesher(start, end, size, cPoints, tol)@) -- a distinct upstream constructor,
  898 -- not a defaulted-arg variant of the single-point one.
  899 concentrating1dMesherMulti :: Double -> Double -> Word
  900   -> [(Double, Double, Bool)] -- ^concentration points: (location, density, requireCPoint)
  901   -> Double -- ^tol
  902   -> IO Fdm1dMesher
  903 concentrating1dMesherMulti start end sz cPoints tol =
  904   let (locs, densities, reqs) = unzip3 cPoints
  905   in qlConcentrating1dMesherMulti start end sz (fromIntegral (length cPoints)) locs densities reqs tol
  906 qlConcentrating1dMesherMulti :: (Double) -> (Double) -> (Word) -> (Word) -- ^number of concentration points
  907  -> ([Double]) -- ^locations
  908  -> ([Double]) -- ^densities
  909  -> ([Bool]) -- ^requireCPoint per point
  910  -> (Double) -- ^tol
  911  -> IO ((Fdm1dMesher))
  912 qlConcentrating1dMesherMulti a1 a2 a3 a4 a5 a6 a7 a8 =
  913   let {a1' = realToFrac a1} in 
  914   let {a2' = realToFrac a2} in 
  915   let {a3' = fromIntegral a3} in 
  916   let {a4' = fromIntegral a4} in 
  917   withDoubleArrayRaw a5 $ \a5' -> 
  918   withDoubleArrayRaw a6 $ \a6' -> 
  919   withBoolArrayRaw a7 $ \a7' -> 
  920   let {a8' = realToFrac a8} in 
  921   preErrorCheck $ \a9' -> 
  922   qlConcentrating1dMesherMulti'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' >>= \res ->
  923   peekFdm1dMesher res >>= \res' ->
  924   errorCheck  a9'>>
  925   return (res')
  926 
  927 
  928 
  929 -- |'Glued1dMesher(leftMesher, rightMesher)' -- splices two 'Fdm1dMesher's into one, deduplicating
  930 -- their shared boundary point if @leftMesher@'s rightmost location and @rightMesher@'s leftmost
  931 -- location coincide (within QuantLib's usual @close@ tolerance). Throws if @leftMesher@'s rightmost
  932 -- point is strictly greater than @rightMesher@'s leftmost point -- the two ranges may touch or be
  933 -- disjoint-but-ordered, never overlap or reverse.
  934 gluedMesher :: (Fdm1dMesher) -- ^leftMesher
  935  -> (Fdm1dMesher) -- ^rightMesher
  936  -> IO ((Fdm1dMesher))
  937 gluedMesher a1 a2 =
  938   withFdm1dMesher a1 $ \a1' -> 
  939   withFdm1dMesher a2 $ \a2' -> 
  940   preErrorCheck $ \a3' -> 
  941   gluedMesher'_ a1' a2' a3' >>= \res ->
  942   peekFdm1dMesher res >>= \res' ->
  943   errorCheck  a3'>>
  944   return (res')
  945 
  946 
  947 
  948 -- |'FdmBlackScholesMesher(size, process, maturity, strike, ...)' -- the standard log-spot mesher
  949 -- for a Black-Scholes-family process, reusing the same 'GeneralizedBlackScholesProcess'\/
  950 -- 'Dividend'\/'FdmQuantoHelper' plumbing "QuantLib.PricingEngine"'s @fd*@ engines already use.
  951 fdmBlackScholesMesher :: (Word) -- ^size
  952  -> (GenGeneralizedBlackScholesProcess gbs) -> (Double) -- ^maturity
  953  -> (Double) -- ^strike
  954  -> (Maybe Double) -- ^xMinConstraint
  955  -> (Maybe Double) -- ^xMaxConstraint
  956  -> (Double) -- ^eps
  957  -> (Double) -- ^scaleFactor
  958  -> (Maybe Double) -- ^concentration point location
  959  -> (Maybe Double) -- ^concentration point density
  960  -> ([Dividend]) -> (Maybe FdmQuantoHelper) -> (Double) -- ^spotAdjustment
  961  -> IO ((Fdm1dMesher))
  962 fdmBlackScholesMesher a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 =
  963   let {a1' = fromIntegral a1} in 
  964   withGeneralizedBlackScholesProcess a2 $ \a2' -> 
  965   let {a3' = realToFrac a3} in 
  966   let {a4' = realToFrac a4} in 
  967   let {a5' = fromMaybeDouble a5} in 
  968   let {a6' = fromMaybeDouble a6} in 
  969   let {a7' = realToFrac a7} in 
  970   let {a8' = realToFrac a8} in 
  971   let {a9' = fromMaybeDouble a9} in 
  972   let {a10' = fromMaybeDouble a10} in 
  973   withDividendArray a11 $ \(a11'1, a11'2) -> 
  974   withMaybeFdmQuantoHelper a12 $ \a12' -> 
  975   let {a13' = realToFrac a13} in 
  976   preErrorCheck $ \a14' -> 
  977   fdmBlackScholesMesher'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' a10' a11'1  a11'2 a12' a13' a14' >>= \res ->
  978   peekFdm1dMesher res >>= \res' ->
  979   errorCheck  a14'>>
  980   return (res')
  981 
  982 
  983 
  984 -- |'FdmCEV1dMesher(size, f0, alpha, beta, maturity, eps, scaleFactor, cPoint)' -- the standard
  985 -- mesher for a CEV process.
  986 fdmCev1dMesher :: (Word) -- ^size
  987  -> (Double) -- ^f0
  988  -> (Double) -- ^alpha
  989  -> (Double) -- ^beta
  990  -> (Double) -- ^maturity
  991  -> (Double) -- ^eps
  992  -> (Double) -- ^scaleFactor
  993  -> (Maybe Double) -- ^concentration point location
  994  -> (Maybe Double) -- ^concentration point density
  995  -> IO ((Fdm1dMesher))
  996 fdmCev1dMesher a1 a2 a3 a4 a5 a6 a7 a8 a9 =
  997   let {a1' = fromIntegral a1} in 
  998   let {a2' = realToFrac a2} in 
  999   let {a3' = realToFrac a3} in 
 1000   let {a4' = realToFrac a4} in 
 1001   let {a5' = realToFrac a5} in 
 1002   let {a6' = realToFrac a6} in 
 1003   let {a7' = realToFrac a7} in 
 1004   let {a8' = fromMaybeDouble a8} in 
 1005   let {a9' = fromMaybeDouble a9} in 
 1006   preErrorCheck $ \a10' -> 
 1007   fdmCev1dMesher'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' a10' >>= \res ->
 1008   peekFdm1dMesher res >>= \res' ->
 1009   errorCheck  a10'>>
 1010   return (res')
 1011 
 1012 
 1013 
 1014 -- |'ExponentialJump1dMesher(steps, beta, jumpIntensity, eta, eps)' -- mesher for the jump-diffusion
 1015 -- component of a jump-diffusion process.
 1016 exponentialJump1dMesher :: (Word) -- ^steps
 1017  -> (Double) -- ^beta
 1018  -> (Double) -- ^jumpIntensity
 1019  -> (Double) -- ^eta
 1020  -> (Double) -- ^eps
 1021  -> IO ((Fdm1dMesher))
 1022 exponentialJump1dMesher a1 a2 a3 a4 a5 =
 1023   let {a1' = fromIntegral a1} in 
 1024   let {a2' = realToFrac a2} in 
 1025   let {a3' = realToFrac a3} in 
 1026   let {a4' = realToFrac a4} in 
 1027   let {a5' = realToFrac a5} in 
 1028   preErrorCheck $ \a6' -> 
 1029   exponentialJump1dMesher'_ a1' a2' a3' a4' a5' a6' >>= \res ->
 1030   peekFdm1dMesher res >>= \res' ->
 1031   errorCheck  a6'>>
 1032   return (res')
 1033 
 1034 
 1035 
 1036 -- |'FdmSimpleProcess1dMesher(size, process, maturity, tAvgSteps, epsilon, mandatoryPoint)' --
 1037 -- generic mesher for any bound one-dimensional 'StochasticProcess1D'.
 1038 fdmSimpleProcess1dMesher :: (Word) -- ^size
 1039  -> (GenStochasticProcess1D p1d) -> (Double) -- ^maturity
 1040  -> (Word) -- ^tAvgSteps
 1041  -> (Double) -- ^epsilon
 1042  -> (Maybe Double) -- ^mandatoryPoint
 1043  -> IO ((Fdm1dMesher))
 1044 fdmSimpleProcess1dMesher a1 a2 a3 a4 a5 a6 =
 1045   let {a1' = fromIntegral a1} in 
 1046   withStochasticProcess1D a2 $ \a2' -> 
 1047   let {a3' = realToFrac a3} in 
 1048   let {a4' = fromIntegral a4} in 
 1049   let {a5' = realToFrac a5} in 
 1050   let {a6' = fromMaybeDouble a6} in 
 1051   preErrorCheck $ \a7' -> 
 1052   fdmSimpleProcess1dMesher'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
 1053   peekFdm1dMesher res >>= \res' ->
 1054   errorCheck  a7'>>
 1055   return (res')
 1056 
 1057 
 1058 
 1059 -- |'FdmHestonVarianceMesher(size, process, maturity, tAvgSteps, epsilon, mixingFactor)' -- variance
 1060 -- mesher for a Heston-family process.
 1061 fdmHestonVarianceMesher :: (Word) -- ^size
 1062  -> (GenHestonProcess hp) -> (Double) -- ^maturity
 1063  -> (Word) -- ^tAvgSteps
 1064  -> (Double) -- ^epsilon
 1065  -> (Double) -- ^mixingFactor
 1066  -> IO ((Fdm1dMesher))
 1067 fdmHestonVarianceMesher a1 a2 a3 a4 a5 a6 =
 1068   let {a1' = fromIntegral a1} in 
 1069   withHestonProcess a2 $ \a2' -> 
 1070   let {a3' = realToFrac a3} in 
 1071   let {a4' = fromIntegral a4} in 
 1072   let {a5' = realToFrac a5} in 
 1073   let {a6' = realToFrac a6} in 
 1074   preErrorCheck $ \a7' -> 
 1075   fdmHestonVarianceMesher'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
 1076   peekFdm1dMesher res >>= \res' ->
 1077   errorCheck  a7'>>
 1078   return (res')
 1079 
 1080 
 1081 
 1082 -- |'FdmHestonLocalVolatilityVarianceMesher(size, process, leverageFct, maturity, tAvgSteps, epsilon, mixingFactor)'
 1083 -- -- Heston variance mesher accounting for a local-volatility leverage function.
 1084 fdmHestonLocalVolatilityVarianceMesher :: (Word) -- ^size
 1085  -> (GenHestonProcess hp) -> (GenLocalVolTermStructure lv) -- ^leverageFct
 1086  -> (Double) -- ^maturity
 1087  -> (Word) -- ^tAvgSteps
 1088  -> (Double) -- ^epsilon
 1089  -> (Double) -- ^mixingFactor
 1090  -> IO ((Fdm1dMesher))
 1091 fdmHestonLocalVolatilityVarianceMesher a1 a2 a3 a4 a5 a6 a7 =
 1092   let {a1' = fromIntegral a1} in 
 1093   withHestonProcess a2 $ \a2' -> 
 1094   withGenLocalVolTermStructure a3 $ \a3' -> 
 1095   let {a4' = realToFrac a4} in 
 1096   let {a5' = fromIntegral a5} in 
 1097   let {a6' = realToFrac a6} in 
 1098   let {a7' = realToFrac a7} in 
 1099   preErrorCheck $ \a8' -> 
 1100   fdmHestonLocalVolatilityVarianceMesher'_ a1' a2' a3' a4' a5' a6' a7' a8' >>= \res ->
 1101   peekFdm1dMesher res >>= \res' ->
 1102   errorCheck  a8'>>
 1103   return (res')
 1104 
 1105 
 1106 
 1107 -- |'FdmMesherComposite' -- combine one or more 'Fdm1dMesher's into the multi-dimensional
 1108 -- 'FdmMesher' the operator\/step-condition callbacks and 'fdmSolve' operate over; the sole
 1109 -- concrete 'FdmMesher' upstream.
 1110 fdmMesherComposite :: ([Fdm1dMesher]) -> IO ((FdmMesher))
 1111 fdmMesherComposite a1 =
 1112   withFdm1dMesherArray a1 $ \(a1'1, a1'2) -> 
 1113   preErrorCheck $ \a2' -> 
 1114   fdmMesherComposite'_ a1'1  a1'2 a2' >>= \res ->
 1115   peekFdmMesher res >>= \res' ->
 1116   errorCheck  a2'>>
 1117   return (res')
 1118 
 1119 
 1120 
 1121 -- |Real-valued node locations along one dimension of a mesher, e.g. to map 'fdmSolve''s flat
 1122 -- result array back to coordinates (mirrors how @Fdm1DimSolver@\/@FdmNdimSolver@ build their own
 1123 -- @x_@ arrays from this same call upstream).
 1124 fdmMesherLocations :: (FdmMesher) -> (Int) -- ^direction
 1125  -> IO ((RealVector))
 1126 fdmMesherLocations a1 a2 =
 1127   withFdmMesher a1 $ \a1' -> 
 1128   let {a2' = fromIntegral a2} in 
 1129   preDoubleArray $ \(a3'1, a3'2) -> 
 1130   preErrorCheck $ \a4' -> 
 1131   fdmMesherLocations'_ a1' a2' a3'1  a3'2 a4' >>
 1132   peekRealVector  a3'1  a3'2>>= \a3'' -> 
 1133   errorCheck  a4'>>
 1134   return (a3'')
 1135 
 1136 
 1137 
 1138 qlFdmInnerValueCalculatorFromFunctions :: (FdmMesher) -> (Callback) -> (Callback) -> IO ((FdmInnerValueCalculator))
 1139 qlFdmInnerValueCalculatorFromFunctions a1 a2 a3 =
 1140   withFdmMesher a1 $ \a1' -> 
 1141   withCallbackPtr a2 $ \a2' -> 
 1142   withCallbackPtr a3 $ \a3' -> 
 1143   preErrorCheck $ \a4' -> 
 1144   qlFdmInnerValueCalculatorFromFunctions'_ a1' a2' a3' a4' >>= \res ->
 1145   peekFdmInnerValueCalculator res >>= \res' ->
 1146   errorCheck  a4'>>
 1147   return (res')
 1148 
 1149 
 1150 
 1151 -- |Wraps a Haskell @t -> location -> value@ pair of @innerValue@\/@avgInnerValue@ functions as a
 1152 -- real 'FdmInnerValueCalculator' that retains both callbacks after the continuation returns.
 1153 -- Callback exceptions are rethrown by the enclosing Haskell call. Unlike every callback
 1154 -- 'fdmRollback' takes, this crosses the language boundary once /per grid node/, not once per outer
 1155 -- iteration over the whole grid -- there is no batched \"whole-grid inner value\" shape anywhere
 1156 -- in QuantLib or QuantLib-SWIG. The per-call FFI cost across
 1157 -- every node (and, if a step condition also calls the calculator, every node at every exercise
 1158 -- date) is accepted -- matching QuantLib-SWIG's own accepted-cost precedent,
 1159 -- @FdmInnerValueCalculatorDelegate@ (@SWIG\/fdm.i@).
 1160 withCustomFdmInnerValueCalculator :: FdmMesher
 1161   -> (Double -> [Double] -> Double) -- ^innerValue(t, location)
 1162   -> (Double -> [Double] -> Double) -- ^avgInnerValue(t, location)
 1163   -> (FdmInnerValueCalculator -> IO b) -> IO b
 1164 withCustomFdmInnerValueCalculator mesher iv aiv k =
 1165   withFdmInnerValue iv $ \inner ->
 1166   withFdmInnerValue aiv $ \average ->
 1167   qlFdmInnerValueCalculatorFromFunctions mesher inner average >>= k
 1168 
 1169 -- |'FdmZeroInnerValue' -- an 'FdmInnerValueCalculator' whose @innerValue@\/@avgInnerValue@ are
 1170 -- always 0.
 1171 fdmZeroInnerValue :: IO ((FdmInnerValueCalculator))
 1172 fdmZeroInnerValue =
 1173   preErrorCheck $ \a1' -> 
 1174   fdmZeroInnerValue'_ a1' >>= \res ->
 1175   peekFdmInnerValueCalculator res >>= \res' ->
 1176   errorCheck  a1'>>
 1177   return (res')
 1178 
 1179 
 1180 
 1181 -- |'FdmCellAveragingInnerValue(payoff, mesher, direction)' -- cell-averages @payoff@ over each
 1182 -- grid cell along @direction@ (Simpson-integrating across the cell straddling a kink, e.g. a
 1183 -- strike, rather than just evaluating at the cell center), with the identity value mapping. See
 1184 -- 'withCustomCellAveragingInnerValue' for the @gridMapping@-taking overload (e.g. to reproduce
 1185 -- 'fdmLogInnerValue' by hand), and 'fdmLogInnerValue' for the common log-mapped case QuantLib
 1186 -- itself gives its own dedicated subclass.
 1187 fdmCellAveragingInnerValue :: (Payoff) -> (FdmMesher) -> (Int) -- ^direction
 1188  -> IO ((FdmInnerValueCalculator))
 1189 fdmCellAveragingInnerValue a1 a2 a3 =
 1190   withPayoff a1 $ \a1' -> 
 1191   withFdmMesher a2 $ \a2' -> 
 1192   let {a3' = fromIntegral a3} in 
 1193   preErrorCheck $ \a4' -> 
 1194   fdmCellAveragingInnerValue'_ a1' a2' a3' a4' >>= \res ->
 1195   peekFdmInnerValueCalculator res >>= \res' ->
 1196   errorCheck  a4'>>
 1197   return (res')
 1198 
 1199 
 1200 
 1201 qlFdmCellAveragingInnerValueMapped :: (Payoff) -> (FdmMesher) -> (Int) -> (Callback) -> IO ((FdmInnerValueCalculator))
 1202 qlFdmCellAveragingInnerValueMapped a1 a2 a3 a4 =
 1203   withPayoff a1 $ \a1' -> 
 1204   withFdmMesher a2 $ \a2' -> 
 1205   let {a3' = fromIntegral a3} in 
 1206   withCallbackPtr a4 $ \a4' -> 
 1207   preErrorCheck $ \a5' -> 
 1208   qlFdmCellAveragingInnerValueMapped'_ a1' a2' a3' a4' a5' >>= \res ->
 1209   peekFdmInnerValueCalculator res >>= \res' ->
 1210   errorCheck  a5'>>
 1211   return (res')
 1212 
 1213 
 1214 
 1215 -- |As 'fdmCellAveragingInnerValue', but with an explicit @gridMapping :: Double -> Double@ applied
 1216 -- to each node's location before the payoff sees it (e.g. @exp@ on a log-spot grid, reproducing
 1217 -- 'fdmLogInnerValue' by hand) -- a genuine per-node Haskell callback; see
 1218 -- 'withCustomFdmInnerValueCalculator'. The calculator retains the callback after the continuation.
 1219 withCustomCellAveragingInnerValue :: Payoff -> FdmMesher -> Int -> (Double -> Double)
 1220   -> (FdmInnerValueCalculator -> IO b) -> IO b
 1221 withCustomCellAveragingInnerValue payoff mesher direction mapping k =
 1222   withFdmGridMapping mapping $ \callback ->
 1223   qlFdmCellAveragingInnerValueMapped payoff mesher direction callback >>= k
 1224 
 1225 -- |'FdmLogInnerValue(payoff, mesher, direction)' -- 'fdmCellAveragingInnerValue' with the
 1226 -- @gridMapping = exp@ QuantLib itself gives its own dedicated subclass (the standard shape for a
 1227 -- log-spot grid, e.g. 'fdmBlackScholesMesher''s own grid).
 1228 fdmLogInnerValue :: (Payoff) -> (FdmMesher) -> (Int) -- ^direction
 1229  -> IO ((FdmInnerValueCalculator))
 1230 fdmLogInnerValue a1 a2 a3 =
 1231   withPayoff a1 $ \a1' -> 
 1232   withFdmMesher a2 $ \a2' -> 
 1233   let {a3' = fromIntegral a3} in 
 1234   preErrorCheck $ \a4' -> 
 1235   fdmLogInnerValue'_ a1' a2' a3' a4' >>= \res ->
 1236   peekFdmInnerValueCalculator res >>= \res' ->
 1237   errorCheck  a4'>>
 1238   return (res')
 1239 
 1240 
 1241 
 1242 -- |'FdmLogBasketInnerValue(payoff, mesher)' -- the multi-asset counterpart to 'fdmLogInnerValue':
 1243 -- evaluates a 'BasketPayoff' with each dimension's location exponentiated first (@exp@ on every
 1244 -- mesher direction, i.e. a log-spot grid per underlying), no cell averaging.
 1245 fdmLogBasketInnerValue :: (BasketPayoff) -> (FdmMesher) -> IO ((FdmInnerValueCalculator))
 1246 fdmLogBasketInnerValue a1 a2 =
 1247   withBasketPayoff a1 $ \a1' -> 
 1248   withFdmMesher a2 $ \a2' -> 
 1249   preErrorCheck $ \a3' -> 
 1250   fdmLogBasketInnerValue'_ a1' a2' a3' >>= \res ->
 1251   peekFdmInnerValueCalculator res >>= \res' ->
 1252   errorCheck  a3'>>
 1253   return (res')
 1254 
 1255 
 1256 
 1257 -- |'FdmAffineModelSwapInnerValue\<G2\>(disModel, fwdModel, swap, exerciseDates, mesher, direction)'
 1258 -- -- the swap-NPV-under-the-model 'FdmInnerValueCalculator' used internally by
 1259 -- 'QuantLib.PricingEngine.fdG2SwaptionEngine'. @exerciseDates@ pairs each exercise time (the same
 1260 -- @Time@-as-@Double@ year-fraction convention used throughout, not a dedicated type) with the
 1261 -- 'Data.Time.Calendar.Day' it corresponds to (upstream's @std::map\<Time, Date\>@).
 1262 fdmAffineG2ModelSwapInnerValue :: G2 -> G2 -> GenFixedVsFloatingSwap f -> [(Double, Day)] -> FdmMesher -> Int -> IO FdmInnerValueCalculator
 1263 fdmAffineG2ModelSwapInnerValue disModel fwdModel swap exerciseDates =
 1264   let (times, dates) = unzip exerciseDates
 1265   in qlFdmAffineG2ModelSwapInnerValue disModel fwdModel swap (length exerciseDates) times dates
 1266 qlFdmAffineG2ModelSwapInnerValue :: (G2) -> (G2) -> (GenFixedVsFloatingSwap f) -> (Int) -- ^number of exercise dates
 1267  -> ([Double]) -- ^exercise times
 1268  -> ([Day]) -- ^exercise dates
 1269  -> (FdmMesher) -> (Int) -- ^direction
 1270  -> IO ((FdmInnerValueCalculator))
 1271 qlFdmAffineG2ModelSwapInnerValue a1 a2 a3 a4 a5 a6 a7 a8 =
 1272   withG2 a1 $ \a1' -> 
 1273   withG2 a2 $ \a2' -> 
 1274   withFixedVsFloatingSwap a3 $ \a3' -> 
 1275   let {a4' = fromIntegral a4} in 
 1276   withDoubleArrayRaw a5 $ \a5' -> 
 1277   withDayPtr a6 $ \a6' -> 
 1278   withFdmMesher a7 $ \a7' -> 
 1279   let {a8' = fromIntegral a8} in 
 1280   preErrorCheck $ \a9' -> 
 1281   qlFdmAffineG2ModelSwapInnerValue'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' >>= \res ->
 1282   peekFdmInnerValueCalculator res >>= \res' ->
 1283   errorCheck  a9'>>
 1284   return (res')
 1285 
 1286 
 1287 
 1288 -- |As 'fdmAffineG2ModelSwapInnerValue', but for 'HullWhite' -- used internally by
 1289 -- 'QuantLib.PricingEngine.fdHullWhiteSwaptionEngine'.
 1290 fdmAffineHullWhiteModelSwapInnerValue :: HullWhite -> HullWhite -> GenFixedVsFloatingSwap f -> [(Double, Day)] -> FdmMesher -> Int -> IO FdmInnerValueCalculator
 1291 fdmAffineHullWhiteModelSwapInnerValue disModel fwdModel swap exerciseDates =
 1292   let (times, dates) = unzip exerciseDates
 1293   in qlFdmAffineHullWhiteModelSwapInnerValue disModel fwdModel swap (length exerciseDates) times dates
 1294 qlFdmAffineHullWhiteModelSwapInnerValue :: (HullWhite) -> (HullWhite) -> (GenFixedVsFloatingSwap f) -> (Int) -- ^number of exercise dates
 1295  -> ([Double]) -- ^exercise times
 1296  -> ([Day]) -- ^exercise dates
 1297  -> (FdmMesher) -> (Int) -- ^direction
 1298  -> IO ((FdmInnerValueCalculator))
 1299 qlFdmAffineHullWhiteModelSwapInnerValue a1 a2 a3 a4 a5 a6 a7 a8 =
 1300   withHullWhite a1 $ \a1' -> 
 1301   withHullWhite a2 $ \a2' -> 
 1302   withFixedVsFloatingSwap a3 $ \a3' -> 
 1303   let {a4' = fromIntegral a4} in 
 1304   withDoubleArrayRaw a5 $ \a5' -> 
 1305   withDayPtr a6 $ \a6' -> 
 1306   withFdmMesher a7 $ \a7' -> 
 1307   let {a8' = fromIntegral a8} in 
 1308   preErrorCheck $ \a9' -> 
 1309   qlFdmAffineHullWhiteModelSwapInnerValue'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' >>= \res ->
 1310   peekFdmInnerValueCalculator res >>= \res' ->
 1311   errorCheck  a9'>>
 1312   return (res')
 1313 
 1314 
 1315 
 1316 -- |Evaluate an 'FdmInnerValueCalculator''s @innerValue@ at the mesher node given by its
 1317 -- coordinates (one index per PDE dimension), at time @t@ -- lets any bound calculator (native or
 1318 -- built via 'withCustomFdmInnerValueCalculator') be inspected directly without assembling a whole
 1319 -- 'fdmSolve'.
 1320 fdmInnerValue :: (FdmInnerValueCalculator) -> (FdmMesher) -> ([Int]) -- ^node coordinates
 1321  -> (Double) -- ^t
 1322  -> IO ((Double))
 1323 fdmInnerValue a1 a2 a3 a4 =
 1324   withFdmInnerValueCalculator a1 $ \a1' -> 
 1325   withFdmMesher a2 $ \a2' -> 
 1326   withIntArray a3 $ \(a3'1, a3'2) -> 
 1327   let {a4' = realToFrac a4} in 
 1328   preErrorCheck $ \a5' -> 
 1329   fdmInnerValue'_ a1' a2' a3'1  a3'2 a4' a5' >>= \res ->
 1330   let {res' = realToFrac res} in
 1331   errorCheck  a5'>>
 1332   return (res')
 1333 
 1334 
 1335 
 1336 -- |As 'fdmInnerValue', but for @avgInnerValue@.
 1337 fdmAvgInnerValue :: (FdmInnerValueCalculator) -> (FdmMesher) -> ([Int]) -- ^node coordinates
 1338  -> (Double) -- ^t
 1339  -> IO ((Double))
 1340 fdmAvgInnerValue a1 a2 a3 a4 =
 1341   withFdmInnerValueCalculator a1 $ \a1' -> 
 1342   withFdmMesher a2 $ \a2' -> 
 1343   withIntArray a3 $ \(a3'1, a3'2) -> 
 1344   let {a4' = realToFrac a4} in 
 1345   preErrorCheck $ \a5' -> 
 1346   fdmAvgInnerValue'_ a1' a2' a3'1  a3'2 a4' a5' >>= \res ->
 1347   let {res' = realToFrac res} in
 1348   errorCheck  a5'>>
 1349   return (res')
 1350 
 1351 
 1352 
 1353 -- |Sibling of 'fdmRollback' that derives its own initial grid from a mesher and an
 1354 -- 'FdmInnerValueCalculator' (@avgInnerValue(t, location)@ per node, called once per mesher node at
 1355 -- @t = maturity@ -- mirroring @Fdm1DimSolver@\/@FdmNdimSolver@'s own constructor loop) instead of
 1356 -- taking a precomputed grid array. Everything else (operator\/step-condition\/scheme\/rollback) is
 1357 -- identical to 'fdmRollback', reusing the same callback machinery. The calculator can be either
 1358 -- fully custom ('fdmInnerValueCalculator') or one of QuantLib's own native subclasses.
 1359 --
 1360 -- @Fdm1DimSolver@\/@FdmNdimSolver@ themselves (their own @LazyObject@ caching and cubic-spline
 1361 -- interpolation) are /not/ bound; combine this function's result with 'fdmMesherLocations' for
 1362 -- interpolation.
 1363 fdmSolve :: (FdmMesher) -> (FdmInnerValueCalculator) -> (Int) -- ^number of PDE directions\/dimensions the operator has
 1364  -> ((Double,Double) -> RealVector -> RealVector) -- ^@apply(r)@
 1365  -> (Int -> (Double,Double) -> RealVector -> RealVector) -- ^@apply_direction(direction, r)@
 1366  -> (Int -> Double -> (Double,Double) -> RealVector -> RealVector) -- ^@solve_splitting(direction, r, s)@
 1367  -> (Maybe (Double -> RealVector -> RealVector)) -- ^optional step condition
 1368  -> (RealVector) -- ^stopping times at which the step condition above is applied
 1369  -> (FdmScheme) -- ^the finite-difference scheme
 1370  -> (Double) -- ^maturity (start time of the rollback, and the time at which avgInnerValue builds the initial grid)
 1371  -> (Double) -- ^to (end time of the rollback, e.g. 0)
 1372  -> (Int) -- ^steps
 1373  -> (Int) -- ^dampingSteps
 1374  -> IO ((RealVector))
 1375 fdmSolve a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 =
 1376   withFdmMesher a1 $ \a1' -> 
 1377   withFdmInnerValueCalculator a2 $ \a2' -> 
 1378   let {a3' = fromIntegral a3} in 
 1379   withFdmApply a4 $ \a4' -> 
 1380   withFdmApplyDirection a5 $ \a5' -> 
 1381   withFdmSolveSplitting a6 $ \a6' -> 
 1382   withMaybeFdmStepCondition a7 $ \a7' -> 
 1383   withRealVector a8 $ \(a8'1, a8'2) -> 
 1384   withFdmSchemeDesc a9 $ \a9' -> 
 1385   let {a10' = realToFrac a10} in 
 1386   let {a11' = realToFrac a11} in 
 1387   let {a12' = fromIntegral a12} in 
 1388   let {a13' = fromIntegral a13} in 
 1389   preDoubleArray $ \(a14'1, a14'2) -> 
 1390   preErrorCheck $ \a15' -> 
 1391   fdmSolve'_ a1' a2' a3' a4' a5' a6' a7' a8'1  a8'2 a9' a10' a11' a12' a13' a14'1  a14'2 a15' >>
 1392   peekRealVector  a14'1  a14'2>>= \a14'' -> 
 1393   errorCheck  a15'>>
 1394   return (a14'')
 1395 
 1396 
 1397 
 1398 -- vim: set ff=unix ts=8 sts=2 sw=2 et:
 1399 
 1400 foreign import ccall safe "QuantLib/Method.chs.h qlPathGenerator"
 1401   pathGenerator'_ :: (C2HSImp.CInt -> ((C2HSImp.Ptr (CStochasticProcess')) -> ((C2HSImp.Ptr (CTimeGrid)) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> (C2HSImp.CInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CPathGenerator))))))))))
 1402 
 1403 foreign import ccall safe "QuantLib/Method.chs.h qlSobolPathGenerator"
 1404   sobolPathGenerator'_ :: (C2HSImp.CInt -> ((C2HSImp.Ptr (CStochasticProcess')) -> ((C2HSImp.Ptr (CTimeGrid)) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> (C2HSImp.CInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CPathGenerator))))))))))
 1405 
 1406 foreign import ccall safe "QuantLib/Method.chs.h qlGaussianRsg"
 1407   gaussianRsg'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CGaussianRsg)))))))
 1408 
 1409 foreign import ccall safe "QuantLib/Method.chs.h qlSobolGaussianRsg"
 1410   sobolGaussianRsg'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CGaussianRsg)))))))
 1411 
 1412 foreign import ccall safe "QuantLib/Method.chs.h qlGaussianRsgDimension"
 1413   rsgDimension'_ :: ((C2HSImp.Ptr (CGaussianRsg)) -> (IO C2HSImp.CUInt))
 1414 
 1415 foreign import ccall safe "QuantLib/Method.chs.h qlGaussianRsgNextSequence"
 1416   nextSequence'_ :: ((C2HSImp.Ptr (CGaussianRsg)) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))
 1417 
 1418 foreign import ccall safe "QuantLib/Method.chs.h qlGaussianRsgLastSequence"
 1419   lastSequence'_ :: ((C2HSImp.Ptr (CGaussianRsg)) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))
 1420 
 1421 foreign import ccall safe "QuantLib/Method.chs.h qlPathGeneratorSequence"
 1422   pathGeneratorSequence'_ :: ((C2HSImp.Ptr (CPathGenerator)) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))
 1423 
 1424 foreign import ccall safe "QuantLib/Method.chs.h qlPathGeneratorNext"
 1425   next'_ :: ((C2HSImp.Ptr (CPathGenerator)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CSamplePath)))))
 1426 
 1427 foreign import ccall safe "QuantLib/Method.chs.h qlPathGeneratorAntithetic"
 1428   antithetic'_ :: ((C2HSImp.Ptr (CPathGenerator)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CSamplePath)))))
 1429 
 1430 foreign import ccall safe "QuantLib/Method.chs.h qlSamplePathWeight"
 1431   weight'_ :: ((C2HSImp.Ptr (CSamplePath)) -> (IO C2HSImp.CDouble))
 1432 
 1433 foreign import ccall safe "QuantLib/Method.chs.h qlSamplePathAssetNumber"
 1434   assetNumber'_ :: ((C2HSImp.Ptr (CSamplePath)) -> (IO C2HSImp.CUInt))
 1435 
 1436 foreign import ccall safe "QuantLib/Method.chs.h qlSamplePathSize"
 1437   pathSize'_ :: ((C2HSImp.Ptr (CSamplePath)) -> (IO C2HSImp.CUInt))
 1438 
 1439 foreign import ccall safe "QuantLib/Method.chs.h qlSamplePathAt"
 1440   assetAt'_ :: ((C2HSImp.Ptr (CSamplePath)) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO C2HSImp.CDouble)))))
 1441 
 1442 foreign import ccall safe "QuantLib/Method.chs.h qlSamplePathAssetPath"
 1443   asset'_ :: ((C2HSImp.Ptr (CSamplePath)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))
 1444 
 1445 foreign import ccall safe "QuantLib/Method.chs.h qlLsmRegress"
 1446   lsmRegress'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))))))))
 1447 
 1448 foreign import ccall safe "QuantLib/Method.chs.h qlLsmRegressMulti"
 1449   qlLsmRegressMulti'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))))))))))
 1450 
 1451 foreign import ccall safe "QuantLib/Method.chs.h qlLsmFit"
 1452   qlLsmFit'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ())))))))))))
 1453 
 1454 foreign import ccall safe "QuantLib/Method.chs.h qlLsmEvaluate"
 1455   qlLsmEvaluate'_ :: (C2HSImp.CInt -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ())))))))))))
 1456 
 1457 foreign import ccall safe "QuantLib/Method.chs.h qlLsmEvaluatorIdentity"
 1458   lsmEvaluatorIdentity'_ :: (IO (C2HSImp.Ptr C2HSImp.CChar))
 1459 
 1460 foreign import ccall safe "QuantLib/Method.chs.h qlFdmRollback"
 1461   fdmRollback'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (CFdmSchemeDesc)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))))))))))))))
 1462 
 1463 foreign import ccall safe "QuantLib/Method.chs.h qlPredefined1dMesher"
 1464   predefined1dMesher'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))
 1465 
 1466 foreign import ccall safe "QuantLib/Method.chs.h qlUniform1dMesher"
 1467   uniform1dMesher'_ :: (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher)))))))
 1468 
 1469 foreign import ccall safe "QuantLib/Method.chs.h qlConcentrating1dMesher"
 1470   concentrating1dMesher'_ :: (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))))))
 1471 
 1472 foreign import ccall safe "QuantLib/Method.chs.h qlConcentrating1dMesherMulti"
 1473   qlConcentrating1dMesherMulti'_ :: (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CInt) -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))))))))
 1474 
 1475 foreign import ccall safe "QuantLib/Method.chs.h qlGluedMesher"
 1476   gluedMesher'_ :: ((C2HSImp.Ptr (CFdm1dMesher)) -> ((C2HSImp.Ptr (CFdm1dMesher)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))
 1477 
 1478 foreign import ccall safe "QuantLib/Method.chs.h qlFdmBlackScholesMesher"
 1479   fdmBlackScholesMesher'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr (CGeneralizedBlackScholesProcess')) -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr (CDividend))) -> ((C2HSImp.Ptr (CFdmQuantoHelper)) -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))))))))))))))
 1480 
 1481 foreign import ccall safe "QuantLib/Method.chs.h qlFdmCev1dMesher"
 1482   fdmCev1dMesher'_ :: (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher)))))))))))))
 1483 
 1484 foreign import ccall safe "QuantLib/Method.chs.h qlExponentialJump1dMesher"
 1485   exponentialJump1dMesher'_ :: (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher)))))))))
 1486 
 1487 foreign import ccall safe "QuantLib/Method.chs.h qlFdmSimpleProcess1dMesher"
 1488   fdmSimpleProcess1dMesher'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr (CStochasticProcess1D')) -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))))))
 1489 
 1490 foreign import ccall safe "QuantLib/Method.chs.h qlFdmHestonVarianceMesher"
 1491   fdmHestonVarianceMesher'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr (CHestonProcess')) -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher))))))))))
 1492 
 1493 foreign import ccall safe "QuantLib/Method.chs.h qlFdmHestonLocalVolatilityVarianceMesher"
 1494   fdmHestonLocalVolatilityVarianceMesher'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr (CHestonProcess')) -> ((C2HSImp.Ptr (CLocalVolTermStructure')) -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdm1dMesher)))))))))))
 1495 
 1496 foreign import ccall safe "QuantLib/Method.chs.h qlFdmMesherComposite"
 1497   fdmMesherComposite'_ :: (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr (CFdm1dMesher))) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmMesher))))))
 1498 
 1499 foreign import ccall safe "QuantLib/Method.chs.h qlFdmMesherLocations"
 1500   fdmMesherLocations'_ :: ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))
 1501 
 1502 foreign import ccall safe "QuantLib/Method.chs.h qlFdmInnerValueCalculatorFromFunctions"
 1503   qlFdmInnerValueCalculatorFromFunctions'_ :: ((C2HSImp.Ptr (CFdmMesher)) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator)))))))
 1504 
 1505 foreign import ccall safe "QuantLib/Method.chs.h qlFdmZeroInnerValue"
 1506   fdmZeroInnerValue'_ :: ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator))))
 1507 
 1508 foreign import ccall safe "QuantLib/Method.chs.h qlFdmCellAveragingInnerValue"
 1509   fdmCellAveragingInnerValue'_ :: ((QlPayoff) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator)))))))
 1510 
 1511 foreign import ccall safe "QuantLib/Method.chs.h qlFdmCellAveragingInnerValueMapped"
 1512   qlFdmCellAveragingInnerValueMapped'_ :: ((QlPayoff) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator))))))))
 1513 
 1514 foreign import ccall safe "QuantLib/Method.chs.h qlFdmLogInnerValue"
 1515   fdmLogInnerValue'_ :: ((QlPayoff) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator)))))))
 1516 
 1517 foreign import ccall safe "QuantLib/Method.chs.h qlFdmLogBasketInnerValue"
 1518   fdmLogBasketInnerValue'_ :: ((QlBasketPayoff) -> ((C2HSImp.Ptr (CFdmMesher)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator))))))
 1519 
 1520 foreign import ccall safe "QuantLib/Method.chs.h qlFdmAffineG2ModelSwapInnerValue"
 1521   qlFdmAffineG2ModelSwapInnerValue'_ :: ((C2HSImp.Ptr (CG2')) -> ((C2HSImp.Ptr (CG2')) -> ((C2HSImp.Ptr (CFixedVsFloatingSwap')) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CInt) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator))))))))))))
 1522 
 1523 foreign import ccall safe "QuantLib/Method.chs.h qlFdmAffineHullWhiteModelSwapInnerValue"
 1524   qlFdmAffineHullWhiteModelSwapInnerValue'_ :: ((C2HSImp.Ptr (CHullWhite')) -> ((C2HSImp.Ptr (CHullWhite')) -> ((C2HSImp.Ptr (CFixedVsFloatingSwap')) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr C2HSImp.CInt) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO (C2HSImp.Ptr (CFdmInnerValueCalculator))))))))))))
 1525 
 1526 foreign import ccall safe "QuantLib/Method.chs.h qlFdmInnerValueCalculatorEval"
 1527   fdmInnerValue'_ :: ((C2HSImp.Ptr (CFdmInnerValueCalculator)) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO C2HSImp.CDouble)))))))
 1528 
 1529 foreign import ccall safe "QuantLib/Method.chs.h qlFdmInnerValueCalculatorAvgEval"
 1530   fdmAvgInnerValue'_ :: ((C2HSImp.Ptr (CFdmInnerValueCalculator)) -> ((C2HSImp.Ptr (CFdmMesher)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> (C2HSImp.CDouble -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO C2HSImp.CDouble)))))))
 1531 
 1532 foreign import ccall safe "QuantLib/Method.chs.h qlFdmSolve"
 1533   fdmSolve'_ :: ((C2HSImp.Ptr (CFdmMesher)) -> ((C2HSImp.Ptr (CFdmInnerValueCalculator)) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr (CFdmSchemeDesc)) -> (C2HSImp.CDouble -> (C2HSImp.CDouble -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CDouble)) -> ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (IO ()))))))))))))))))))