10

I need to get Mathematica to evaluate the logarithm of a negative real number using the lower branch instead of the upper branch, so that while

In[1]:=   Log[3.2]
Out[1]:=  1.16315

I need

In[2]:=   Log[-3.2]
Out[2]:=  1.16315 - 3.14159 I

and not

Out[2]:=  1.16315 + 3.14159 I

I have already defined my own function loopLog that does this:

loopLog[x_: NumericQ] = If[Element[x,Reals], Conjugate[Log[x]]];

But I am not able to get it to perform any of the usual simplifications or manipulations using this function. For example, when I want to differentiate loopLog, I get

In[3]:=   D[loopLog[x],x]
Out[3]:=  If[x \[Element] Reals, Derivative[1][Conjugate][Log[x]]/x]

Instead of the much needed 1/x. What is the cleanest way to define such a logarithm function in Mathematica?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
QuantumDot
  • 19,601
  • 7
  • 45
  • 121
  • 1
    x_: NumericQ this is a pattern that matches anything, but defaults to the symbol NumericQ if no argument is given. You surely meant x_?NumericQ – Rojo Dec 26 '12 at 09:46
  • 2
    Would be nice with some $BranchCut global variable that affects ArcTan and the rest as well, even nicer if it could be set to an arbitrary curve. – ssch Dec 26 '12 at 13:14
  • @Rojo Yes, bad programing on my part. It should have been x_?NumericQ – QuantumDot Dec 26 '12 at 17:14
  • 2
    @ssch: Well, inspired by whuber's answer, here's a Log with a branch cut along any curve of the form $z = re^{i\theta(r)}$: branchLog[z_, \[Theta]_] := With[{r = Abs[z]}, Log[z/Exp[I \[Theta][r]]] + I \[Theta][r]]. Then for ArcTan you can do ExpToTrig[TrigToExp@ArcTan[z] /. Log[z_] -> branchLog[z, \[Theta]]]... –  Dec 27 '12 at 05:30
  • Sorry, the branch is actually along $z=-re^{i\theta(r)}$. –  Dec 27 '12 at 11:06

2 Answers2

15

The question asks for a "cleanest way." Arguably, any solution that reduces the calculation to various cases is not very clean, and is probably inefficient too. These considerations suggest a simple, direct approach:

log0[x_] := -Log[1/x]

Checking a few cases (or a plot) easily confirms that log0 does what is intended with negative real numbers; e.g.,

log0[-3.2]

1.16315 - 3.14159 I

Moreover, it does not change the behavior for any other complex numbers, as a contour plot of its imaginary part demonstrates:

ContourPlot[Chop[Im[Log[x + I y]] -  Im[log0[x + I y]]], {x, -2, 2}, {y, -2, 2},
  PlotPoints -> 100] 

Contour plot

Operators therefore produce the expected results:

D[log0[x], x]

$\frac{1}{x}$

Integrate[x log0[x], {x, -1, 1}]

$\frac{i \pi }{2}$

whuber
  • 20,544
  • 2
  • 59
  • 111
3

I never did this before (i.e. modify system function), but I just tried it, and it seems to work. But I just wanted to first say, that Log[z] as it works in Mathematica is the correct way. i.e. Log[z]=Log[Abs[z]]+k where k=0 when z>0 and k=I*Pi when z<0 so what you are asking to do is not the correct math way. But this is what I tried to change the definition

Log[-3.2]
(*1.1631508098056809 + 3.141592653589793*I*)

Unprotect[Log]
Log[x_?(Element[#, Reals] && # < 0 &)] := Log[Abs[x]] - I*Pi
Protect[Log]
Log[-3.2]
(*  1.1631508098056809 - 3.141592653589793*I  *)

and

Log[3.2]
(*  1.1631508098056809  *)

btw, the reason your D[loopLog[x],x] command did not work, is because you defined your function to accept only numerical x, but you are now taking derivative w.r.t x ? I do not think this will work.

Nasser
  • 143,286
  • 11
  • 154
  • 359
  • 6
    "What you are asking to do is not the correct math way." They're just taking a slightly different branch cut from the usual one; it's hardly incorrect. There can be more than one right way in mathematics! :) –  Dec 26 '12 at 11:46
  • 2
    _?(Element[#, Reals] && # < 0 &) can simply be written as _?Negative :) – rm -rf Dec 26 '12 at 17:33
  • @NasserM.Abbasi Negative and Positive were introduced in version 1, when such conventions were probably not codified. At this point, it is probably left that way for backwards compatibility. – rm -rf Dec 26 '12 at 20:34