I have a complex Maple expression which is in this form:
expr := Sum(f(x, t, n), n=1...N);
To numerically evaluate this in Maple for any x
and t
, I might write
result := (x_, t_) -> value(subs(x=x_, t=t_, N=1000, expr));
result(0.5, 2.0); # some number
However, especially for large N
, this computation is very expensive. How can I speed up result(x, t)
?
I have tried using Compiler:-Compile
, but the functions subs
and value
have no analogue in C code, so this fails. (Compiler:-Compile(result);
gives an error message: Warning, the function names {subs, value} are not recognized in the target language
.)
How can I transform result
so that it may be compiled and evaluated faster, without having to manually rewrite the Sum
as for-loop inside a procedure? I can’t reimplement it from scratch because expr
is generated symbolically and I don’t want to lose generality.
Thank you.
By wrapping the actual call of procedure result
below within a call to evalf
we instruct Maple to try its evalf/Sum
technique of numeric summation convergence acceleration (via Levin-u transformation). This is quick in the case that the trailing terms' contribution is estimated as dropping off quick "enough".
restart;
# for an example
f := (x,t,n)->sin((x-t)/n*Pi):
expr := Sum(f(x, t, n), n=1...N):
result1 := unapply( expr, [x,t,N] ):
evalf(result1( 2.0, 0.1, 10000 ));
46.91622734
The procedure result2
below uses add
instead of sum
. Your original approach of applying the value
command to the inert Sum
would produce an active sum
call, which -- on every invocation, and for each set of passed arguments -- would likely end up causing slow and unnecessary, unsuccessful attempts at symbolic summation before falling back to merely adding up the terms numerically.
By simply replacing the inert Sum
with the much more appropriate add
command we can bypass all such repeated, failing, and wasted attempts at symbolic summation and go straight to the job of numerically adding up all the terms.
result2 := unapply( subs(Sum=add,expr), [x::float,t::float,N::integer] ):
result2( 2.0, 0.1, 10000 );
46.91622733
If the expression expr
is evalhf'able then (since add
is too) we can instead do the numerical adding of all the terms under Maple's faster double-precision floating-point evaluation mechanism.
evalhf(result1( 2.0, 0.1, 10000 ));
46.9162273272279222