Skip to content

Commit

Permalink
use toNumContextProc, generate adaptiveGauss manually
Browse files Browse the repository at this point in the history
Regarding adaptiveGauss see the added comment
  • Loading branch information
Vindaar committed Sep 13, 2024
1 parent c1a98f3 commit 6a34917
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/numericalnim/integrate.nim
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ proc cumtrapz*[T](f: NumContextProc[T, float], X: openArray[float],
t += dx
result = hermiteInterpolate(X, times, y, dy)


proc simpson*[T](f: NumContextProc[T, float], xStart, xEnd: float,
N = 500, ctx: NumContext[T, float] = nil): T {.genInterp.} =
## Calculate the integral of f using Simpson's rule.
Expand Down Expand Up @@ -856,7 +855,7 @@ template adaptiveGaussImpl(): untyped {.dirty.} =
totalValue += highValue

proc adaptiveGauss*[T; U](f_in: NumContextProc[T, U],
xStart_in, xEnd_in: U, tol = 1e-8, initialPoints: openArray[U] = @[], maxintervals: int = 10000, ctx: NumContext[T, U] = nil): T {.genInterp.} =
xStart_in, xEnd_in: U, tol = 1e-8, initialPoints: openArray[U] = @[], maxintervals: int = 10000, ctx: NumContext[T, U] = nil): T =
## Calculate the integral of f using an globally adaptive Gauss-Kronrod Quadrature. Inf and -Inf can be used as integration limits.
##
## Input:
Expand All @@ -874,6 +873,18 @@ proc adaptiveGauss*[T; U](f_in: NumContextProc[T, U],
adaptiveGaussImpl()
return totalValue

proc adaptiveGauss*[T](f_in: InterpolatorType[T]; xStart_in, xEnd_in: T;
tol = 1e-8; initialPoints: openArray[T] = @[];
maxintervals: int = 10000; ctx: NumContext[T, T] = nil): T =
## NOTE: On Nim 2.0.8 we cannot use `{.genInterp.}` on the above proc, because of
## of the double generic it has `[T; U]`. It fails. So this is just a manual version
## of the generated code for the time being.
mixin eval
mixin InterpolatorType
mixin toNumContextProc
let ncp = toNumContextProc(f_in)
adaptiveGauss(ncp, xStart_in, xEnd_in, tol, initialPoints, maxintervals, ctx)

proc cumGaussSpline*[T; U](f_in: NumContextProc[T, U],
xStart_in, xEnd_in: U, tol = 1e-8, initialPoints: openArray[U] = @[], maxintervals: int = 10000, ctx: NumContext[T, U] = nil): InterpolatorType[T] =
## Calculate the cumulative integral of f using an globally adaptive Gauss-Kronrod Quadrature. Inf and -Inf can be used as integration limits.
Expand Down
4 changes: 4 additions & 0 deletions src/numericalnim/interpolate.nim
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ proc toProc*[T](spline: InterpolatorType[T]): InterpolatorProc[T] =
## Returns a proc to evaluate the interpolator.
result = proc(x: float): T = eval(spline, x)

proc toNumContextProc*[T](spline: InterpolatorType[T]): NumContextProc[T, float] =
## Convert interpolator to `NumContextProc`.
result = proc(x: float, ctx: NumContext[T, float]): T = eval(spline, x)

proc derivEval*[T; U](spline: InterpolatorType[T], x: openArray[float], extrap: ExtrapolateKind = Native, extrapValue: U = missing()): seq[T] =
## Evaluates the derivative of an interpolator at all points in `x`.
result = newSeq[T](x.len)
Expand Down
4 changes: 3 additions & 1 deletion src/numericalnim/private/macro_utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ macro genInterp*(fn: untyped): untyped =
let ncpIdent = ident"ncp"
new.body = quote do:
mixin eval # defined in `interpolate`, but macro used in `integrate`
let `ncpIdent` = proc(x: float, ctx: NumContext[T, float]): T = eval(`arg`, x)
mixin InterpolatorType
mixin toNumContextProc
let `ncpIdent` = toNumContextProc(`arg`)
# 2c. add call to original proc
new.body.add genOriginalCall(fn, ncpIdent)
# 3. finalize
Expand Down

0 comments on commit 6a34917

Please sign in to comment.