Skip to content

Commit 5ad8423

Browse files
m-wellsdextorious
authored andcommitted
memory efficient n-dimensional integration (#20)
1 parent 2cb2740 commit 5ad8423

File tree

2 files changed

+65
-14
lines changed

2 files changed

+65
-14
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors = ["dextorious"]
44
version = "0.2.1"
55

66
[deps]
7+
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
78
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
89
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
910

src/NumericalIntegration.jl

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ module NumericalIntegration
22

33
using LinearAlgebra
44
using Logging
5+
using Base.Iterators
6+
using Interpolations
57

68
export integrate, cumul_integrate
79
export Trapezoidal, TrapezoidalEven, TrapezoidalFast, TrapezoidalEvenFast
@@ -177,27 +179,75 @@ function integrate(x::AbstractVector, y::AbstractVector, m::RombergEven)
177179
end
178180

179181

182+
@inline function _midpoints(x::AbstractVector{T}) where T
183+
length(x) == 1 && return x
184+
retval = Vector{T}(undef, length(x)-1)
185+
@simd for i in eachindex(retval)
186+
retval[i] = HALF * (x[i] + x[i+1])
187+
end
188+
return retval
189+
end
190+
@inline function _midpoints(x::AbstractRange)
191+
length(x) == 1 && return x
192+
Δx = HALF*step(x)
193+
return range(first(x)+Δx, stop=last(x)-Δx, length=length(x)-1)
194+
end
180195

181-
function integrate(X::Tuple{AbstractVector}, Y::AbstractVector{T}, M::IntegrationMethod) :: T where {T}
182-
return integrate(X[1], Y, M)
196+
function integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, ::Trapezoidal) where {T,N}
197+
@assert length.(X) == size(Y)
198+
return integrate(X, Y, TrapezoidalFast())
183199
end
184-
"""
185-
integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, method, cache=nothing)
186200

187-
Given an n-dimensional grid of values, compute the total integral along each dim
188-
"""
189-
function integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, M::IntegrationMethod) :: T where {T,N}
190-
n = last(size(Y))
191-
cache = Vector{T}(undef, n)
192-
x = X[1:N-1]
193-
@inbounds for i in 1:n
194-
cache[i] = integrate(x, selectdim(Y,N,i), M)
195-
end
196-
return integrate(X[end], cache, M)
201+
function integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, ::TrapezoidalFast) where {T,N}
202+
midpnts = map(_midpoints, X)
203+
Δ(x::AbstractVector) = length(x) > 1 ? diff(x) : 1
204+
Δxs = map(Δ, X)
205+
interp = LinearInterpolation(X,Y)
206+
f((Δx,x)) = prod(Δx)*interp(x...)
207+
return sum(f, zip(product(Δxs...), product(midpnts...)))
208+
end
209+
210+
function integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, ::TrapezoidalEvenFast) where {T,N}
211+
midpnts = map(_midpoints, X)
212+
Δ(x::AbstractVector) = length(x) > 1 ? x[2] - x[1] : 1
213+
Δx = prod(Δ, X)
214+
interp = LinearInterpolation(X,Y)
215+
f(x) = interp(x...)
216+
return Δx*sum(f, product(midpnts...))
217+
end
218+
219+
function integrate(X::NTuple{N,AbstractRange}, Y::AbstractArray{T,N}, ::TrapezoidalEvenFast) where {T,N}
220+
midpnts = map(_midpoints, X)
221+
Δ(x::AbstractVector) = length(x) > 1 ? step(x) : 1
222+
Δx = prod(Δ, X)
223+
interp = LinearInterpolation(X,Y)
224+
f(x) = interp(x...)
225+
return Δx*sum(f, product(midpnts...))
197226
end
198227

199228

200229

230+
231+
#function integrate(X::Tuple{AbstractVector}, Y::AbstractVector{T}, M::IntegrationMethod) :: T where {T}
232+
# return integrate(X[1], Y, M)
233+
#end
234+
#"""
235+
# integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, method, cache=nothing)
236+
#
237+
#Given an n-dimensional grid of values, compute the total integral along each dim
238+
#"""
239+
#function integrate(X::NTuple{N,AbstractVector}, Y::AbstractArray{T,N}, M::IntegrationMethod) :: T where {T,N}
240+
# n = last(size(Y))
241+
# cache = Vector{T}(undef, n)
242+
# x = X[1:N-1]
243+
# @inbounds for i in 1:n
244+
# cache[i] = integrate(x, selectdim(Y,N,i), M)
245+
# end
246+
# return integrate(X[end], cache, M)
247+
#end
248+
249+
250+
201251
# cumulative integrals
202252

203253
"""

0 commit comments

Comments
 (0)