I want to introduce two variables (I call them EXt and EXtC, where "C" stands for complex conjugate) which would mimic the behavior of a phase of a complex number. For that, I use the following tags:

 EXt /: EXt EXtC := 1;
 EXtC /: EXtC EXt := 1;
 EXt /: EXt EXtC^n_ := EXtC^(n - 1);
 EXtC /: EXtC EXt^n_ := EXt^(n - 1);
 EXt /: EXt^(n_?Negative) := EXtC^(-n);
 EXtC /: EXtC^(n_?Negative) := EXt^(-n);
 EXt /: Conjugate[EXt] := EXtC;  
 EXtC /: Conjugate[EXtC] := EXt;

With that, I can simplify expressions like

EXt^2 EXt^2

i.e. when both of the variables have the same power (and this power is a number)

However, I am not able to simplify the expressions in which the powers are different. For example, I cannot simplify (i.e. make it equal to EXtC in this case),

EXt^2 EXtC^3 

even with the use of FullSimplify. I tried to introduce the following tag

EXt /: EXt^n_ EXtC^m_ := EXtC^(m - n)

but soon learned (for example, from here) that the upvalue mechanism can only scan one level deep, so I expectedly get the error message

TagSetDelayed::tagpos: Tag EXt in EXt^n_ EXtC^m_ is too deep for an assigned rule to be found. >>

Any ideas on how to circumvent this restriction and implement this property?


2 Answers 2


How about the following?:

Clear[ext, extc]
ext /: ext[n_] extc[m_] := extc[m - n]
ext /: ext[n_] ext[m_] := ext[m + n]
extc /: extc[n_] extc[m_] := extc[m + n]
ext /: Conjugate@ext[n_] := extc[n]
extc /: Conjugate@extc[n_] := ext[n]
extc[n_?Negative] := ext[-n]
ext[n_?Negative] := extc[-n]
extc[0] = 1;

ext /: Power[ext[m_], n_] := ext[m n]
extc /: Power[extc[m_], n_] := extc[m n]

$Pre = # &;
patt = Except[Clear | ClearAll | Remove];
ext /: (h : patt)[a___, ext, b___] := h[a, ext@1, b]
extc /: (h : patt)[a___, extc, b___] := h[a, extc@1, b]

Format@ext[n_] := EXt^n
Format@extc[n_] := EXtC^n


(* EXt *)

ext^2 extc^3
(* EXtC *)

ext extc^n // Conjugate
(* EXt^(-1 + n) *)
  • $\begingroup$ One fun thing you could always add is ext /: Power[ext, n] := ext[n] which would obviate the need for writing ext[n] for powers. Then all you'd need to do would be add some rules on ext so that when used in the appropriate context it expands to ext[1] and then you'd get out the behavior the OP wanted. You could even do something like ext /: (h: Power|Times|...)[a___, ext, b___]:>h[a, ext[1], b]) and then things would be easy $\endgroup$
    – b3m2a1
    Oct 23, 2018 at 17:25
  • $\begingroup$ @b3m2a1 Inspired by your comment, I recalled something interesting. Have a look. $\endgroup$
    – xzczd
    Oct 23, 2018 at 18:14
  • $\begingroup$ Edge case that isn't handled: ext[2]^2. Also, as usual, using Format has an evaluation leak, e.g., Hold[ext[1+1]]. $\endgroup$
    – Carl Woll
    Oct 23, 2018 at 18:48
  • $\begingroup$ @CarlWoll Thanks for pointing out. Fixed. $\endgroup$
    – xzczd
    Oct 23, 2018 at 19:03
  • $\begingroup$ Works perfectly! Thanks a lot! $\endgroup$
    – user43283
    Oct 23, 2018 at 19:47

Here's a variation of @xzczd's idea, using only a single symbol and adding formatting:

ext[n_] ext[m_] ^:= ext[n+m]
ext[n_]^m_ ^:= ext[n m]
Conjugate[ext[n_]] ^:= ext[-n]
ext[0] = 1;

MakeBoxes[ext[n_],StandardForm]:=Switch[Unevaluated @ n,
    0, "1",
    1, MakeBoxes[EXt],
    -1, MakeBoxes[EXtC],
    _Integer?Negative, With[{s=-n}, MakeBoxes[EXtC^s]],
    _, MakeBoxes[EXt^n]

For example:

EXt = ext[1]
EXtC = ext[-1]




EXt^2 EXtC^2
EXt^2 EXtC^3
EXt EXtC^n //Conjugate



EXt^(-1 + n)

  • $\begingroup$ Works perfectly! Thanks a lot! $\endgroup$
    – user43283
    Oct 23, 2018 at 19:47

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.