diff --git a/src/compositor.c b/src/compositor.c index cb19f342..69ad60e4 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -545,7 +545,7 @@ static void weston_surface_update_transform(struct weston_surface *surface) { struct weston_matrix *matrix = &surface->transform.matrix; - struct weston_inverse_matrix *inverse = &surface->transform.inverse; + struct weston_matrix *inverse = &surface->transform.inverse; struct weston_transform *tform; if (!surface->transform.dirty) diff --git a/src/compositor.h b/src/compositor.h index 2064d676..53126651 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -230,7 +230,7 @@ struct weston_surface { /* derived state, set up by weston_surface_update_transform */ struct weston_matrix matrix; - struct weston_inverse_matrix inverse; + struct weston_matrix inverse; int enabled; } transform; diff --git a/src/matrix.c b/src/matrix.c index 46ce56a8..98ccf4ca 100644 --- a/src/matrix.c +++ b/src/matrix.c @@ -29,6 +29,7 @@ #include "matrix.h" + /* * Matrices are stored in column-major order, that is the array indices are: * 0 4 8 12 @@ -116,6 +117,16 @@ swap_rows(double *a, double *b) } } +static inline void +swap_unsigned(unsigned *a, unsigned *b) +{ + unsigned tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + static inline unsigned find_pivot(double *column, unsigned k) { @@ -133,16 +144,15 @@ find_pivot(double *column, unsigned k) * LU decomposition, forward and back substitution: Chapter 3. */ -WL_EXPORT int -weston_matrix_invert(struct weston_inverse_matrix *inverse, - const struct weston_matrix *matrix) +MATRIX_TEST_EXPORT inline int +matrix_invert(double *A, unsigned *p, const struct weston_matrix *matrix) { - double A[16]; - unsigned p[4] = { 0, 1, 2, 3 }; unsigned i, j, k; unsigned pivot; double pv; + for (i = 0; i < 4; ++i) + p[i] = i; for (i = 16; i--; ) A[i] = matrix->d[i]; @@ -150,9 +160,7 @@ weston_matrix_invert(struct weston_inverse_matrix *inverse, for (k = 0; k < 4; ++k) { pivot = find_pivot(&A[k * 4], k); if (pivot != k) { - unsigned tmp = p[k]; - p[k] = p[pivot]; - p[pivot] = tmp; + swap_unsigned(&p[k], &p[pivot]); swap_rows(&A[k], &A[pivot]); } @@ -168,30 +176,25 @@ weston_matrix_invert(struct weston_inverse_matrix *inverse, } } - memcpy(inverse->LU, A, sizeof(A)); - memcpy(inverse->p, p, sizeof(p)); return 0; } -WL_EXPORT void -weston_matrix_inverse_transform(struct weston_inverse_matrix *inverse, - struct weston_vector *v) +MATRIX_TEST_EXPORT inline void +inverse_transform(const double *LU, const unsigned *p, GLfloat *v) { /* Solve A * x = v, when we have P * A = L * U. * P * A * x = P * v => L * U * x = P * v * Let U * x = b, then L * b = P * v. */ - unsigned *p = inverse->p; - double *LU = inverse->LU; double b[4]; unsigned j; /* Forward substitution, column version, solves L * b = P * v */ /* The diagonal of L is all ones, and not explicitly stored. */ - b[0] = v->f[p[0]]; - b[1] = (double)v->f[p[1]] - b[0] * LU[1 + 0 * 4]; - b[2] = (double)v->f[p[2]] - b[0] * LU[2 + 0 * 4]; - b[3] = (double)v->f[p[3]] - b[0] * LU[3 + 0 * 4]; + b[0] = v[p[0]]; + b[1] = (double)v[p[1]] - b[0] * LU[1 + 0 * 4]; + b[2] = (double)v[p[2]] - b[0] * LU[2 + 0 * 4]; + b[3] = (double)v[p[3]] - b[0] * LU[3 + 0 * 4]; b[2] -= b[1] * LU[2 + 1 * 4]; b[3] -= b[1] * LU[3 + 1 * 4]; b[3] -= b[2] * LU[3 + 2 * 4]; @@ -225,5 +228,23 @@ weston_matrix_inverse_transform(struct weston_inverse_matrix *inverse, /* the result */ for (j = 0; j < 4; ++j) - v->f[j] = b[j]; + v[j] = b[j]; +} + +WL_EXPORT int +weston_matrix_invert(struct weston_matrix *inverse, + const struct weston_matrix *matrix) +{ + double LU[16]; /* column-major */ + unsigned perm[4]; /* permutation */ + unsigned c; + + if (matrix_invert(LU, perm, matrix) < 0) + return -1; + + weston_matrix_init(inverse); + for (c = 0; c < 4; ++c) + inverse_transform(LU, perm, &inverse->d[c * 4]); + + return 0; } diff --git a/src/matrix.h b/src/matrix.h index 21c1e785..04b179ff 100644 --- a/src/matrix.h +++ b/src/matrix.h @@ -28,11 +28,6 @@ struct weston_matrix { GLfloat d[16]; }; -struct weston_inverse_matrix { - double LU[16]; /* column-major */ - unsigned p[4]; /* permutation */ -}; - struct weston_vector { GLfloat f[4]; }; @@ -50,10 +45,20 @@ void weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v); int -weston_matrix_invert(struct weston_inverse_matrix *inverse, +weston_matrix_invert(struct weston_matrix *inverse, const struct weston_matrix *matrix); + +#ifdef UNIT_TEST +# define MATRIX_TEST_EXPORT WL_EXPORT + +int +matrix_invert(double *A, unsigned *p, const struct weston_matrix *matrix); + void -weston_matrix_inverse_transform(struct weston_inverse_matrix *inverse, - struct weston_vector *v); +inverse_transform(const double *LU, const unsigned *p, GLfloat *v); + +#else +# define MATRIX_TEST_EXPORT static +#endif #endif /* WESTON_MATRIX_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index e9d96acd..a1f361e1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,7 +6,7 @@ endif AM_CFLAGS = $(GCC_CFLAGS) -AM_CPPFLAGS = -I../src +AM_CPPFLAGS = -I../src -DUNIT_TEST matrix_test_SOURCES = \ matrix-test.c \ diff --git a/tests/matrix-test.c b/tests/matrix-test.c index 76d93ada..6fdab839 100644 --- a/tests/matrix-test.c +++ b/tests/matrix-test.c @@ -30,6 +30,11 @@ #include "matrix.h" +struct inverse_matrix { + double LU[16]; /* column-major */ + unsigned perm[4]; /* permutation */ +}; + static struct timespec begin_time; static void @@ -81,9 +86,9 @@ determinant(const struct weston_matrix *m) } static void -print_permutation_matrix(const struct weston_inverse_matrix *m) +print_permutation_matrix(const struct inverse_matrix *m) { - const unsigned *p = m->p; + const unsigned *p = m->perm; const char *row[4] = { "1 0 0 0\n", "0 1 0 0\n", @@ -95,7 +100,7 @@ print_permutation_matrix(const struct weston_inverse_matrix *m) } static void -print_LU_decomposition(const struct weston_inverse_matrix *m) +print_LU_decomposition(const struct inverse_matrix *m) { unsigned r, c; @@ -128,7 +133,7 @@ print_LU_decomposition(const struct weston_inverse_matrix *m) } static void -print_inverse_data_matrix(const struct weston_inverse_matrix *m) +print_inverse_data_matrix(const struct inverse_matrix *m) { unsigned r, c; @@ -140,7 +145,7 @@ print_inverse_data_matrix(const struct weston_inverse_matrix *m) printf("permutation: "); for (r = 0; r < 4; ++r) - printf(" %u", m->p[r]); + printf(" %u", m->perm[r]); printf("\n"); } @@ -175,22 +180,6 @@ randomize_matrix(struct weston_matrix *m) #endif } -static void -invert_matrix(struct weston_matrix *m) -{ - struct weston_inverse_matrix q; - unsigned i; - - if (weston_matrix_invert(&q, m) != 0) { - m->d[0] = NAN; - return; - } - - for (i = 0; i < 4; ++i) - weston_matrix_inverse_transform(&q, - (struct weston_vector *)&m->d[i * 4]); -} - /* Take a matrix, compute inverse, multiply together * and subtract the identity matrix to get the error matrix. * Return the largest absolute value from the error matrix. @@ -199,15 +188,14 @@ static double test_inverse(struct weston_matrix *m) { unsigned i; - struct weston_inverse_matrix q; + struct inverse_matrix q; double errsup = 0.0; - if (weston_matrix_invert(&q, m) != 0) + if (matrix_invert(q.LU, q.perm, m) != 0) return INFINITY; for (i = 0; i < 4; ++i) - weston_matrix_inverse_transform(&q, - (struct weston_vector *)&m->d[i * 4]); + inverse_transform(q.LU, q.perm, &m->d[i * 4]); m->d[0] -= 1.0f; m->d[5] -= 1.0f; @@ -309,21 +297,21 @@ static void __attribute__((noinline)) test_loop_speed_inversetransform(void) { struct weston_matrix m; - struct weston_inverse_matrix inv; + struct inverse_matrix inv; struct weston_vector v = { { 0.5, 0.5, 0.5, 1.0 } }; unsigned long count = 0; double t; - printf("\nRunning 3 s test on weston_matrix_inverse_transform()...\n"); + printf("\nRunning 3 s test on inverse_transform()...\n"); weston_matrix_init(&m); - weston_matrix_invert(&inv, &m); + matrix_invert(inv.LU, inv.perm, &m); running = 1; alarm(3); reset_timer(); while (running) { - weston_matrix_inverse_transform(&inv, &v); + inverse_transform(inv.LU, inv.perm, v.f); count++; } t = read_timer(); @@ -336,11 +324,11 @@ static void __attribute__((noinline)) test_loop_speed_invert(void) { struct weston_matrix m; - struct weston_inverse_matrix inv; + struct inverse_matrix inv; unsigned long count = 0; double t; - printf("\nRunning 3 s test on weston_matrix_invert()...\n"); + printf("\nRunning 3 s test on matrix_invert()...\n"); weston_matrix_init(&m); @@ -348,7 +336,7 @@ test_loop_speed_invert(void) alarm(3); reset_timer(); while (running) { - weston_matrix_invert(&inv, &m); + matrix_invert(inv.LU, inv.perm, &m); count++; } t = read_timer(); @@ -364,7 +352,7 @@ test_loop_speed_invert_explicit(void) unsigned long count = 0; double t; - printf("\nRunning 3 s test on computing the explicit inverse matrix...\n"); + printf("\nRunning 3 s test on weston_matrix_invert()...\n"); weston_matrix_init(&m); @@ -372,7 +360,7 @@ test_loop_speed_invert_explicit(void) alarm(3); reset_timer(); while (running) { - invert_matrix(&m); + weston_matrix_invert(&m, &m); count++; } t = read_timer(); @@ -385,7 +373,7 @@ int main(void) { struct sigaction ding; struct weston_matrix M; - struct weston_inverse_matrix Q; + struct inverse_matrix Q; int ret; double errsup; double det; @@ -402,7 +390,7 @@ int main(void) M.d[2] = 6.0; M.d[6] = 18.0; M.d[10] = -12; M.d[14] = 0.0; M.d[3] = 0.0; M.d[7] = 0.0; M.d[11] = 0.0; M.d[15] = 1.0; - ret = weston_matrix_invert(&Q, &M); + ret = matrix_invert(Q.LU, Q.perm, &M); printf("ret = %d\n", ret); printf("det = %g\n\n", determinant(&M));