3

I currently have the following GLSL functions defined for raising a complex number to a power.

dvec2 p2 (dvec2 t) {return (dvec2 (cmul(t,t) ));}
dvec2 p3 (dvec2 t) {return (dvec2 (cmul(cmul(t,t),t) ));}
dvec2 p4 (dvec2 t) {return (dvec2 (cmul(cmul(cmul(t,t),t),t) ));}
dvec2 p5 (dvec2 t) {return (dvec2 (cmul(cmul(cmul(cmul(t,t),t),t),t) ));}
dvec2 p6 (dvec2 t) {return (dvec2 (cmul(cmul(cmul(cmul(cmul(t,t),t),t),t),t) ));}
dvec2 p7 (dvec2 t) {return (dvec2 (cmul(cmul(cmul(cmul(cmul(cmul(t,t),t),t),t),t),t) ));}
dvec2 p8 (dvec2 t) {return (dvec2 (cmul(cmul(cmul(cmul(cmul(cmul(cmul(t,t),t),t),t),t),t),t) ));}

I can use these in complex number formula like

dvec2 func (dvec2 z) { return (dvec2( cadd(csub(p4(z),cmul(c5,p2(z))),c4) ));

and it works fine.

Now I want to get rid of those p2,p3,p4,etc functions and write a more generalized power function. So I tried the following

dvec2 cpow (dvec2 c, int p) {
    for (int i = 0; i < p; i++) {
    c=cmul(c,c);
    }
    return c;
}

which I then call like

dvec2 func   (dvec2 z) { return (dvec2( cadd(csub(cpow(z,4),cmul(c5,cpow(z,2))),c4) )); }

But it gives different results. I can find a lot of complex power routines online but they all use log and trig calls which are not double precision which I need for this GLSL code.

Can any GLSL gurus spot why that simple cpow loop would not work?

Some1Else
  • 715
  • 11
  • 26
  • You don't need to be a "GLSL guru" to spot an off-by-one error. I don't remember complex arithmetic that well, but as just a sanity check, (X,0) to the power 0 ought to be (1, 0), right? And (X, 0) to the power 1 ought to be (X, 0), right? – Nicol Bolas Mar 02 '21 at 21:29
  • The code isn't raising the complex number to the loop variable though? It is just repeatedly multiplying by itself in the loop. – Some1Else Mar 02 '21 at 21:31
  • Are you saying that `cpow(something, 1)` does not mean "raise `something` to the power 1?" If not, what is it *supposed* to do, and why do you call it `cpow`? Indeed, you want to replace `p2(z)` with `cpow(z, 2)`, so *you* seem to think that `cpow` is supposed to raise numbers to the power you give it. – Nicol Bolas Mar 02 '21 at 21:33
  • Yes, that is correct, cpow(z,4) is supposed to raise z to the power of 4 by repeatedly multiplying z by itself in a loop. – Some1Else Mar 02 '21 at 21:41
  • If you want to raise X to the power 4, how many `*`s would you have to write in the code? Now compare that to how many times your loop would do it. – Nicol Bolas Mar 02 '21 at 21:45
  • OK, but changing p in the loop to p-1 still does not replicate the other function results. – Some1Else Mar 02 '21 at 21:53

1 Answers1

3

your conversion formula is wrong ... because you multiply by the subresult meaning you got squaring instead of multiplying ... You have to change your function to:

dvec2 cpow (dvec2 c, int p) 
    {
    dvec2 a=(1.0,0.0); // assuming a.x is real part
    for (int i = 1; i <= p; i++) a=cmul(a,c);
    return a;
    }

if you want something faster you can use power by squaring or even port to polar representation do power there and convert back to cartesian form of complex number. For more info see:

Look for the vec2 cpow(vec2 a,vec2 b) // a^b in the GLSL code for tetration fractal.

Spektre
  • 49,595
  • 11
  • 110
  • 380