Skip to content

Commit 8346f9b

Browse files
authored
Use specialized methods for ranges (#26)
* Use specialized methods for ranges and avoid initializations with zeros * Update Travis configuration
1 parent c39942b commit 8346f9b

File tree

2 files changed

+65
-59
lines changed

2 files changed

+65
-59
lines changed

.travis.yml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@ os:
66
julia:
77
- 1.2
88
- 1.3
9-
- 1.4
9+
- 1
1010
- nightly
1111
notifications:
1212
email: false
13-
# uncomment the following lines to override the default test script
14-
#script:
15-
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
16-
# - julia -e 'Pkg.clone(pwd()); Pkg.build("NumericalIntegration"); Pkg.test("NumericalIntegration"; coverage=true)'
1713
after_success:
18-
# push coverage results to Coveralls
19-
- julia -e 'cd(Pkg.dir("NumericalIntegration")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
20-
# push coverage results to Codecov
21-
- julia -e 'cd(Pkg.dir("NumericalIntegration")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
14+
- if [[ $TRAVIS_JULIA_VERSION = 1 ]] && [[ $TRAVIS_OS_NAME = linux ]]; then
15+
julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())';
16+
julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder())';
17+
fi

src/NumericalIntegration.jl

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -46,26 +46,20 @@ function cumul_integrate(x,y...) end
4646

4747
#implementation
4848

49-
function _zero(x,y)
50-
ret = zero(eltype(x)) + zero(eltype(y))
51-
end
52-
53-
function _zeros(x::AbstractVector,y::AbstractVector)
54-
ret = zeros(eltype(x),size(x)) + zeros(eltype(y),size(y))
55-
end
56-
5749
"""
5850
integrate(x::AbstractVector, y::AbstractVector, ::Trapezoidal)
5951
6052
Use Trapezoidal rule. This is the default when no method is supplied.
6153
"""
6254
function integrate(x::AbstractVector, y::AbstractVector, ::Trapezoidal)
63-
@assert length(x) == length(y) "x and y vectors must be of the same length!"
64-
retval = _zero(x,y)
65-
for i in 1 : length(y)-1
66-
retval += (x[i+1] - x[i]) * (y[i] + y[i+1])
67-
end
68-
return HALF * retval
55+
n = length(x)
56+
length(x) == length(y) || error("x and y vectors must be of the same length!")
57+
n 2 || error("vectors must contain at least two elements")
58+
59+
return integrate(x, y, TrapezoidalFast())
60+
end
61+
function integrate(x::AbstractRange, y::AbstractVector, ::Trapezoidal)
62+
return integrate(x, y, TrapezoidalEven())
6963
end
7064

7165
"""
@@ -74,8 +68,11 @@ end
7468
Use Trapezoidal rule, assuming evenly spaced vector x.
7569
"""
7670
function integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalEven)
77-
@assert length(x) == length(y) "x and y vectors must be of the same length!"
78-
return (x[2] - x[1]) * (HALF * (y[1] + y[end]) + sum(y[2:end-1]))
71+
n = length(x)
72+
length(y) == n || error("x and y vectors must be of the same length!")
73+
n 2 || error("vectors must contain at least two elements")
74+
75+
return integrate(x, y, TrapezoidalEvenFast())
7976
end
8077

8178
"""
@@ -84,25 +81,31 @@ end
8481
Use Trapezoidal rule. Unsafe method: no bound checking.
8582
"""
8683
function integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalFast)
87-
retval = _zero(x,y)
88-
@fastmath @simd for i in 1 : length(y)-1
89-
@inbounds retval += (x[i+1] - x[i]) * (y[i] + y[i+1])
84+
@inbounds retval = (x[2] - x[1]) * (y[1] + y[2])
85+
@inbounds @fastmath @simd for i in 2:(length(y) - 1)
86+
retval += (x[i+1] - x[i]) * (y[i] + y[i+1])
9087
end
9188
return HALF * retval
9289
end
90+
function integrate(x::AbstractRange, y::AbstractVector, ::TrapezoidalFast)
91+
return integrate(x, y, TrapezoidalEvenFast())
92+
end
9393

9494
"""
9595
integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalEvenFast)
9696
9797
Use Trapezoidal rule, assuming evenly spaced vector x. Unsafe method: no bound checking.
9898
"""
9999
function integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalEvenFast)
100-
retval = _zero(x,y)
101-
N = length(y) - 1
102-
@fastmath @simd for i in 2 : N
103-
@inbounds retval += y[i]
100+
if length(x) < 3
101+
@inbounds return HALF * (x[2] - x[1]) * (y[1] + y[2])
102+
else
103+
@inbounds retval = y[2]
104+
@inbounds @fastmath @simd for i in 3:(length(y) - 1)
105+
retval += y[i]
106+
end
107+
@inbounds return (x[2] - x[1]) * (retval + HALF * (y[1] + y[end]))
104108
end
105-
@inbounds return (x[2] - x[1]) * (retval + HALF*y[1] + HALF*y[end])
106109
end
107110

