from: http://www.csis.pace.edu/~bergin/polycalc/