In MATLAB there's a function called phase
that is just like our Listable
friend Arg
, but that, when evaluated with a list, it tries to keep the result "continuous", allowing itself to return values outside the [-Pi, Pi]
range. So, for example, sampling a complex exponential
vec = E^(I 2 π #/10) & /@ Range[100];
resMMA = Arg[vec] // N;
The red line is Mathematica's result with Arg
, and the blue line is MATLAB's with phase
So, I want to implement a function that does a good job at allowing you to see phase properties such as "linearity", more easily, like phase
, in Mathematica.
Ideally, it should also work on some symbolic functions and not only lists, but what's more important to me is for it to work as good as possible on lists.
My attempt at the "list version" is very simple, but seems to be working reasonably, and fast. I also tested it with a function that's positive and negative, like
vec2 = E^(I 2 Pi/16. #) Sinc[2 Pi #/20.] & /@ Range[100];
Here's the code
phase = Compile[{{l, _Complex, 1}},
FoldList[
Function[{prev, new}, # + Round[prev - #, 2 Pi] &@Arg@new],
Arg@First@l, Rest@l],
CompilationTarget -> "C", RuntimeOptions -> "Speed"];
Any improvements, would be appreciated. For example, it would probably be better if it could look at more than just the nearest neighbouring point, to be more robust to an occasional noise. I'd also appreciate ideas on how to achieve something analogous for a continuous well-behaved, not-created-by-mathematicians-just-to-prove-people-wrong symbolic function?
Plot3D
. It'd be needed for example when solving a Schrodinger equation and plottingArg
of wave-function versus time and space. $\endgroup$phase[vec_?VectorQ] := Module[{n = Length[vec], ph = Arg[vec], df}, df = Differences[ph]; Do[ph -= 2 Pi Sign[df[[k]]] PadRight[ConstantArray[0, k], n, 1], {k, Flatten[Position[Abs[df], _?(# > Pi &)]]}]; ph]
$\endgroup$