home *** CD-ROM | disk | FTP | other *** search
-
- (* ****************************************************************
- *
- * ComplexExpand, Kelly Roach and Roman Maeder, V2.0
- *
- ***************************************************************** *)
-
- BeginPackage["System`ComplexExpand`"]
-
- (*
- This is not too dangerous since the System`ComplexExpand` context is removed at the end
- *)
-
- Off[ General::shdw]
-
- Unprotect[ ComplexExpand, TargetFunctions, AbsExpr, ArgExpr, ConjugateExpr,
- ReImExpr, SignExpr]
-
- Map[ Clear, {ComplexExpand, TargetFunctions, AbsExpr, ArgExpr, ConjugateExpr,
- ReImExpr, SignExpr}]
-
-
- (* ****************************************************************
- *
- * Rigorous Definitions Of The Elementary Inverse Functions
- *
- *Definitions:
- *
- *(1) Log[z_]:=If[And[SameQ[Im[z],0],Re[z]<0],Log[-z]+Pi*I,Log[z]]
- *(2) Power[u_,v_]:=E^(v*Log[u])
- *(3) Sqrt[z_]:=Power[z,1/2]
- *(4) ArcSin[z_]:=-I*Log[I*z+Sqrt[1-z^2]]
- *(5) ArcCos[z_]:=Pi/2-ArcSin[z]
- *(6) ArcTan[z_]:=-I*Log[(1+I*z)/Sqrt[1+z^2]]
- * ArcTan[u_,v_]:=-I*Log[(u+I*v)/Sqrt[u^2+v^2]]
- *(7) ArcCsc[z_]:=ArcSin[1/z]
- *(8) ArcSec[z_]:=ArcCos[1/z]
- *(9) ArcCot[z_]:=If[SameQ[z,0],Pi/2,ArcTan[1/z]]
- *(10) ArcSinh[z_]:=Log[z+Sqrt[1+z^2]]
- *(11) ArcCosh[z_]:=Log[z+(z+1)*Sqrt[(z-1)/(z+1)]]
- *(12) ArcTanh[z_]:=Log[(1+z)/Sqrt[1-z^2]]
- *(13) ArcCsch[z_]:=ArcSinh[1/z]
- *(14) ArcSech[z_]:=ArcCosh[1/z]
- *(15) ArcCoth[z_]:=If[SameQ[z,0],Pi*I/2,ArcTanh[1/z]]
- *
- *Branch Cuts:
- *
- *(1) Log
- * (-Infinity,0) attaches to quadrant II.
- * Im[Log[z]] == Pi for z in (-Infinity,0)
- *(2) Power (Considering Power for constant v.)
- * (-Infinity,0) attaches to quadrant II, for u not an integer.
- * Power[u,v] == (-u)^v*(Cos[v]+I*Sin[v]) for v in (-Infinity,0)
- *(3) Sqrt
- * (-Infinity,0) attaches to quadrant II.
- * Sign[Im[Sqrt[z]]] > 0 for z in (-Infinity,0)
- *(4) ArcSin
- * (-Infinity,-1) attaches to quadrant II and (1,Infinity) to quadrant IV.
- * Re[ArcSin[z]] == -Pi/2 for z in (-Infinity,-1)
- * Re[ArcSin[z]] == Pi/2 for z in (1,Infinity)
- *(5) ArcCos
- * (-Infinity,-1) attaches to quadrant II and (1,Infinity) to quadrant IV.
- * Re[ArcCos[z]] == Pi for z in (-Infinity,-1)
- * Re[ArcCos[z]] == 0 for z in (1,Infinity)
- *(6) ArcTan
- * (-I*Infinity,-I) attaches to quadrant IV and (I,I*Infinity) to quadrant II.
- * Re[ArcTan[z]] == -Pi/2 for z in (-I*Infinity,-I)
- * Re[ArcTan[z]] == Pi/2 for z in (I,I*Infinity)
- *(7) ArcCsc
- * (-1,0) attaches to quadrant III and (0,1) to quadrant I.
- * Re[ArcCsc[z]] == -Pi/2 for z in (-1,0).
- * Re[ArcCsc[z]] == Pi/2 for z in (0,1).
- *(8) ArcSec
- * (-1,0) attaches to quadrant III and (0,1) to quadrant I.
- * Re[ArcSec[z]] == Pi for z in (-1,0).
- * Re[ArcSec[z]] == 0 for z in (0,1).
- *(9) ArcCot
- * (-I,0) attaches to quadrant III and (0,I) to quadrant I.
- * Re[ArcCot[z]] == Pi/2 for z in (-I,0).
- * Re[ArcCot[z]] == -Pi/2 for z in (0,I).
- *(10) ArcSinh
- * (-I*Infinity,-I) attaches to quadrant I and (I,I*Infinity) to quadrant III.
- * Im[ArcSinh[z]] == -Pi/2 for z in (-I*Infinity,-I)
- * Im[ArcSinh[z]] == Pi/2 for z in (I,I*Infinity)
- *(11) ArcCosh
- * (-Infinity,1) attaches to quadrants I and II.
- * Sign[Im[ArcCosh[z]]] > 0 for z in (-Infinity,1).
- *(12) ArcTanh
- * (-Infinity,-1) attaches to quadrant II and (1,Infinity) to quadrant IV.
- * Im[ArcTanh[z]]] == Pi/2 for z in (-Infinity,-1).
- * Im[ArcTanh[z]]] == -Pi/2 for z in (1,Infinity).
- *(13) ArcCsch
- * (-I,0) attaches to quadrant IV and (0,I) to quadrant I.
- * Sign[Re[ArcCsch[z]]] > 0 for z in (-I,0)
- * Sign[Re[ArcCsch[z]]] < 0 for z in (0,I)
- *(14) ArcSech
- * (-Infinity,0) attaches to quadrant III and (1,Infinity) to quadrant IV.
- * Sign[Im[ArcSech[z]]] > 0 for z in (-Infinity,0)
- * Sign[Im[ArcSech[z]]] > 0 for z in (1,Infinity)
- *(15) ArcCoth
- * (-1,0] attaches to quadrant III and (0,1) to quadrant I.
- * Im[ArcCoth[z]] == Pi/2 for z in (-1,0]
- * Im[ArcCoth[z]] == -Pi/2 for z in (0,1)
- ***************************************************************** *)
-
- (* ****************************************************************
- *
- * Useful Trigonometric Identities
- *
- * Sinh[X] == -I*Sin[I*X] == -Sinh[-X] == I*Sin[-I*X]
- * Cosh[X] == Cos[I*X] == Cosh[-X] == Cos[-I*X]
- * Tanh[X] == -I*Tan[I*X] == -Tanh[-X] == I*Tan[-I*X]
- * ArcSinh[X] == I*ArcSin[-I*X] == Log[X+Sqrt[1+X^2]]
- * Sin[X] == -I*Sinh[I*X] == -Sin[-X] == I*Sinh[-I*X]
- * Cos[X] == Cosh[I*X] == Cos[-X] == Cosh[-I*X]
- * Tan[X] == -I*Tanh[I*X] == -Tan[-X] == I*Tanh[-I*X]
- * ArcSin[X] == -I*ArcSinh[I*X] == -I*Log[I*X+Sqrt[1-X^2]]
- *
- *Note: Be very careful with ArcSinh and ArcSin. The above equations
- *are correct. Cannot assume X is real and must pay attention to branch
- *cuts.
- ***************************************************************** *)
-
- (* ****************************************************************
- *
- * Abs, Arg, Conjugate, Im, Re, Sign Identities
- *
- *For X!=0:
- *
- * Abs[X] == Sqrt[X*Conjugate[X]]
- * Arg[X] == -I*Log[X/Sqrt[X*Conjugate[X]]]
- * Im[X] == (X-Conjugate[X])/2
- * Re[X] == (X+Conjugate[X])/2
- * Sign[X] == X/Sqrt[X*Conjugate[X]]
- *
- *All other relations follow from these relations. Examples:
- *
- * Conjugate[X]=Abs[X]^2/X
- * Re[X]=X/2+X/(2*Sign[X]^2)
- * Im[X]=X*(1-E^(-2*I*Arg[X]))/2
- *
- *Etc.
- ***************************************************************** *)
-
- (* ****************************************************************
- *
- * Leaf Functions
- *
- ***************************************************************** *)
-
- LeafAbs[f_?NumberQ, _] := Abs[f]
-
- LeafAbs[_, True]:= ReImFail /; IsOK[Abs]
- LeafAbs[f_, _]:= Abs[f] /; IsOK[Abs]
-
- (* cartesian *)
- LeafAbs[f_, _]:= Sqrt[Re[f]^2+Im[f]^2] /; IsOK[{Re, Im}]
-
- (* polar: n/a *)
-
- (* other cases *)
- LeafAbs[f_, toplevel_]:=
- Switch[First[AllowedFunctions],
- Sign, f/Sign[f],
- Arg, f/E^(I*Arg[f]),
- Conjugate, Sqrt[f*Conjugate[f]],
- Im, Sqrt[2*f*Re[f]-f^2],
- Re, Sqrt[f^2-2*I*f*Im[f]],
- _, ReImFail]
-
-
- LeafArg[f_?NumberQ, _] := Arg[f]
-
- LeafArg[_, True]:= ReImFail /; IsOK[Arg]
- LeafArg[f_, _]:= Arg[f] /; IsOK[Arg]
-
- (* cartesian *)
- LeafArg[f_, _]:= ArcTan[Re[f],Im[f]] /; IsOK[{Re, Im}]
-
- (* polar: n/a *)
-
- (* other cases *)
- LeafArg[f_, toplevel_]:=
- Switch[First[AllowedFunctions],
- Abs, -I*Log[f/Abs[f]],
- Conjugate, -I*Log[f/Sqrt[f*Conjugate[f]]],
- Im, ArcTan[f-I*Im[f],Im[f]],
- Re, ArcTan[Re[f],-I*(f-Re[f])],
- Sign, -I*Log[Sign[f]],
- _, ReImFail]
-
-
- LeafConjugate[f_?NumberQ, _] := Conjugate[f]
-
- LeafConjugate[f_, _] := f /; !IsComplex[f]
-
- LeafConjugate[_, True]:= ReImFail /; IsOK[Conjugate]
- LeafConjugate[f_, _]:= Conjugate[f] /; IsOK[Conjugate]
-
- (* cartesian *)
- LeafConjugate[f_, _]:= Re[f]-I*Im[f] /; IsOK[{Re, Im}]
-
- (* polar *)
- LeafConjugate[f_, _]:= Abs[f] Exp[-I Arg[f]] /; IsOK[{Arg, Abs}]
-
- (* other cases *)
- LeafConjugate[f_, toplevel_]:=
- Switch[First[AllowedFunctions],
- Abs, Abs[f]^2/f,
- Arg, f*E^(-2*I*Arg[f]),
- Im, f-2*I*Im[f],
- Re, 2*Re[f]-f,
- Sign, f*Sign[f]^(-2),
- _, ReImFail]
-
-
- LeafReIm[f_?NumberQ, _] := {Re[f], Im[f]}
-
- LeafReIm[_, True]:= {ReImFail, ReImFail} /; IsOK[{Re, Im}]
- LeafReIm[f_, True]:= {ReImFail, -I*(f-Re[f])} /; IsOK[Re]
- LeafReIm[f_, True]:= {f-I*Im[f], ReImFail} /; IsOK[Im]
-
- (* cartesian *)
- LeafReIm[f_, _]:= {Re[f], Im[f]} /; IsOK[{Re, Im}]
-
- (* mixed mode, evaluate only once *)
- LeafReIm[f_, _]:= With[{re = Re[f]}, {re, -I*(f-re)}] /; IsOK[Re]
- LeafReIm[f_, _]:= With[{im = Im[f]}, {f-I*im, im}] /; IsOK[Im]
-
- (* polar *)
- LeafReIm[f_, _]:=
- With[{arg = Arg[f], abs = Abs[f]},
- {abs Cos[arg], abs Sin[arg]}
- ] /; IsOK[{Arg, Abs}]
-
- (* other cases *)
- LeafReIm[f_, toplevel_]:=
- Switch[First[AllowedFunctions],
- Abs, With[{abs = Abs[f]},
- {f/2+abs^2/(2*f), f/(2*I)-abs^2/(2*I*f)}],
- Arg, With[{arg = Arg[f]},
- {f/2+f*E^(-2*I*Arg[f])/2,
- f/(2*I)-f*E^(-2*I*Arg[f])/(2*I)}],
- Conjugate, With[{con = Conjugate[f]},
- {(f+con)/2, (f-con)/(2*I)}],
- Sign, With[{sign = Sign[f]},
- {f/2+f*sign^(-2)/2,
- f/(2*I)-f*sign^(-2)/(2*I)}],
- _, ReImFail]
-
-
- LeafSign[f_?NumberQ, _] := Sign[f]
-
- LeafSign[_, True]:= ReImFail /; IsOK[Sign]
- LeafSign[f_, _]:= Sign[f] /; IsOK[Sign]
-
- (* cartesian *)
- LeafSign[f_, _]:= (Re[f] + I Im[f])/Sqrt[Re[f]^2+Im[f]^2] /; IsOK[{Re, Im}]
-
- (* polar *)
- LeafSign[f_, _]:= f/Abs[f] /; IsOK[{Arg, Abs}]
-
- (* other cases *)
- LeafSign[f_, toplevel_]:=
- Switch[First[AllowedFunctions],
- Abs, f/Abs[f],
- Arg, Exp[I Arg[f]],
- Conjugate, f/Sqrt[f*Conjugate[f]],
- Re, f/Sqrt[2*f*Re[f]-f^2],
- Im, f/Sqrt[f^2-2*I*f*Im[f]],
- _, ReImFail]
-
-
- (* ****************************************************************
- *
- * Arg
- *
- ***************************************************************** *)
-
- ArgExpr[Abs[_], _] := 0
-
- ArgExpr[e_, toplevel_:False] := ArgRecursive[e, toplevel] /;
- IsRecursive[Arg] || ConstantQ[e]
-
- ArgExpr[e_, toplevel_:False] := LeafArg[e, toplevel]
-
- ArgRecursive[e_ ^ r_Rational, _] :=
- r Arg[e] /; r < 1 (* principal root *)
- ArgRecursive[e_ ^ (_Rational|_Integer), _] := 0 /; Arg[e] == 0 (* positive *)
-
- (* special exponentials *)
-
- (* internal code makes -1 < Im[c] <= 1 *)
- ArgRecursive[ Exp[c_Complex Pi], _ ] := Im[c] Pi
- ArgRecursive[ Exp[e_], _ ] := 0 /; Im[e] === 0 (* positive for real e *)
-
- ArgRecursive[e_, toplevel_] := LeafArg[e, toplevel]
-
- (* ****************************************************************
- *
- * Abs
- *
- ***************************************************************** *)
-
- AbsExpr[t:Abs[_], _] := t
- (* AbsExpr[Sign[_], _] := 1 : not true for 0 *)
-
- AbsExpr[e_, toplevel_:False] := AbsRecursive[e, toplevel] /;
- IsRecursive[Abs] || ConstantQ[e]
-
- AbsExpr[e_, toplevel_:False] := LeafAbs[e, toplevel]
-
- AbsRecursive[Literal[Conjugate[e_]], _] := Abs[e]
- AbsRecursive[e_Plus, toplevel_] := AbsPlus[e, toplevel]
- AbsRecursive[e_Times, toplevel_] := Abs /@ e
-
- AbsRecursive[g_ ^ n_Integer, _] :=
- Block[{x, y},
- {x,y} = ReImExpr[g];
- Which[ y === 0, If[EvenQ[n], g^n, Abs[g]^n],
- x === 0, If[Mod[n,4] === 0, g^n, Abs[g]^n],
- True, Abs[g]^n]
- ]
-
- AbsRecursive[g_ ^ h_, _] :=
- Block[{x, y},
- {x, y} = ReImExpr[h];
- Abs[g]^x E^(-y*Arg[g])
- ]
-
- AbsRecursive[e_, toplevel_] := LeafAbs[e, toplevel]
-
- AbsPlus[f_Plus, _] := Abs /@ f /; SameSignsQ[f] =!= ReImFail
- AbsPlus[e_, toplevel_] := LeafAbs[e, toplevel]
-
-
- (* ****************************************************************
- *
- * ConjugateExpr
- *
- ***************************************************************** *)
-
- (* commute with Conjugate -> real valued for real arg *)
-
- ConjugateFunctions={
- ArcCot, ArcCoth, ArcCsc, ArcCsch,
- ArcSec, ArcSech, ArcSinh, ArcTan,
- Cos, Cosh, Cot, Coth, Csc, Csch,
- Sec, Sech, Sin, Sinh, Tan, Tanh,
- Plus, Times, Sign
- }
-
- (* are real valued always: *)
-
- RealFunctions = { Abs, Arg, Im, Re }
-
- ConjugateExpr[Literal[Conjugate[f_]], _] := f
- ConjugateExpr[t:f_Symbol[_], _] := t /; MemberQ[RealFunctions,f]
-
- ConjugateExpr[e_, toplevel_:False] := ConjugateRecursive[e, toplevel] /;
- IsRecursive[Conjugate] || ConstantQ[e]
-
- ConjugateExpr[e_, toplevel_:False] := LeafConjugate[e,toplevel]
-
- ConjugateRecursive[t:f_Symbol[__], _] := Conjugate /@ t /;
- MemberQ[ConjugateFunctions,f]
-
- (* real powers *)
- ConjugateRecursive[e_?Positive ^ (r_Rational|r_Integer), _] := e^r
-
- ConjugateRecursive[e_, toplevel_] := LeafConjugate[e, toplevel]
-
-
- (* ****************************************************************
- *
- * SignExpr
- *
- ***************************************************************** *)
-
- SignExpr[t:Sign[_], _] := t
-
- SignExpr[e_, toplevel_:False] := SignRecursive[e, toplevel] /;
- IsRecursive[Sign] || ConstantQ[e]
-
- SignExpr[e_, toplevel_:False] := LeafSign[e, toplevel]
-
- SignRecursive[e_Times, _] := Sign /@ e
-
- SignRecursive[e_Plus, toplevel_] :=
- Block[{answer = SameSignsQ[e]},
- If[ answer =!= ReImFail, answer, LeafSign[e, toplevel] ]
- ]
-
-
- SignRecursive[g_ ^ n_Integer, _]:=
- Block[{x,y},
- {x,y}=ReImExpr[g];
- Which[ y === 0, If[EvenQ[n],1,Sign[g]],
- x === 0, Switch[Mod[n,4],
- 0, 1,
- 1, I*Sign[g],
- 2, -1,
- _, -I*Sign[g]],
- True, Sign[g] ^ n]
- ]
-
- (* number roots *)
-
- SignRecursive[g_?NumberQ ^ r_Rational, _]:= g^r/Abs[g]^r
-
- (* exponentials *)
-
- SignRecursive[ Exp[e_], _ ] := Exp[ I Im[e] ]
-
- (*
- SignRecursive[g_ ^ h_, _]:=
- Block[{x, y},
- {x,y}=ReImExpr[h];
- g^h / (Abs[g]^x*E^(-y*Arg[g]))
- ]
- *)
-
- SignRecursive[e_, toplevel_] := LeafSign[e, toplevel]
-
- SameSignsQ[f_]:=
- (* If all args have same sign (skipping 0), then return sign. *)
- Block[{answer = 0, sign, i = 1, n = Length[f]},
- While[i<=n,
- sign=Sign[f[[i]]];
- Which[ SameQ[answer,0], answer=sign,
- SameQ[sign,0], _,
- SameQ[answer,sign], _,
- True, answer=ReImFail; Break[] ];
- i=i+1];
- answer]
-
-
- SignRe[n_]:=
- (* Exact sign of real part of number. *)
- Block[{sign},
- sign=Sign[Re[n]];
- sign=Which[sign<0, -1,
- sign==0, 0,
- True, 1];
- sign]
-
- SignIm[n_]:=
- (* Exact sign of imaginary part of number. *)
- Block[{sign},
- sign=Sign[Im[n]];
- sign=Which[sign<0, -1,
- sign==0, 0,
- True, 1];
- sign]
-
- (* ****************************************************************
- *
- * Re and Im
- *
- ***************************************************************** *)
-
- ReImExpr[t:f_Symbol[_], top_:False] := {t, 0} /; MemberQ[RealFunctions,f]
-
- ReImExpr[e_, toplevel_:False] := ReImRecursive[e, toplevel] /;
- IsRecursive[Re] || IsRecursive[Im] || ConstantQ[e]
-
- ReImExpr[Literal[Conjugate[f_]], True] := {1, -1} ReImExpr[f, False]
-
- ReImExpr[e_, toplevel_:False] := LeafReIm[e,toplevel]
-
- ReImRecursive[t:f_Symbol[g_], _] := {t, 0} /;
- MemberQ[ConjugateFunctions, f] && Im[g] == 0
-
- ReImRecursive[ArcCos[g_], _] := ReImExpr[ Pi/2+I*Log[I*g+Sqrt[1-g^2]] ]
- ReImRecursive[ArcCosh[g_], _] := ReImExpr[ Log[g+(g+1)*Sqrt[(g-1)/(g+1)]] ]
- ReImRecursive[ArcCot[g_], _] := ReImExpr[ -I*Log[(1+I/g)/Sqrt[1+g^(-2)]] ]
- ReImRecursive[ArcCoth[g_], _] := ReImExpr[ Log[(1+1/g)/Sqrt[1-g^(-2)]] ]
- ReImRecursive[ArcCsc[g_], _] := ReImExpr[ -I*Log[I/g+Sqrt[1-g^(-2)]] ]
- ReImRecursive[ArcCsch[g_], _] := ReImExpr[ Log[1/g+Sqrt[1+g^(-2)]] ]
- ReImRecursive[ArcSec[g_], _] := ReImExpr[ ArcCos[1/g] ]
- ReImRecursive[ArcSech[g_], _] := ReImExpr[ Log[1/g+(1/g+1)*Sqrt[(1-g)/(1+g)]] ]
- ReImRecursive[ArcSin[g_], _] := ReImExpr[ -I*Log[I*g+Sqrt[1-g^2]] ]
- ReImRecursive[ArcSinh[g_], _] := ReImExpr[ Log[g+Sqrt[1+g^2]] ]
- ReImRecursive[ArcTan[g_], _] := ReImExpr[ -I*Log[(1+I*g)/Sqrt[1+g^2]] ]
- ReImRecursive[ArcTanh[g_], _] := ReImExpr[ Log[(1+g)/Sqrt[1-g^2]] ]
-
- ReImRecursive[Cos[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g]; {Cos[x]*Cosh[y],-Sin[x]*Sinh[y]} ]
- ReImRecursive[Cosh[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g]; {Cosh[x]*Cos[y],Sinh[x]*Sin[y]} ]
- ReImRecursive[Cot[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {-Sin[2*x], Sinh[2*y]}/(Cos[2*x]-Cosh[2*y]) ]
- ReImRecursive[Coth[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {-Sinh[2*x], Sin[2*y]}/(Cos[2*y]-Cosh[2*x]) ]
- ReImRecursive[Csc[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {-2*Sin[x]*Cosh[y], 2*Cos[x]*Sinh[y]}/(Cos[2*x]-Cosh[2*y]) ]
- ReImRecursive[Csch[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {-2*Cos[y]*Sinh[x], 2*Sin[y]*Cosh[x]}/(Cos[2*y]-Cosh[2*x]) ]
- ReImRecursive[Sec[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {2*Cos[x]*Cosh[y], 2*Sin[x]*Sinh[y]}/(Cos[2*x]+Cosh[2*y]) ]
- ReImRecursive[Sech[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {2*Cos[y]*Cosh[x], -2*Sin[y]*Sinh[x]}/(Cos[2*y]+Cosh[2*x]) ]
- ReImRecursive[Sin[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g]; {Sin[x]*Cosh[y],Cos[x]*Sinh[y]} ]
- ReImRecursive[Sinh[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g]; {Sinh[x]*Cos[y],Cosh[x]*Sin[y]} ]
- ReImRecursive[Tan[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {Sin[2*x], Sinh[2*y]}/(Cos[2*x]+Cosh[2*y]) ]
- ReImRecursive[Tanh[g_], _] :=
- Block[ {x, y}, {x, y} = ReImExpr[g];
- {Sinh[2*x], Sin[2*y]}/(Cos[2*y]+Cosh[2*x]) ]
-
- ReImRecursive[Literal[Conjugate[g_]], _] := {1, -1} ReImExpr[g]
-
- ReImRecursive[Log[g_], _] := ConstantLog[g] /; ConstantQ[g]
- ReImRecursive[Log[g_], _] := {RealLog[Abs[g]],Arg[g]}
-
- ReImRecursive[e_Plus, _] := ReImExpr /@ e (* thanks to listability of Plus *)
-
- ReImRecursive[f_Times, _] :=
- Block[{u,v,x,y,k},
- {u,v}=ReImExpr[f[[1]]];
- Do[ {x,y}=ReImExpr[f[[k]]];
- {u,v}={u*x-v*y,u*y+v*x},
- {k,2,Length[f]}];
- {u,v} ]
-
- ReImRecursive[g_ ^ n_Integer, _] :=
- Block[{x,y,answer},
- {x,y}=ReImExpr[g];
- answer=Which[SameQ[y,0], {x^n,0},
- SameQ[x,0], If[EvenQ[n],
- {((-1)^(n/2))*(y^n),0},
- {0,((-1)^((n-1)/2))*(y^n)}],
- True, Block[{sign,m,u,v},
- (* Note: N==0 should not occur. *)
- (* If N<0, use identity (X+I*Y)^N ==
- (X-I*Y)^(-N)/(X^2+Y^2)^(-N) *)
- sign=Sign[n];
- m=Abs[n];
- If[sign<0,y=-y];
- (* Apply Binomial Theorem for (X+I*Y)^N. *)
- u=Sum[((-1)^(i/2))*Binomial[m,i]*(x^(m-i))*(y^i),
- {i,0,m,2}];
- v=Sum[((-1)^((i-1)/2))*Binomial[m,i]*(x^(m-i))*(y^i),
- {i,1,m,2}];
- If[sign<0,
- Block[{den},
- den=Abs[g]^(2*m);
- u=u/den;
- v=v/den]];
- {u,v}]];
- answer]
-
- ReImRecursive[g_ ^ h_, _] :=
- Block[{abs,arg,x,y,theta,power},
- abs=Abs[g];
- arg=Arg[g];
- {x,y}=ReImExpr[h];
- theta=y*RealLog[abs]+x*arg;
- power=abs^x*E^(-y*arg);
- {power*Cos[theta],power*Sin[theta]}
- ]
-
- ReImRecursive[f_?NumberQ, _] := {Re[f], Im[f]}
-
- (* top level *)
-
- ReImRecursive[e_, True] := {e, 0} /; !IsComplex[e]
- ReImRecursive[ _, True] := {ReImFail, ReImFail}
-
- (* leaves *)
-
- ReImRecursive[e_, toplevel_] := LeafReIm[e,toplevel]
-
-
- ReImInternalTimes[{x1_,y1_},{x2_,y2_}]:=
- {x1*x2-y1*y2,x1*y2+x2*y1}
-
- ReImInternalDivide[{x1_,y1_},{x2_,y2_}]:=
- Block[{norm},
- norm=x2^2+y2^2;
- {(x1*x2+y1*y2)/norm,(x1*y2-x2*y1)/norm}]
-
- (* ****************************************************************
- *
- * Constant Functions
- *
- * These functions implement Log and inverse trigonometric functions
- *on constant args. These are slightly clever about paying attention
- *to branch cuts.
- ***************************************************************** *)
-
- ConstantSymbols={Catalan,Degree,E,EulerGamma,GoldenRatio,Pi}
-
- ConstantAbs[g_]:=
- Block[{x,y,answer},
- {x,y}=ReImExpr[g];
- answer=Which[SameQ[y,0], Switch[SignRe[N[x]],
- 1, x,
- 0, 0,
- _, Foil[-1,x]],
- SameQ[x,0], Switch[SignRe[N[y]],
- 1, y,
- 0, 0,
- _, Foil[-1,y]],
- True, Sqrt[x^2+y^2]];
- answer]
-
- ConstantArg[g_]:=
- Block[{x,y,answer},
- {x,y}=ReImExpr[g];
- answer=Which[SameQ[y,0], Switch[SignRe[N[x]],
- 1, 0,
- 0, 0,
- _, Pi],
- SameQ[x,0], Switch[SignRe[N[y]],
- 1, Pi/2,
- 0, 0,
- _, -Pi/2],
- True, ReImInternalTimes[
- {0,-1},
- ConstantLog[ReImInternalDivide[{x,y},ConstantAbs[g]]]]];
- answer]
-
- ConstantSign[g_]:=
- Block[{x,y,answer},
- {x,y}=ReImExpr[g];
- answer=Which[SameQ[y,0], SignRe[N[x]],
- SameQ[x,0], I*SignRe[N[y]],
- True, g/ConstantAbs[g]];
- answer]
-
- ConstantArcCot[g_]:=
- Block[{x,y,u,v,k,answer},
- {x,y}=ReImExpr[g];
- {u,v}=If[SameQ[y,0],
- {ArcCot[g],0},
- Block[{arccot,log},
- arccot=ArcCot[2*x/(-1+x^2+y^2)];
- log=Log[(x^2+(y+1)^2)/(x^2+(y-1)^2)];
- (* log=Log[(1+x^2+2*y+y^2)/(1+x^2-2*y+y^2)]; *)
- {3/4*Pi-1/2*arccot,-1/4*log}]];
- (* Place on proper branch. *)
- k=Round[Re[N[(ArcCot[g]-u)/(Pi/2)]]];
- u=u+k*Pi/2;
- answer={u,v};
- answer]
-
- ConstantArcTan[g_]:=
- Block[{x,y,u,v,k,answer},
- {x,y}=ReImExpr[g];
- {u,v}=If[SameQ[y,0],
- {ArcTan[g],0},
- Block[{arctan,log},
- arctan=ArcTan[2*x/(-1+x^2+y^2)];
- log=Log[(x^2+(y+1)^2)/(x^2+(y-1)^2)];
- (* log=Log[(1+x^2+2*y+y^2)/(1+x^2-2*y+y^2)]; *)
- {-1/2*arctan,1/4*log}]];
- (* Place on proper branch. *)
- k=Round[Re[N[(ArcTan[g]-u)/(Pi/2)]]];
- u=u+k*Pi/2;
- answer={u,v};
- answer]
-
- ConstantLog[g_]:=
- Block[{x,y,answer},
- {x,y}=ReImExpr[g];
- answer=Which[SameQ[y,0], If[N[x]>0,
- {Log[x],0},
- {Log[-x],Pi}],
- SameQ[x,0], If[N[y]>0,
- {Log[y],Pi/2},
- {Log[-y],-Pi/2}],
- True, Block[{norm,q,log,arctan},
- norm=x^2+y^2;
- q=y/x;
- log=Log[norm];
- arctan=ArcTan[q];
- {1/2*log,arctan}]];
- answer]
-
- (* ****************************************************************
- *
- * Real Functions
- *
- ***************************************************************** *)
-
- RealAbs[x_]:=
- Which[ConstantQ[x], If[Re[N[x]]>=0,x,Foil[-1,x]],
- SameQ[SyntacticSign[x],1], Abs[x],
- True, Abs[Foil[-1,x]]]
-
- RealLog[x_ ^ y_?NumberQ] := y Log[x] /; Im[y] == 0
- RealLog[x_] := Log[x]
-
- RealSign[x_]:=
- Which[ConstantQ[x], SignRe[N[x]],
- SameQ[SyntacticSign[x],1], Sign[x],
- True, -Sign[Foil[-1,x]]]
-
- SyntacticSign[expr_]:=
- (* If the first character of EXPR that will print is "-" then -1,
- if SameQ[EXPR,0] then 0,
- otherwise 1. *)
- Block[{answer},
- answer=Switch[Head[expr],
- Integer, Sign[expr],
- Rational, Sign[expr],
- Real, Sign[expr],
- Complex, If[SameQ[Re[expr],0],
- Sign[Im[expr]],
- Sign[Re[expr]]],
- Plus, SyntacticSign[expr[[1]]],
- Times, SyntacticSign[expr[[1]]],
- _, 1];
- answer]
-
- Foil[expr1_,expr2_]:=
- (* Distributive product. *)
- Block[{i,j,answer},
- answer=If[Not[SameQ[Head[expr1],Plus]],
- If[Not[SameQ[Head[expr2],Plus]],
- expr1*expr2,
- Sum[expr1*expr2[[j]],
- {j,Length[expr2]}]],
- If[Not[SameQ[Head[expr2],Plus]],
- Sum[expr1[[i]]*expr2,
- {i,Length[expr2]}],
- Sum[Sum[expr1[[i]]*expr2[[j]],
- {j,Length[expr2]}],
- {i,Length[expr1]}]]];
- answer]
-
- (* ****************************************************************
- *
- * Install our definitions of Abs, Arg, Re and Im
- *
- * Info about the C Routines:
- *(1) Abs -- does numbers.
- *(2) Arg -- does infinities, real and imaginary exact numbers, and floats.
- *(3) Conjugate -- does numbers.
- *(4) Im -- does numbers.
- *(5) Re -- does numbers.
- *(6) Sign -- does infinities, numbers, constant symbols, integer Power's
- *recursively, Plus recursively if all args have same sign, and
- *Times recursively.
- ***************************************************************** *)
-
- ConstantQ[s_Symbol] := MemberQ[ConstantSymbols, s]
- ConstantQ[_?NumberQ] := True
- ConstantQ[a_ + b_] := ConstantQ[a] && ConstantQ[b]
- ConstantQ[a_ * b_] := ConstantQ[a] && ConstantQ[b]
- ConstantQ[a_ ^ b_] := ConstantQ[a] && ConstantQ[b]
- ConstantQ[_] = False
-
- AllowedSix={Re, Im, Abs, Arg, Conjugate, Sign}
- AllowedFunctions=AllowedSix
- RecursiveFunctions={Sign} (* for top-level *)
-
- AssumedComplex={ _ } (* for top-level *)
-
- IsComplex[e_] := Or @@ (MatchQ[e, #]& /@ AssumedComplex)
-
- IsOK[f_List] := And @@ IsOK /@ f
- IsOK[f_] := MemberQ[AllowedFunctions, f]
-
- IsRecursive[f_] := MemberQ[RecursiveFunctions, f]
-
- PolarQ := IsOK[{Arg, Abs}]
- CartQ := IsOK[{Re, Im}]
-
- (* symbols ComplexExpand, TargetFunctions
- have been created by internal code *)
-
- Begin["`Private`"]
-
- Unprotect[ComplexExpand]
-
- Options[ComplexExpand] = {TargetFunctions -> AllowedSix}
-
- ComplexExpand::exf = "Value of option TargetFunctions -> `1` does not
- contain any of the allowed functions `2`."
-
- ComplexExpand[e_List, args___] := ComplexExpand[#, args]& /@ e
-
- ComplexExpand[expr_, opts___Rule] := ComplexExpand[expr, {}, opts]
-
- ComplexExpand[expr_, cvars_List, opts___Rule] :=
- Block[{AssumedComplex, AllowedFunctions, RecursiveFunctions,
- `x, `y, `funs},
- AssumedComplex = cvars;
- RecursiveFunctions = AllowedSix;
- funs = TargetFunctions /. {opts} /. Options[ComplexExpand];
- If[Head[funs] =!= List, funs = List[funs]];
- AllowedFunctions = Select[funs, MemberQ[AllowedSix, #]&];
- If[ Length[AllowedFunctions] < 1,
- Message[ComplexExpand::exf, funs, AllowedSix];
- Return[expr] ];
- Update /@ AllowedSix;
- {x, y} = ReImExpr[expr];
- If[ x === ReImFail || y === ReImFail, expr, x + I y]
- ]
-
- ComplexExpand[expr_, var_, opts___Rule] := ComplexExpand[expr, {var}, opts]
-
- ComplexExpand[args___] := $Failed /;
- Message[General::argct, ComplexExpand, Length[{args}]]
-
- Protect[ComplexExpand]
-
- End[]
-
- On[ General::shdw]
-
- EndPackage[]
-
- (* do not leave context on path *)
-
- $ContextPath = Drop[ $ContextPath,
- Position[$ContextPath, "System`ComplexExpand`"][[1]] ]
-
- Unprotect[$Packages]
- $Packages = Drop[$Packages,
- Position[$Packages, "System`ComplexExpand`"][[1]]]
- Protect[$Packages]
-
- Null
-
-