Avoided zero devision in cube root approximation

Halley's method to get a better approximation is omitted, if it
would include a devision by zero (INFINITY/NaN is worse).

Change-Id: Ida09326e2b5892d7cb21bcb956631c289e5b56ba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Bernd Weimer 2013-07-18 14:32:20 +02:00 committed by The Qt Project
parent 4237faf580
commit cebac1ae2f
2 changed files with 15 additions and 9 deletions

View File

@ -608,14 +608,16 @@ struct BezierEase : public QEasingCurveFunction
sign = -1;
d = d * sign;
qreal t_i = _fast_cbrt(d);
qreal t = _fast_cbrt(d);
//one step of Halley's Method to get a better approximation
const qreal t_i_cubic = t_i * t_i * t_i;
qreal t = t_i * (t_i_cubic + d + d) / (t_i_cubic + t_i_cubic + d);
const qreal t_cubic = t * t * t;
const qreal f = t_cubic + t_cubic + d;
if (f != qreal(0.0))
t = t * (t_cubic + d + d) / f;
//another step
/*t_i = t;
/*qreal t_i = t;
t_i_cubic = pow(t_i, 3);
t = t_i * (t_i_cubic + d + d) / (t_i_cubic + t_i_cubic + d);*/

View File

@ -730,14 +730,16 @@ double static inline _fast_cbrt(double d)
void tst_QEasingCurve::testCbrtDouble()
{
const qreal errorBound = 0.0001;
const double errorBound = 0.0001;
for (int i = 0; i < 100000; i++) {
double d = double(i) / 1000.0;
double t = _fast_cbrt(d);
const double t_cubic = t * t * t;
t = t * (t_cubic + d + d) / (t_cubic + t_cubic + d);
const double f = t_cubic + t_cubic + d;
if (f != 0.0)
t = t * (t_cubic + d + d) / f;
double expected = pow(d, 1.0/3.0);
@ -754,14 +756,16 @@ void tst_QEasingCurve::testCbrtDouble()
void tst_QEasingCurve::testCbrtFloat()
{
const qreal errorBound = 0.0005;
const float errorBound = 0.0005;
for (int i = 1; i < 100000; i++) {
for (int i = 0; i < 100000; i++) {
float f = float(i) / 1000.0f;
float t = _fast_cbrt(f);
const float t_cubic = t * t * t;
t = t * (t_cubic + f + f) / (t_cubic + t_cubic + f);
const float fac = t_cubic + t_cubic + f;
if (fac != 0.0f)
t = t * (t_cubic + f + f) / fac;
float expected = pow(f, float(1.0/3.0));