@@ -46,26 +46,20 @@ function cumul_integrate(x,y...) end
46
46
47
47
# implementation
48
48
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
-
57
49
"""
58
50
integrate(x::AbstractVector, y::AbstractVector, ::Trapezoidal)
59
51
60
52
Use Trapezoidal rule. This is the default when no method is supplied.
61
53
"""
62
54
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 ())
69
63
end
70
64
71
65
"""
74
68
Use Trapezoidal rule, assuming evenly spaced vector x.
75
69
"""
76
70
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 ())
79
76
end
80
77
81
78
"""
84
81
Use Trapezoidal rule. Unsafe method: no bound checking.
85
82
"""
86
83
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 ])
90
87
end
91
88
return HALF * retval
92
89
end
90
+ function integrate (x:: AbstractRange , y:: AbstractVector , :: TrapezoidalFast )
91
+ return integrate (x, y, TrapezoidalEvenFast ())
92
+ end
93
93
94
94
"""
95
95
integrate(x::AbstractVector, y::AbstractVector, ::TrapezoidalEvenFast)
96
96
97
97
Use Trapezoidal rule, assuming evenly spaced vector x. Unsafe method: no bound checking.
98
98
"""
99
99
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 ]))
104
108
end
105
- @inbounds return (x[2 ] - x[1 ]) * (retval + HALF* y[1 ] + HALF* y[end ])
106
109
end
107
110
108
111
"""
@@ -111,12 +114,10 @@ end
111
114
Use Simpson's rule, assuming evenly spaced vector x.
112
115
"""
113
116
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 ())
120
121
end
121
122
122
123
"""
125
126
Use Simpson's rule, assuming evenly spaced vector x. Unsafe method: no bound checking.
126
127
"""
127
128
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 )
132
132
retval += y[i]
133
133
end
134
134
@inbounds return (x[2 ] - x[1 ]) * retval
@@ -256,12 +256,14 @@ end
256
256
Use Trapezoidal rule. This is the default when no method is supplied.
257
257
"""
258
258
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 ())
265
267
end
266
268
267
269
"""
@@ -271,11 +273,9 @@ Use Trapezoidal rule, assuming evenly spaced vector x.
271
273
"""
272
274
function cumul_integrate (x:: AbstractVector , y:: AbstractVector , :: TrapezoidalEven )
273
275
@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 ())
279
279
end
280
280
281
281
"""
@@ -284,10 +284,16 @@ end
284
284
Use Trapezoidal rule. Unsafe method: no bound checking.
285
285
"""
286
286
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 ])
290
295
end
296
+
291
297
return HALF * retarr
292
298
end
293
299
@@ -316,12 +322,16 @@ end
316
322
# default behaviour
317
323
integrate (x:: AbstractVector , y:: AbstractVector ) = integrate (x, y, Trapezoidal ())
318
324
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
320
328
321
329
integrate (X:: NTuple , Y:: AbstractArray ) = integrate (X, Y, Trapezoidal ())
322
330
323
331
cumul_integrate (x:: AbstractVector , y:: AbstractVector ) = cumul_integrate (x, y, Trapezoidal ())
324
332
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
326
336
327
337
end # module
0 commit comments