From f5cc64ddd6c612362f3b5a9175f18f41bce53891 Mon Sep 17 00:00:00 2001 From: Stephan Lenor Date: Sat, 25 Mar 2023 06:06:38 +0100 Subject: [PATCH] Speed up matrix operations (unit-wise, no interface is touched) --- libgimpmath/gimpmatrix.c | 172 +++++++++++++++++++-------------------- libgimpmath/gimpmatrix.h | 12 +-- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/libgimpmath/gimpmatrix.c b/libgimpmath/gimpmatrix.c index d9d75aed5e..0f2caebd34 100644 --- a/libgimpmath/gimpmatrix.c +++ b/libgimpmath/gimpmatrix.c @@ -221,27 +221,26 @@ gimp_matrix2_identity (GimpMatrix2 *matrix) /** * gimp_matrix2_mult: - * @matrix1: The first input matrix. - * @matrix2: The second input matrix which will be overwritten by the result. + * @left: The first input matrix. + * @right: The second input matrix which will be overwritten by the result. * * Multiplies two matrices and puts the result into the second one. */ void -gimp_matrix2_mult (const GimpMatrix2 *matrix1, - GimpMatrix2 *matrix2) +gimp_matrix2_mult (const GimpMatrix2 *left, + GimpMatrix2 *right) { - GimpMatrix2 tmp; + gdouble r00 = right->coeff[0][0]; + gdouble r01 = right->coeff[0][1]; - tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] + - matrix1->coeff[0][1] * matrix2->coeff[1][0]); - tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] + - matrix1->coeff[0][1] * matrix2->coeff[1][1]); - tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] + - matrix1->coeff[1][1] * matrix2->coeff[1][0]); - tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] + - matrix1->coeff[1][1] * matrix2->coeff[1][1]); - - *matrix2 = tmp; + right->coeff[0][0] = (left->coeff[0][0] * r00 + + left->coeff[0][1] * right->coeff[1][0]); + right->coeff[0][1] = (left->coeff[0][0] * r01 + + left->coeff[0][1] * right->coeff[1][1]); + right->coeff[1][0] = (left->coeff[1][0] * r00 + + left->coeff[1][1] * right->coeff[1][0]); + right->coeff[1][1] = (left->coeff[1][0] * r01 + + left->coeff[1][1] * right->coeff[1][1]); } /** @@ -519,34 +518,36 @@ gimp_matrix3_transform_point (const GimpMatrix3 *matrix, /** * gimp_matrix3_mult: - * @matrix1: The first input matrix. - * @matrix2: The second input matrix which will be overwritten by the result. + * @left: The first input matrix. + * @right: The second input matrix which will be overwritten by the result. * * Multiplies two matrices and puts the result into the second one. */ void -gimp_matrix3_mult (const GimpMatrix3 *matrix1, - GimpMatrix3 *matrix2) +gimp_matrix3_mult (const GimpMatrix3 *left, + GimpMatrix3 *right) { - gint i, j; - GimpMatrix3 tmp; - gdouble t1, t2, t3; + gint i; + gdouble li0, li1, li2; + gdouble r00 = right->coeff[0][0]; + gdouble r01 = right->coeff[0][1]; + gdouble r02 = right->coeff[0][2]; + gdouble r10 = right->coeff[1][0]; + gdouble r11 = right->coeff[1][1]; + gdouble r12 = right->coeff[1][2]; + gdouble r20 = right->coeff[2][0]; + gdouble r21 = right->coeff[2][1]; + gdouble r22 = right->coeff[2][2]; for (i = 0; i < 3; i++) { - t1 = matrix1->coeff[i][0]; - t2 = matrix1->coeff[i][1]; - t3 = matrix1->coeff[i][2]; - - for (j = 0; j < 3; j++) - { - tmp.coeff[i][j] = t1 * matrix2->coeff[0][j]; - tmp.coeff[i][j] += t2 * matrix2->coeff[1][j]; - tmp.coeff[i][j] += t3 * matrix2->coeff[2][j]; - } + li0 = left->coeff[i][0]; + li1 = left->coeff[i][1]; + li2 = left->coeff[i][2]; + right->coeff[i][0] = li0 * r00 + li1 * r10 + li2 * r20; + right->coeff[i][1] = li0 * r01 + li1 * r11 + li2 * r21; + right->coeff[i][2] = li0 * r02 + li1 * r12 + li2 * r22; } - - *matrix2 = tmp; } /** @@ -718,19 +719,15 @@ gimp_matrix3_affine (GimpMatrix3 *matrix, gdouble gimp_matrix3_determinant (const GimpMatrix3 *matrix) { - gdouble determinant; - - determinant = (matrix->coeff[0][0] * - (matrix->coeff[1][1] * matrix->coeff[2][2] - - matrix->coeff[1][2] * matrix->coeff[2][1])); - determinant -= (matrix->coeff[1][0] * - (matrix->coeff[0][1] * matrix->coeff[2][2] - - matrix->coeff[0][2] * matrix->coeff[2][1])); - determinant += (matrix->coeff[2][0] * - (matrix->coeff[0][1] * matrix->coeff[1][2] - - matrix->coeff[0][2] * matrix->coeff[1][1])); - - return determinant; + gdouble m01 = matrix->coeff[0][1]; + gdouble m02 = matrix->coeff[0][2]; + gdouble m11 = matrix->coeff[1][1]; + gdouble m12 = matrix->coeff[1][2]; + gdouble m21 = matrix->coeff[2][1]; + gdouble m22 = matrix->coeff[2][2]; + return matrix->coeff[0][0] * (m11 * m22 - m12 * m21) + - matrix->coeff[1][0] * (m01 * m22 - m02 * m21) + + matrix->coeff[2][0] * (m01 * m12 - m02 * m11); } /** @@ -742,44 +739,40 @@ gimp_matrix3_determinant (const GimpMatrix3 *matrix) void gimp_matrix3_invert (GimpMatrix3 *matrix) { - GimpMatrix3 inv; - gdouble det; + gdouble det; + gdouble m00 = matrix->coeff[0][0]; + gdouble m01 = matrix->coeff[0][1]; + gdouble m02 = matrix->coeff[0][2]; + gdouble m10 = matrix->coeff[1][0]; + gdouble m11 = matrix->coeff[1][1]; + gdouble m12 = matrix->coeff[1][2]; + gdouble m20 = matrix->coeff[2][0]; + gdouble m21 = matrix->coeff[2][1]; + gdouble m22 = matrix->coeff[2][2]; - det = gimp_matrix3_determinant (matrix); + /* To avoid redundant access to the coefficients, inline the determinant + * formula. + * + * See: https://gitlab.gnome.org/GNOME/gimp/-/merge_requests/880#note_1727051 + */ + det = m00 * (m11 * m22 - m12 * m21) + - m10 * (m01 * m22 - m02 * m21) + + m20 * (m01 * m12 - m02 * m11); if (det == 0.0) return; det = 1.0 / det; - inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] - - matrix->coeff[1][2] * matrix->coeff[2][1]) * det; - - inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] - - matrix->coeff[1][2] * matrix->coeff[2][0]) * det; - - inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] - - matrix->coeff[1][1] * matrix->coeff[2][0]) * det; - - inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] - - matrix->coeff[0][2] * matrix->coeff[2][1]) * det; - - inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] - - matrix->coeff[0][2] * matrix->coeff[2][0]) * det; - - inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] - - matrix->coeff[0][1] * matrix->coeff[2][0]) * det; - - inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] - - matrix->coeff[0][2] * matrix->coeff[1][1]) * det; - - inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] - - matrix->coeff[0][2] * matrix->coeff[1][0]) * det; - - inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] - - matrix->coeff[0][1] * matrix->coeff[1][0]) * det; - - *matrix = inv; + matrix->coeff[0][0] = (m11 * m22 - m12 * m21) * det; + matrix->coeff[1][0] = - (m10 * m22 - m12 * m20) * det; + matrix->coeff[2][0] = (m10 * m21 - m11 * m20) * det; + matrix->coeff[0][1] = - (m01 * m22 - m02 * m21) * det; + matrix->coeff[1][1] = (m00 * m22 - m02 * m20) * det; + matrix->coeff[2][1] = - (m00 * m21 - m01 * m20) * det; + matrix->coeff[0][2] = (m01 * m12 - m02 * m11) * det; + matrix->coeff[1][2] = - (m00 * m12 - m02 * m10) * det; + matrix->coeff[2][2] = (m00 * m11 - m01 * m10) * det; } @@ -942,30 +935,37 @@ gimp_matrix4_identity (GimpMatrix4 *matrix) /** * gimp_matrix4_mult: - * @matrix1: The first input matrix. - * @matrix2: The second input matrix which will be overwritten by the result. + * @left: The first input matrix. + * @right: The second input matrix which will be overwritten by the result. * * Multiplies two matrices and puts the result into the second one. * * Since: 2.10.16 */ void -gimp_matrix4_mult (const GimpMatrix4 *matrix1, - GimpMatrix4 *matrix2) +gimp_matrix4_mult (const GimpMatrix4 *left, + GimpMatrix4 *right) { GimpMatrix4 result = {}; - gint i, j, k; + gint i, j; + gdouble li0, li1, li2, li3; for (i = 0; i < 4; i++) { + li0 = left->coeff[i][0]; + li1 = left->coeff[i][1]; + li2 = left->coeff[i][2]; + li3 = left->coeff[i][3]; for (j = 0; j < 4; j++) { - for (k = 0; k < 4; k++) - result.coeff[i][j] += matrix1->coeff[i][k] * matrix2->coeff[k][j]; + result.coeff[i][j] = li0 * right->coeff[0][j] + + li1 * right->coeff[1][j] + + li2 * right->coeff[2][j] + + li3 * right->coeff[3][j]; } } - *matrix2 = result; + *right = result; } /** diff --git a/libgimpmath/gimpmatrix.h b/libgimpmath/gimpmatrix.h index a71a218a94..d0cc6fca95 100644 --- a/libgimpmath/gimpmatrix.h +++ b/libgimpmath/gimpmatrix.h @@ -54,8 +54,8 @@ GParamSpec * gimp_param_spec_matrix2 (const gchar *name, void gimp_matrix2_identity (GimpMatrix2 *matrix); -void gimp_matrix2_mult (const GimpMatrix2 *matrix1, - GimpMatrix2 *matrix2); +void gimp_matrix2_mult (const GimpMatrix2 *left, + GimpMatrix2 *right); gdouble gimp_matrix2_determinant (const GimpMatrix2 *matrix); void gimp_matrix2_invert (GimpMatrix2 *matrix); @@ -90,8 +90,8 @@ GParamSpec * gimp_param_spec_matrix3 (const gchar *name, void gimp_matrix3_identity (GimpMatrix3 *matrix); -void gimp_matrix3_mult (const GimpMatrix3 *matrix1, - GimpMatrix3 *matrix2); +void gimp_matrix3_mult (const GimpMatrix3 *left, + GimpMatrix3 *right); void gimp_matrix3_translate (GimpMatrix3 *matrix, gdouble x, gdouble y); @@ -135,8 +135,8 @@ void gimp_matrix3_transform_point (const GimpMatrix3 *matrix, /*****************/ void gimp_matrix4_identity (GimpMatrix4 *matrix); -void gimp_matrix4_mult (const GimpMatrix4 *matrix1, - GimpMatrix4 *matrix2); +void gimp_matrix4_mult (const GimpMatrix4 *left, + GimpMatrix4 *right); void gimp_matrix4_to_deg (const GimpMatrix4 *matrix, gdouble *a,