# How to optimize this code?

I am implementing a code that works correctly but it takes too much time. I did not see how to optimize it to be run quickly. Here is my code:

data=RandomInteger[{1,400},{5000,2}];
c=10;
r=60;

pts=c + r {Cos[#], Sin[#]} & /@ Range[0, 2 π, 2 π/16];

newCoord = Table[(# - pts[[i]]) & /@ data, {i, 1, Length@pts}];

PolarCoords = Table[ToPolarCoordinates[#] & /@ newCoord[[i]] /.
{x_, y_} /; y < 0 -> {x, y + 2 π}, {i, 1, Length@pts}]; // AbsoluteTiming

(* {8.59775, Null} *)


I am running my code Mac OS X processor, Core i7 and RAM 8 GB.

• Can you give us more info about what this does? You're generating points from some distribution. I don't know what it is. Jan 18 '16 at 19:58
• The problem is not about distribution. The variable "data" is pixels coordinates of an image. Jan 18 '16 at 20:12

Most of your time is spent in defining PolarCoords. Let's take a look at your code.

It looks like you've tried to optimize it already. Let's try to simplify it first:

PolarCoords =
Map[Function[i,
ToPolarCoordinates /@
newCoord[[i]] /. {x_, y_} /; y < 0 -> {x, y + 2 \[Pi]}],
Range@Length@pts]


Simpler:

PolarCoords =
Map[Function[i, ToPolarCoordinates /@ newCoord[[i]]],
Range@Length@pts] /. {x_, y_} /; y < 0 -> {x, y + 2 \[Pi]}


Simpler:

PolarCoords =
Map[ToPolarCoordinates, newCoord] /. {x_, y_} /; y < 0 -> {x, y + 2 \[Pi]}


And even simpler since ToPolarCoodrindates doesn't need to be mapped:

PolarCoords =
ToPolarCoordinates[newCoord] /. {x_, y_} /; y < 0 :> {x, y + 2 \[Pi]}


This code above is helpful. It helps me understand what the line is supposed to do. You wanted to first run ToPolarCoordinates over every point and then shift them right by 2Pi if y is negative.

In large vectorized computations, conditionals can be a problem. You can replace the condition with:

{x_, y_} :> {x, Mod[y, 2 Pi]}


Which does what I think you intended. So if I wanted to make this run fast, I would probably combine the two operations into one function:

f[{x_, y_}] := {Sqrt[x^2 + y^2], Mod[ArcTan[x, y], 2 Pi]}
g[coord_] := Map[f, coord_, {2}]


And then I could use either use Compile to make a compiled version of g or use ParallelMap.

• Without compiling, you might consider this, which is about 2x as fast it seems: PolarCoords = newCoord /. {x_, y_} :> {Sqrt[x^2 + y^2], Mod[ArcTan[x, y], N[2 [Pi]]]}; Jan 18 '16 at 20:33
• I want to note that typically, you use a different formula for the hypotenuse, for numerical stability. Maybe you should use Norm instead. Jan 18 '16 at 20:35

If you use float instead integer you can reduce the computing time.

  data = RandomInteger[{1, 400}, {5000, 2}];
c = 10.;
r = 60.;

pts = c + r {Cos[#], Sin[#]} & /@ Range[0., 2. π, 2. π/16.];

newCoord = Table[(# - pts[[i]]) & /@ data, {i, 1, Length@pts}];

PolarCoords =
Table[ToPolarCoordinates[#] & /@
newCoord[[i]] /. {x_, y_} /; y < 0 -> {x, y + 2 π}, {i, 1,
Length@pts}]; // AbsoluteTiming

• Thanks, but it still takes times 2.16 seconds. I have a big data set. Jan 18 '16 at 17:21
• To bring the timing down still you could use data2=RandomReal[{1, 400}, {5000, 2}]; instead of data with random Integers. On my machine this halves the time taken yet again. Jan 18 '16 at 18:48
• @Sascha, in my real code data is already Real. it takes about 1.62 s Jan 18 '16 at 19:00
• @Developer2000, you might consider replacing the symbolic Pi with its numeric value, which I just tested can have a 2x speedup. Feb 22 '16 at 21:38