7
$\begingroup$

I'm defining branch cut functions, and I'm using $\arg(z)$ as a building block. So I just spent an hour at the whiteboard assuming that $\arg(z)$ goes from $0$ to $2\pi$, and then I implement the code, and everything goes horribly wrong.

I just realized that the problem is that the the Arg function built into Mathematica goes from $-\pi$ to $\pi$. Is there anyway I can redefine Arg so that my code will work?

$\endgroup$
5
  • 6
    $\begingroup$ arg[z_] /; Im[z] < 0 := Arg[z] + 2 Pi; arg[z_] /; Im[z] >= 0 := Arg[z] $\endgroup$
    – Artes
    Commented Apr 12, 2014 at 17:31
  • 1
    $\begingroup$ See also the arg I use here. $\endgroup$
    – Jens
    Commented Apr 12, 2014 at 18:10
  • $\begingroup$ See also this answer How to calculate contour integrals with Mathematica? regarding closely related branch cuts. $\endgroup$
    – Artes
    Commented Apr 12, 2014 at 18:22
  • 1
    $\begingroup$ RELATED $\endgroup$ Commented Apr 12, 2014 at 20:53
  • 4
    $\begingroup$ arg[z_] := Pi+ArcTan[Re[z],Im[z]] $\endgroup$ Commented Apr 13, 2014 at 19:15

3 Answers 3

3
$\begingroup$

Let me test several versions of the redefined arg:

x = RandomComplex[{-1 - I, 1 + I}, 1000000];

arg1[x_] := Mod[Arg@x, 2 π];
arg2[x_] := Arg[-x] + π;
arg3[z_] := π + ArcTan[-Re[z], -Im[z]];

Max[Abs[arg1[x] - arg2[x]], Abs[arg1[x] - arg3[x]]]
(* 8.88178*10^-16 *)

arg1[x]; // AbsoluteTiming
(* {0.16715, Null} *)

arg2[x]; // AbsoluteTiming
(* {0.154602, Null} *)

arg3[x]; // AbsoluteTiming
(* {0.090001, Null} *)

It is surprising to me that ArcTan works sufficiently faster then Arg.

However, I do not recommend to redefine the build-in Arg. Sometimes it works

Block[{Arg = arg3}, Arg[Exp[-I]]]
(* -1 + 2 π *)

and sometimes not (why?)

Block[{Arg = arg3}, Plot[Arg@Exp[I φ], {φ, -2 π, 2 π}]] 

enter image description here

$\endgroup$
3
  • 2
    $\begingroup$ The Block thing is an issue with the way Compile is used on the expression being plotted. You can fix it by setting the (undocumented?) Compiled option for Plot to False, or by moving the Block into the Plot statement. Either way, I think it's probably a bug and definitely worth a question of its own.... $\endgroup$
    – Pillsy
    Commented Nov 12, 2015 at 18:23
  • $\begingroup$ Did you copy the timings correctly? On my machine Mac OS X 10.11, ArcTan is definitely slower than Arg in Mathematica 10.4, 10.3, 9.0 and 8.0.4. On 10.3 they timings are {0.016644, 0.025684, 0.090886} on my machine. $\endgroup$
    – QuantumDot
    Commented Apr 13, 2016 at 18:55
  • $\begingroup$ @QuantumDot Yes, I obtain almost the same timings in v9 and {0.10717, 0.087667, 0.10717} in v10.3. The ratios between timings can be machine specific. I tested on my old laptop with Core 2 Duo under Linux. $\endgroup$
    – ybeltukov
    Commented Apr 13, 2016 at 20:35
2
$\begingroup$

EDIT: See comment below by Daniel, his answer is better. I shied away from using ArcTan[] because the previous comments mentioned problems with it, but it seems to work fine... Also I have since noticed a problem with my version where pure reals also get a shift.

My previous comment:

So I stumbled upon this thead looking for the same answer as OP. While the answers here work, they are orders of magnitude slower than using the built in Arg[]. This is what I could come up with to solve my problem:

argVec[zVec_] := Module[{imShift},
 imShift = Unitize[(Sign /@ Im[zVec] - 1)]*(2π//N);
 Arg[zVec] + imShift];

This is only about 2x slower than the Arg[] function and it was the best I could come up with. I built it specifically to work with lists, just like Arg[], but it works just as well with scalars. The //N is needed to maintain the speed since my input zVec is machine precision, and I want machine precision output, however you can remove the //N and you will also get integer output for integer input, at the cost of speed.

Cheers!

$\endgroup$
1
  • 2
    $\begingroup$ Somewhat faster using Mod: Mod[ArcTan[Re[z], Im[z]], 2.*Pi]. $\endgroup$ Commented Feb 20, 2018 at 16:00
0
$\begingroup$

From a comment by Artes, this seemed to solve the problem for the OP:

arg[z_] /; Im[z] < 0 := Arg[z] + 2 Pi; arg[z_] /; Im[z] >= 0 := Arg[z]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.