This solves a cubic equation of the form:
f(x) = ax^3 + bx^2 + cx + d
The result is returned in a dict containing the three solutions, root1, root2 and root3, consisting of a real part and an imaginary part.
Was transcoded from javascript from http://www.random-science-tools.com/maths/cubic.htm
KPV see also Cubic equation
proc cubic_root x { if {$x < 0} { return [expr {-pow(- $x,(1.0/3.0))}] } else { return [expr {pow($x,(1.0/3.0))}] } } proc solveCubic {a b c d} { # solve a cubic equation set rt {root1 {re 0 im 0} root2 {re 0 im 0} root3 {re 0 im 0}} set q [expr {double(3 * $a * $c - $b * $b) / (9 * $a * $a)}] set r [expr {double(9 * $a * $b * $c - 27 * $a * $a * $d - 2 * $b * $b * $b) / (54 * $a * $a * $a)}] set qqq_plus_rr [expr { $q * $q * $q + $r * $r}] if {$qqq_plus_rr < 0} { # All three roots real and unequal set j [expr {sqrt(- $q)}] set i [expr {$j * $j * $j}] set k [expr {acos(double($r) / $i)}] set M [expr {cos($k/3.0)}] set N [expr {sqrt(3) * sin($k/3.0)}] set b_over_3a [expr {$b/(3.0 * $a)}] dict set rt root1 re [expr {2 * $j * cos($k / 3.0) - $b_over_3a}] dict set rt root2 re [expr {- $j * ($M + $N) - $b_over_3a}] dict set rt root3 re [expr {$j * ($N - $M) - $b_over_3a}] } else { if {$qqq_plus_rr > 0} { set root_qqq_plus_rr [expr {sqrt($qqq_plus_rr)}] set s [cubic_root [expr {$r + $root_qqq_plus_rr}]] set t [cubic_root [expr {$r - $root_qqq_plus_rr}]] dict set rt root1 re [expr {$s + $t - $b / (3.0 * $a)}] dict set rt root2 re [expr {-0.5 * ($s + $t) - $b / (3.0 * $a)}] dict set rt root2 im [expr {sqrt(3) / 2.0 * ($s - $t)}] dict set rt root3 re [dict get $rt root2 re] dict set rt root3 im [expr {-[dict get $rt root2 im]}] } else { # ppp == rr so three real equal roots set res [expr {-[cubic_root [expr {double($d) / $a}]]}] dict set rt root1 re $res dict set rt root2 re $res dict set rt root3 re $res } } return $rt; }
# usage: solveCubic 28 5 -5 11 # -> root1 {re -0.8837041642689161 im 0} root2 {re 0.35256636784874373 im 0.5659101188251707} root3 {re 0.35256636784874373 im -0.5659101188251707}