108111
"""
@@ -111,12 +114,10 @@ end
111114
Use Simpson's rule, assuming evenly spaced vector x.
112115
"""
113116
function integrate(x::AbstractVector, y::AbstractVector, ::SimpsonEven)
114-
@assert length(x) == length(y) "x and y vectors must be of the same length!"
115-
retval = (17*y[1] + 59*y[2] + 43*y[3] + 49*y[4] + 49*y[end-3] + 43*y[end-2] + 59*y[end-1] + 17*y[end]) / 48
116-
for i in 5 : length(y) - 1
117-
retval += y[i]
118-
end
119-
return (x[2] - x[1]) * retval
117+
length(x) == length(y) || error("x and y vectors must be of the same length!")
118+
length(x) 4 || error("vectors must contain at least 4 elements")
119+
120+
return integrate(x, y, SimpsonEvenFast())
120121
end
121122

122123
"""
@@ -125,10 +126,9 @@ end
125126
Use Simpson's rule, assuming evenly spaced vector x. Unsafe method: no bound checking.
126127
"""
127128
function integrate(x::AbstractVector, y::AbstractVector, ::SimpsonEvenFast)
128-
@inbounds retval = 17*y[1] + 59*y[2] + 43*y[3] + 49*y[4]
129-
@inbounds retval += 49*y[end-3] + 43*y[end-2] + 59*y[end-1] + 17*y[end]
130-
retval /= 48
131-
@fastmath @inbounds for i in 5 : length(y)-1
129+
@inbounds retval = (17 * (y[1] + y[end]) + 59 * (y[2] + y[end-1]) +
130+
43 * (y[3] + y[end-2]) + 49 * (y[4] + y[end-3])) / 48
131+
@fastmath @inbounds for i in 5:(length(y) - 4)
132132
retval += y[i]
133133
end
134134
@inbounds return (x[2] - x[1]) * retval
@@ -256,12 +256,14 @@ end
256256
Use Trapezoidal rule. This is the default when no method is supplied.
257257
"""
258258
function cumul_integrate(x::AbstractVector, y::AbstractVector, ::Trapezoidal)
259-
@assert length(x) == length(y) "x and y vectors must be of the same length!"
260-
retarr = _zeros(x,y)
261-
for i in 2 : length(y)
262-
retarr[i] = retarr[i-1] + (x[i] - x[i-1]) * (y[i] + y[i-1])
263-
end
264-
return HALF * retarr
259+
n = length(x)
260+
@assert length(y) == n "x and y vectors must be of the same length!"
261+
n 2 || error("vectors must contain at least two elements")
262+
263+
return cumul_integrate(x, y, TrapezoidalFast())
264+
end
265+
function cumul_integrate(x::AbstractRange, y::AbstractVector, ::Trapezoidal)
266+
return cumul_integrate(x, y, TrapezoidalEven())
265267
end
266268

267269
"""
@@ -271,11 +273,9 @@ Use Trapezoidal rule, assuming evenly spaced vector x.
271273
"""
272274
function cumul_integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalEven)
273275
@assert length(x) == length(y) "x and y vectors must be of the same length!"
274-
retarr = _zeros(x,y)
275-
for i in 2 : length(y)
276-
retarr[i] = retarr[i-1] + (y[i-1] + y[i])
277-
end
278-
return (x[2] - x[1]) * HALF * retarr
276+
n 2 || error("vectors must contain at least two elements")
277+
278+
return cumul_integrate(x, y, TrapezoidalEvenFast())
279279
end
280280

281281
"""
@@ -284,10 +284,16 @@ end
284284
Use Trapezoidal rule. Unsafe method: no bound checking.
285285
"""
286286
function cumul_integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalFast)
287-
retarr = _zeros(x,y)
288-
@fastmath for i in 2 : length(y) #not sure if @simd can do anything here
289-
@inbounds retarr[i] = retarr[i-1] + (x[i] - x[i-1]) * (y[i] + y[i-1])
287+
# compute initial value
288+
@inbounds init = (x[2] - x[1]) * (y[1] + y[2])
289+
retarr[i] = Vector{typeof(init)}(undef, n)
290+
retarr[1] = init
291+
292+
# for all other values
293+
@inbounds @fastmath for i in 2:n # not sure if @simd can do anything here
294+
retarr[i] = retarr[i-1] + (x[i] - x[i-1]) * (y[i] + y[i-1])
290295
end
296+
291297
return HALF * retarr
292298
end
293299

@@ -316,12 +322,16 @@ end
316322
#default behaviour
317323
integrate(x::AbstractVector, y::AbstractVector) = integrate(x, y, Trapezoidal())
318324

319-
integrate(x::AbstractVector, y::AbstractMatrix; dims=2) = integrate(x, y, Trapezoidal(); dims=dims)
325+
function integrate(x::AbstractVector, y::AbstractMatrix; kwargs...)
326+
return integrate(x, y, Trapezoidal(); kwargs...)
327+
end
320328

321329
integrate(X::NTuple, Y::AbstractArray) = integrate(X, Y, Trapezoidal())
322330

323331
cumul_integrate(x::AbstractVector, y::AbstractVector) = cumul_integrate(x, y, Trapezoidal())
324332

325-
cumul_integrate(x::AbstractVector, y::AbstractMatrix; dims=2) = cumul_integrate(x, y, Trapezoidal(); dims=dims)
333+
function cumul_integrate(x::AbstractVector, y::AbstractMatrix; kwargs...)
334+
return cumul_integrate(x, y, Trapezoidal(); kwargs...)
335+
end
326336

327337
end # module

0 commit comments

Comments
 (0)