Code comes from function eigen2x2 in opencv.
For a real matrix with following form:
solve for its eigenvalues:
double u = (a + c)*0.5;
double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
double l1 = u + v; //the 1st eigenvalue
double l2 = u - v; // the 2nd eigenvalue
Then solve for eigenvectors corresponding to l1
, which means solving for following system:
Code in eigen2x2
is as follows:
double x = b;
double y = l1 - a;
double e = fabs(x);
if (e + fabs(y) < 1e-4)
{
y = b;
x = l1 - c;
e = fabs(x);
if (e + fabs(y) < 1e-4)
{
e = 1. / (e + fabs(y) + FLT_EPSILON);
x *= e, y *= e;
}
}
double d = 1. / std::sqrt(x*x + y*y + DBL_EPSILON);
double x1 = x*d; //I moderately changed variable name for simplicity.
double x2 = y*d;
where x1
and x2
constitute eigenvector corresponding to l1
.
Question
To my understanding, when the matrix approximates zero matrix, following codes will be executed:
e = 1. / (e + fabs(y) + FLT_EPSILON);
x *= e, y *= e;
So what is the role it plays? And Is it permissible to kick out FLT_EPSILON
and subsequent DBL_EPSILON
?
Those exist to prevent division by zero (or by sub-epsilon values). Instead, you get a large float.
Assuming your values are modest in size it should have nearly no effect on the result; smaller that other rounding effects.
Removing it safely would require some subset of writing extensive unit tests, finding the documented cases why it was added originally, or extensive use in a wide variety live code where bad behaviour is safe (no money reputation or lives on the line) yet noticable. Unit tests need to cover a range of small, zero, denormalized values mixed with medium and large ones, including white box reverse engineering to produce said values at each intermediate step (to be safe).
I'd leave them in; they look harmless.