I haven't really optimised the code that much so that its 'easier' to see whats going on and so that I can go over a couple of useful things. Like the a and b variables - if you have a cubic x^3+px+q=0 then a and b in the code can be set a=p,b=q rather than setting c=1,d=0,e=p,f=q. The reason for this is that the first stage of solving a cubic is reducing it to this form.
(init: i27=1/27;i3=1/3;twopi=acos(-1)*2😉
a=(3*c*e-sqr(d))/(3*sqr(c));
b=(2*sqr(d)*d-9*c*d*e+27*sqr(c)*f)/(27*sqr(c)*c);
tmp=sqr(b)+(4*a*sqr(a))*i27;
p3r=0.5*(-b+if(above(tmp,0),sqrt(tmp),0));
p3i=0.5*if(below(tmp,0),sqrt(tmp),0);
q3r=0.5*(b+if(above(tmp,0),sqrt(tmp),0));
q3i=0.5*if(below(tmp,0),sqrt(tmp),0);
pk=sqrt(sqr(p3r)+sqr(p3i));
qk=sqrt(sqr(q3r)+sqr(q3i));
p0=atan2(p3r,p3i);
q0=atan2(q3r,q3i);
pr1=pow(pk,i3)*cos(p0*twopi*i3);
pi1=pow(pk,i3)*sin(p0*twopi*i3);
pr2=pow(pk,i3)*cos(p0*2*twopi*i3);
pi2=pow(pk,i3)*sin(p0*2*twopi*i3);
pr3=pow(pk,i3)*cos(p0*3*twopi*i3);
pi3=pow(pk,i3)*sin(p0*3*twopi*i3);
qr1=pow(qk,i3)*cos(q0*twopi*i3);
qi1=pow(qk,i3)*sin(q0*twopi*i3);
qr2=pow(qk,i3)*cos(q0*2*twopi*i3);
qi2=pow(qk,i3)*sin(q0*2*twopi*i3);
qr3=pow(qk,i3)*cos(q0*3*twopi*i3);
qi3=pow(qk,i3)*sin(q0*3*twopi*i3);
t1=if(above(abs(pi1+qi1),0.01),10000,pr1+qr1);
t2=if(above(abs(pi2+qi2),0.01),10000,pr2+qr2);
t3=if(above(abs(pi3+qi3),0.01),10000,pr3+qr3);
t1=if(below(t1,0),10000,t1);
t2=if(below(t2,0),10000,t2);
t3=if(below(t3,0),10000,t3);
t=min(min(t1,t2),t3);
Unlike when solving a quadratic we can't just ignore complex results from the square roots and cube roots in the intermediary stages since they may end up forming a purely real root at the end. As a result this code also contains a method for finding a cube root of a complex number.
If you replace 3 with another number and increment n from 1 to that number then you can find any root (4th root, 5th root etc..) of any complex number, not just that but you get a different root for each value of n which means that you can calculate all of the roots and not just one (real root) like sqrt(x) or pow(x,1/n) does.
prn=pow(pk,1/3)*cos(p0*n*twopi/3);
pin=pow(pk,1/3)*sin(p0*n*twopi/3);
Don't expect a quartic solution anytime soon, in algebraic notation its about 4 times bigger than a cubic.. in code that may translate to even more. No torii or helices just yet. 🙁
Hopefully someone other than me will find this code useful, or at least interesting.