Message Boards Message Boards


Define a custom variation on Sqrt[-1] ?

Posted 2 years ago
6 Replies
3 Total Likes

I'm looking to define a variable or function (let's call it I'), similar to I , such that I'^n takes on user-defined values.

For conventional I :

Table[I^n, {n, 10}]
{I, -1, -I, 1, I, -1, -I, 1, I, -1}

But I would like to define an I' such that

Table[I'^n, {n, 10}]

yields {-1, -I, 1, I, -1, -I, 1, I, -1,-I} ("phase-shifted I") or perhaps {-1, -1, I, I, -1, -1, I, I, -1,-1} , or {-1,-2,I,2I,1,2,-I,-2I,-1,-2}, or any arbitrary list.

So whenever I'^n appears in a polynomial, each instance of I'^n is interpreted as the corresponding user-defined value.

Any ideas? Thanks in advance.

6 Replies


To do this you need tp look at UpValues:

ip /: ip^n_ := {1, 2, 3, 4}[[Mod[n, 4, 1]]]

This defines an UpValue of Ip that matches the pattern ip^n. Then I lookup the value in the sequence based on the Mod operation.



Posted 2 years ago

Very helpful Neil, thank you. I was unaware of UpValues.

Posted 2 years ago

Any thoughts on a workaround for ip, when not displayed as ip^1 ?

Ideally, ip would return 1 (or the first element in the list), not ip.


The simplest thing that comes to mind is to do a replace rule at the end. For some reason I can't get optional arguments to work with UpValues. You need to let MMA apply the UpValue rule before the simplest case of just ip. For example,

f = ip + 3* ip^2 + 4*ip^3 /. ip -> 1

will properly give 19 (given my strange definition for ip in the previous post)

Another approach is to define a rule that will do what you want:

In[1]:= myrule = ip^n___ : 1 :> {1, 2, 3, 4}[[Mod[n, 4, 1]]] 

In[2]:= f = ip + 3* ip^2 + 4*ip^3 /. myrule

Out[2]= 19

I tried this same approach with the UpValues but it failed to work (I am reporting it as a bug). I tried:

ip /: ip^n___:1 := {1, 2, 3, 4}[[Mod[n, 4, 1]]] 

This should have made the n optional with a default value of 1. Maybe someone knows another way to make this into a built-in rule. I'll report back what I get from Tech Support.



Posted 2 years ago

Yes, ReplaceAll ( /. ) would be my preferred method, but I am working with a very long polynomial, thousands or millions of terms long. Mathematica truncates or uses Short, so it only replaces some terms, not all. (this post)

Appreciate the input Neil.


Short is only a display feature -- it does not affect the values or expressions in any way. Also, I usually try not to display such long outputs because it’s slow (use a semicolon) but no content is lost by the truncated display.

If replaceAll does not get every term it’s because your replacement is adding new terms in. Mathematica will not “miss” any. (And I’ve done many huge expressions!). I suggest you use ReplaceAllRepeated (//.) this will repeat until nothing changes.

Here is an example:

In[1]:= myrule = ip^n___ : 1 :> {1, ip, -1, -ip}[[Mod[n, 4, 1]]];

In[4]:= f = (1 - ip)^2 * (2 + 3*ip + 5* ip^2)

Out[4]= (1 - ip)^2 (2 + 3 ip + 5 ip^2)

In[6]:= g = Expand[f]

Out[6]= 2 - ip + ip^2 - 7 ip^3 + 5 ip^4

In[7]:= g /. myrule

Out[7]= 8 - 4 ip

In[9]:= g //. myrule

Out[9]= 4

Note that Out[7] contains ip but only because my definition (myrule) has ip in it.

I read your other post and I agree with Daniel -- the answer from MMA is correct. Expand is a fast operation. The reason you see such slowdowns is that you are attempting to print ever increasingly complex expressions. Rerun your computation with a semicolon on the end of all the lines-- you will see a monumental speedup in your code. Besides you can't make sense of such a large output and it really brings the machine to its knees. To "explore" such long output look at chunks (myexpression[[1;;20]] to see the first 20 terms, etc.



Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract