# How to optimize the following function?

Consider the following function:

 function[x_, y_] = If[x < Exp[y], Sqrt[1 - x/Exp[y]], 0];
functionTotal1[x_] = Sum[function[x, 0.02*j], {j, 0, 4*10^5, 1}];


Calling this function is very slow:

AbsoluteTiming[functionTotal1[2]]


gives 1.5 seconds. This is probably related to If condition. What is a possible way to make calling faster, apart from making an interpolation?

• If you have a multicore CPU you can use ParallelSum. – vi pa Dec 20 '19 at 10:45

Using Ramp and vectorized operations:

y = -.02 Range[0, 4 10^5];
Total @ Sqrt[Ramp[1 - 2 Exp[y]]] //AbsoluteTiming


{0.018728, 399935.}

• H o l y c o w ! :-) – Mr.Wizard Dec 20 '19 at 1:27

On my machine

function[x_, y_] := If[x < Exp[y], Sqrt[1 - x/Exp[y]], 0];
functionTotal1[x_] := Sum[function[x, 0.02*j], {j, 0, 4*10^5, 1}];
RepeatedTiming[functionTotal1[2]]


{6.631, 399935.}

Here are a few things that I noticed that speed up evaluation.

# Each term is real or imaginary

First we see that if $$x \leq \exp(y)$$, then $$\sqrt{1-x e^{-y}}$$ is real, and if $$x > \exp(y)$$, then $$\sqrt{1-x e^{-y}}$$ is strictly imaginary. Therefore, if we get rid of the If and ignore all the imaginary terms (effectively setting each term where $$x > \exp(y)$$ to zero)

f[x_, y_] := Sqrt[1 - x/Exp[y]]
ftot[x_] := Re@Sum[f[x, 0.02*j], {j, 0., 4.*10^5}]
RepeatedTiming[ftot[2]]


{5.3, 399935.}

# Vectorization and packed arrays

With the thought of restructuring the Sum into a Dot to utilize vectorization, we rewrite the term $$\sqrt{1-x e^{-y}}$$ into a product of terms as $$e^{-y/2} \sqrt{e^y-x}$$. Then, skipping the declaration of the "term" function, the sum can be written as

ftotdot[x_] := Dot @@ (Transpose@Table[{Exp[-0.02 y/2], Sqrt[Exp[0.02 y] - x]}, {y, 0., 4.*10^5}]) // Re
ftotdot[2] // RepeatedTiming


{2.91, 399935.}

Then, since Exp and arithmetic operators are vectorized we can replace the Table with an evaluation of the packed array in Range.

ftotdot2[x_] := Exp[-#/2].Sqrt[Exp[#] - x] &[0.02 Range[0., 4.*10^5]]) // Re
ftotdot2[2] // RepeatedTiming


{2.3, 399935.}

Further improvements may include the use of SparseArrays, Compile, even just parallelization.