Where your exposition differs from my algorithm is that you are making ##du_k## dependent on ##z## whereas in my algorithm ##the step size ##du## is selected at the beginning by a loop (
'while x > max_dp') that selects it to be small enough that ##f(u)du<\textit{max_dp}## for some pre-set tolerance
max_dp. Perhaps the algorithm can be done with varying increments but it would make things unnecessarily complex.
Define a function
simp that is given an odd number of consecutive values of a function at evenly spaced increments
du, and returns the Simpson's Rule estimate of the integral of the function over the relevant interval.
Then define another function
x_simp (Extended Simpson) that is given
any finite number of values of the function and estimates the integral as:
- zero if there is only one value
- simp applied to those values if there is an odd number of values
- the trapezoidal integral for the first incremental volume, added to simp applied to the odd sequence of values obtained by dropping the first one, if there's a nonzero, even number of values
Let the practical support of ##f## be ##[0,\textit{max_lim})##, so that we can ignore the probability of ##U## exceeding
max_lim. Then we define
M to be
max_lim / du rounded up to the next integer. At each nesting level
k, we will estimate ##F_{Z_k}(u)## for ##u\in\{0, du, ...,M\,du\}##. The elements of this estimate make up a vector ##(A_0^k, ..., A_M^k)##, and we can calculate this directly for ##k=1## as ##A_r^k=F_U(r\, du)##.
Then for ##k>1## and natural number ##j\le M## we have:
$$F_{Z_k}(j\,du) =
\int_0^z F_{Z_{k-1}}(z-j\,du)f_U(j\,du)\,du
\approx
\textit{x_simp}(A_0^{k-1}f_U(j\,du), A_1^{k-1}f_U((j-1)du), ..., A_{j-1}^{k-1}f_U(du), A_j^{k-1}f_U(0))
$$
Note how we store in the vector of ##A^{k-1}_r##s all the information we'll need later about ##F_{Z_{k-1}}## when we do level ##k-1##. Then we use that, together with the values of ##f_U## at multiples of ##du##, to calculate the next set of ##A^k_r##s.
So no recursive expansions are ever needed. In your post you've done a recursive expansion over two levels, so that your last formula contains both ##u_2## and ##u_3##. Rather than recursively expanding, we just access the
A values from teh previous level and use them in the Simpson integration estimate.
I hope that's clearer.
As I recall, the recursive version in R ran in about 3 mins 30, while the new version runs in about seven seconds, so the speed-up factor is about thirty. That's because the recursive version, at levels below the top one, is always redoing calcs that have already been done, whereas this approach avoids that.